Android 10 (Q) ACCESS_BACKGROUND_LOCATION permission - java

I need the user to check and set permission to ACCESS_BACKGROUND_LOCATION ("Allow all the time") without the option to "Allow only while using the app". My GPS Tracking app needs to continue accessing location even when the application is minimised.
I have already permissions working for ACCESS_FINE_LOCATION for Android 9.
AndroidManifest.xml--------------------------------------------------->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
TrackingActivity.java (need to include ACCESS_BACKGROUND_LOCATION)---->
private void permissionCheck1() {
int permissionCheck1 = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck1 != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
} else {
grantedSetupGPSandMap();
}
}
I need the only permission option to be "Allow all the time" if possible. How do I set this up when checking and setting permissions?

For Android 10, if:
You omit ACCESS_BACKGROUND_LOCATION, and:
You use a foreground service with the android:foregroundServiceType="location" property set in the manifest, then:
The system will supply only the "Allow only while using the app" and "Deny" options to the user, in reference to the location permission.
I realize that's the exact opposite of what you asked for, but the point is, under this condition, "Allow only while using the app" effectively behaves like "Allow all the time", provided the aforementioned foreground service is running.
You will be able to receive location updates even when the app is offscreen. And the user does not have the option of only partially allowing location updates; they have to choose between fully allowing it, or fully denying it.
EDIT
This answer also assumes your targetSdkVersion is 29.

Related

How to check if "Allow management of all files" is allowed?

There are basically 3 types of storage permissions in the android app settings:
My app requires the highest permission, so I use <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> in manifest.xml.
Now I want to block the whole app, if the permission is not granted. So I tried using this code to check, if the highest permission is granted, but it always returns false.
if(ActivityCompat.checkSelfPermission(requireActivity(), Manifest.permission.MANAGE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
I also tried using WRITE_EXTERNAL_STORAGE, but it also returns true at the second option "Allow access to media only".
Conclusion
I am looking for a boolean function:
Returning true, if "Allow management of all files" is selected
Returning false, if "Allow access to media only" is selected
Returning false, if "Deny" is selected
Thank you.
Environment.isExternalStorageManager().

Android Geofence Background Limitations

How can I get instant transitions updates from geofence, when the app is running in the background?
Android background location limitations are preventing that from happening. Is there any way around it?
In Android 8: Apps in the background can only retrieve the user's location a few times per hour.
Before Android 10: Location permission is a single resource, and the application can be used everywhere with only one authorization (foreground and background).
In Android 10: The background location becomes an independent resource. In addition to the foreground request, the application must explicitly request this permission.
In Android 11: It is not possible to request background location permission at the same time as others, and the application must request it separately. In addition, requesting this permission will not prompt the user immediately like other permissions, but will take the user to the Settings page so that the user can update the permission level.
Before Android 10
Location permission only needs to be requested once, and apps in the foreground and background can be used. The user has only 2 options: authorize or not authorize.
#TargetApi(28)
fun Context.checkLocationPermissionAPI28(locationRequestCode : Int) {
if (!checkSinglePermission(Manifest.permission.ACCESS_FINE_LOCATION) ||
!checkSinglePermission(Manifest.permission.ACCESS_COARSE_LOCATION)) {
val permList = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
requestPermissions(permList, locationRequestCode)
}
}
private fun Context.checkSinglePermission(permission: String) : Boolean {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
Android 10
In this version, ACCESS_BACKGROUND_LOCATION is added, you can request this permission to obtain both the foreground and background permissions, like the following:
#TargetApi(29)
private fun Context.checkLocationPermissionAPI29(locationRequestCode : Int) {
if (checkSinglePermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
checkSinglePermission(Manifest.permission.ACCESS_COARSE_LOCATION) &&
checkSinglePermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) return
val permList = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION)
requestPermissions(permList, locationRequestCode)
}
private fun Context.checkSinglePermission(permission: String) : Boolean {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
Similarly, if the foreground permission (ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION) is requested, the Android operating system will automatically add the background permission (ACCESS_BACKGROUND_LOCATION) to the request. It is similar to the declaration of , whether ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION is declared, ACCESS_BACKGROUND_LOCATION will be added during the installation process.
The user now has three options: background (anytime), foreground (only during APP use), and reject.
Android 11
In addition to the above, developers also need to add some other steps.
There are two scenarios here. The first one is when only requesting permission from the front desk. In this case, we usually use ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION. However, the pop-up window for requesting authorization is slightly different from the previous one. In Android 11, Google added an option Only this time.
Please note that even if ACCESS_BACKGROUND_LOCATION is added to the list of permissions to request, the system will ignore it.
The second situation is that the application also needs background permission. For this, you must prepare your own dialog box and use a clear message to explain the use of the background location.
When the user agrees, he will be directed to the application settings page, where he can choose the permission level he wants to grant.
#TargetApi(30)
private fun Context.checkBackgroundLocationPermissionAPI30(backgroundLocationRequestCode: Int) {
if (checkSinglePermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) return
AlertDialog.Builder(this)
.setTitle(R.string.background_location_permission_title)
.setMessage(R.string.background_location_permission_message)
.setPositiveButton(R.string.yes) { _,_ ->
// this request will take user to Application's Setting page
requestPermissions(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), backgroundLocationRequestCode)
}
.setNegativeButton(R.string.no) { dialog,_ ->
dialog.dismiss()
}
.create()
.show()
}
In Android 11, we have 4 permission levels for location information.
When the user selects Allow all the time, the APP has the permission to use location information in the background.

How to create folder in external storage android? I have tried all the other answers on stackoverflow but none is working for me. [duplicate]

I'm trying to write code to send an SMS from an Android app, but when I try to send the SMS it sends me back the error:
09-17 18:37:29.974 12847-12847/**.**.****E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: **.**.****, PID: 12847
java.lang.SecurityException: Sending SMS message: uid 10092 does not have android.permission.SEND_SMS.
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at com.android.internal.telephony.ISms$Stub$Proxy.sendTextForSubscriber(ISms.java:768)
at android.telephony.SmsManager.sendTextMessageInternal(SmsManager.java:310)
at android.telephony.SmsManager.sendTextMessage(SmsManager.java:293)
at **.**.****.MainActivity$3.onClick(MainActivity.java:70)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
I checked but I have the permissions in the manifest, as follows:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-feature android:name="android.hardware.telephony"
android:required="true"/>
<application
android:exported="true"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
I searched the internet but all the errors were about the <uses-permission/> syntax, could you help me please?
(the following is extracted from a blog post of mine about this)
The big reason for not getting your permission nowadays is because
your project has a targetSdkVersion of 23 or higher, and the permission
that you are requesting is "dangerous". In Android 6.0, this includes:
ACCEPT_HANDOVER
ACCESS_BACKGROUND_LOCATION
ACCESS_MEDIA_LOCATION
ACTIVITY_RECOGNITION
ANSWER_PHONE_CALLS
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
ADD_VOICEMAIL
BODY_SENSORS
CALL_PHONE
CAMERA
GET_ACCOUNTS
PROCESS_OUTGOING_CALLS
READ_CALENDAR
READ_CALL_LOG
READ_CELL_BROADCASTS
READ_CONTACTS
READ_EXTERNAL_STORAGE
READ_PHONE_STATE
READ_SMS
RECEIVE_MMS
RECEIVE_SMS
RECEIVE_WAP_PUSH
RECORD_AUDIO
SEND_SMS
USE_SIP
WRITE_CALENDAR
WRITE_CALL_LOG
WRITE_CONTACTS
WRITE_EXTERNAL_STORAGE
For these permissions, not only does your targetSdkVersion 23+ app
need to have the <uses-permission> element(s), but you also have
to ask for those permissions at runtime from the user on Android 6.0+
devices, using methods like checkSelfPermission() and
requestPermissions().
As a temporary workaround, drop your targetSdkVersion below 23.
However, eventually, you will have some reason to want your
targetSdkVersion to be 23 or higher. At that time, you will need
to adjust your app to use the new runtime permission system.
The Android documentation has
a page dedicated to this topic.
Above API level 23 you will be given programmatically pragmatically like:
private static final int PERMISSION_REQUEST_CODE = 1;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.SEND_SMS)
== PackageManager.PERMISSION_DENIED) {
Log.d("permission", "permission denied to SEND_SMS - requesting it");
String[] permissions = {Manifest.permission.SEND_SMS};
requestPermissions(permissions, PERMISSION_REQUEST_CODE);
}
}
Please go through the link below,
https://developer.android.com/guide/topics/permissions/overview.html
Some samples are also available there to get start with the permissions.
To make android more secure now developers has to mention permission in manifest as well as they should have to ask user as well in run time to get the work done. They are permission categorized in dangerous permission section which are mention below
CALENDAR
READ_CALENDAR
WRITE_CALENDAR
CAMERA
CAMERA
CONTACTS
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE
RECORD_AUDIO
PHONE
READ_PHONE_STATE
READ_PHONE_NUMBERS
CALL_PHONE
ANSWER_PHONE_CALLS (must request at runtime)
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
ANSWER_PHONE_CALLS
SENSORS
BODY_SENSORS
SMS
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
request permission pragmatically (after API 23)
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.SEND_SMS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Ask for permision
ActivityCompat.requestPermissions(this,new String[] { Manifest.permission.SEND_SMS}, 1);
}
else {
// Permission has already been granted
}
"If the app has the permission, the method checkSelfPermission() returns PERMISSION_GRANTED, and the app can proceed with the operation.
If the app does not have the permission, the method returns PERMISSION_DENIED, and the app has to explicitly ask the user for permission. You need to prompt the user for that permission, as shown in the above code. Calling requestPermissions() brings up a standard Android dialog, which you cannot customize."
If you are using sdk 23 or higher then you must check run time permissions.
when you declare permisson in Manifest and it's not work means you are performing Task in MarshMallow and for MarshMallow you have set Permisson at RunTime.
like this way
ActivityCompat.requestPermissions();
If you are using Android version "23" or "23+", then app will show you errors when you are trying to access anything which requires user's permission. You have to ask for permissions at run-time even if you have declared those permissions in Android manifest.
Check this: https://developer.android.com/training/permissions/requesting.html
But if you have created your whole application and don't want to change at every place then a little cheat will be sufficient.
Go to "Build.gradle" file and change the target Sdk version to less than 23, like 22, 21.
Along with CommonsWare's answer,
There is a Security Setting (I checked on CM13) to set SMS Message Limit. If you set this to "None", OS will popup a Dialog for every SMS, even after obtaining SMS_SEND permission in the runtime. Best thing is to set this to maximum.
If the maximum is not enough, there are ways to increases the maximum rate on a rooted device.
I added this to my MainActivity, that resolve my problem
int MY_PERMISSIONS_REQUEST_READ_CONTACTS=0;
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
I hope the solution to write to external storage will be useful too
public boolean checkPermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Timber.tag(LOG_TAG).e("Permission error. You have permission");
return true;
} else {
Timber.tag(LOG_TAG).e("Permission error. You have asked for permission");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else {
// for a stuff below api level 23
Timber.tag(LOG_TAG).e("Permission error. You already have the permission");
return true;
}
}
So i had to create an app to send and receive messages but the send action crashed whenever i clicked on send even though the permission was granted . I had requested runtime permissions and allowed them, still i faced a crash that the process doesnt have the requested permission to send SMS .
I had checked the granted permissions from :
adb shell dumpsys package <package-name>
The order of my request for permissions was
RECEIVE_SMS
SEND_SMS
I reverted the order of request and it works fine . This was tested with a complete new app(uninstall-> install -> test). The answer may seem weird but just give it a shot .
(If it works in the shown way in a certain order, then Android might have a bug!!)

Permission is not a changeable permission type

Background: I was trying out the new Tiles and TileService and decided to recreate the USB Tethering tile from CyanogenMod. I used reflection to access Connectivity manager's methods.
Problem: One Such method is the isTetheringSupported() which causes java.lang.SecurityException: You either need MANAGE_USERS or CREATE_USERS permission to: query user
So I added the permissions to the manifest but every time I use pm grant it returns "Permission is not a changeable permission type"
According to this I should not get this error when signed with the debug key.
Question: How do I get those permissions?
UPDATE:
Via Xposed it is possible to hook into the PackageManger and remove the below check and then do pm grant... to successfully grant whatever permission. If someone sees this and needs help to do so comment below I'll help you out.
OLD ANSWER
This code in the source
boolean isDevelopment =
((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0);
doesn't check if your app is in development mode. It checks if the permission you are requesting has the protectionLevel attribute (set in manifest) set to development.
And the permission you are trying to get seems not to have any elements declared in the manifest that could pass this check:
if (!isNormal && !isDangerous && !isDevelopment) {
throw new SecurityException("Permission " + bp.name
+ " is not a changeable permission type");
}
Just stumbled upon this with another permission. Seems there's sadly no way to get it.

Some phones need permission READ_CONTACTS to read from contact picker

I have a HTC ONE M7 (GPE 4.2.2) and HTC EVO 3D (4.0.3) HTC Sense 3.6
HTC ONE does not need:
<uses-permission android:name="android.permission.READ_CONTACTS" />
on HTC EVO 3D however, following code throws an exception:
public static String getPhoneNumberFromIntent(Context context, Intent data) throws SecurityException {
String contactNumber = null;
final Uri contactUri = data.getData();
if (contactUri != null) {
Cursor c = null;
try {
// Read contact number from contacts provider
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
c = context.getContentResolver().query(contactUri, projection, null, null, null);
if (c != null && c.moveToFirst()) {
int maxNumberLength = context.getResources().getInteger(R.integer.max_phone_number_cze);
contactNumber = cutOnlyLastPhoneNumberDigits(c.getString(0), maxNumberLength);
}
} finally {
if (c != null) {
c.close();
}
}
}
return contactNumber;
}
-
java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.HtcContactsProvider2
uri content://com.android.contacts/data/2158 from pid=14938, uid=10125 requires android.permission.READ_CONTACTS
I have read that appliaction is granted required permissions when user selects contact by hand. However on some phones this does not work (HTC EVO 3D).
Why is this happending? Is there a workaround such is ability to ask for this permission at runtime ?
HTC ONE does not need: <uses-permission android:name="android.permission.READ_CONTACTS" /> on HTC EVO 3D however, following code throws an exception
If the Uri you are getting is coming from ACTION_PICK or ACTION_GET_CONTENT, whether or not you have temporary read permissions for that contact will vary by contact-picking app.
I have read that appliaction is granted required permissions when user selects contact by hand. However on some phones this does not work (HTC EVO 3D).
There is no requirement that all contact-picking apps grant you temporary read access to the contact. In fact, I am unclear if third-party contact managers would have the ability to grant you temporary read access to the contact.
Is there a workaround such is ability to ask for this permission at runtime ?
You cannot change your mix of candidate permissions at runtime.
Your choices are:
Always ask for READ_CONTACTS in the manifest. This ensures you can do what you want, at the cost of requesting another permission, one that prospective users might not like.
Handle the SecurityException and simply do without the data that you are trying to query(), if that data is not essential.
Write a separate app with the READ_CONTACTS permission that can serve as a "plugin" for your app, securely retrieving contact data on behalf of your main app. You can then route users who get the SecurityException to install your contacts plugin. This is tricky to write without introducing security flaws, so I would encourage you to use either of the other options.
You can't ask permission at run-time. You can only add a level API to your permission for example:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
It means that the permission is no needed if api is 19 or higher.

Categories