So I have camera permission in manifest , Still when app goes to start camera it crashes .this happens beacuse user had denied the permission in permission manager for camera that comes with xiaomi devices
So the app Crashes , can someone help about how to handle this.
with the normal way of getting permisions , it does not give correct result
String permission = "android.permission.CAMERA";
int res = getContext().checkCallingOrSelfPermission(permission);
res is always 0(has Permission) for below 23 devices , if user has manually denied permission by going to permission manager then also
Revoking permissions on android devices below 23 is non-standard behavior and is afaik only possible through customized OS versions (like Cyanogen mod or in your case, the Xiaomi modified version). Users should be aware, that revoking permissions that way may cause error ins apps.
Prior to Android 6.0, you could reasonably assume that if your app is running at all, it has all the permissions it declares in the app manifest.
https://developer.android.com/training/permissions/best-practices.html#testing
Therefore I suggest you run your methods that require a certain permission with a try/catch. If the api lvl is below 23 and your method call fails, you know for sure if you have the permission or not.
Related
I have faced problems while getting Location data in OEM's Custom OS (Pre-Marshmallow i.e. Android Version < 6.0) with Permission Managers where the user can deny Location permission to the app.
Is there a way to detect that the permissions have been denied and also a way to ask for those permissions?
Code:
I use the following code taken from here with a target API level 23 (and minimum API level 18).
private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceNameTextView.setText(bluetoothDevice.getName());
}
}
};
On a button pressed event I call:
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery(); // was initialized successsfully
My AndroidManifest.xml contains:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
Devices:
Samsung Galaxy S III (API level 18)
Sony Xperia Z3 (API level 23)
Facts:
both devices are running the exact same code
device 1 can discover device 2 (and any other Bluetooth device)
device 2 cannot discover device 1 (or any other Bluetooth device)
both devices are discoverable
tested discoverability with the standard system dialog for pairing for both devices successfully
both devices were unpaired at all times (I don't want to pair)
No exceptions are thrown.
What is wrong?
Update 1:
Since API level 23 permissions may have to be requested at run time. Yvette pointed me to that, thank you! Unfortunately it didn't solve my problem.
What speaks against her theory is the following:
mBluetoothAdapter.startDiscovery() returns true, which means success (see here).
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity , Manifest.permission.BLUETOOTH_ADMIN);
if(permissionCheck == PackageManager.PERMISSION_GRANTED)
Log.i("info", "Permission granted!");
else
Log.i("info", "Permission not granted!");
Running this code with BLUETOOTH_ADMIN and BLUETOOTH returns both times:
Permission granted!
When doing some research, I found the following article from the official documentation regarding changes in Android 6.0 (API level 23).
To access the hardware identifiers of nearby external devices via
Bluetooth and Wi-Fi scans, your app must now have the
ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions:
- WifiManager.getScanResults()
- BluetoothDevice.ACTION_FOUND
- BluetoothLeScanner.startScan()
So, I was missing the permissions ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION all along. But just adding them in the AndroidManifest.xml file is not enough. You have to request those privileges at run time like Yvette suggested.
You can find here how you can do that or just use this piece of code I wrote to get the permissions needed for Bluetooth discovery.
final int CODE = 5; // app defined constant used for onRequestPermissionsResult
String[] permissionsToRequest =
{
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.BLUETOOTH,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
};
boolean allPermissionsGranted = true;
for(String permission : permissionsToRequest)
{
allPermissionsGranted = allPermissionsGranted && (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED);
}
if(!allPermissionsGranted)
{
ActivityCompat.requestPermissions(this, permissionsToRequest, CODE);
}
mBluetoothAdapter.startDiscovery();
This code is assuming that the user grants the permissions (for simplicity). If you want your app to behave differently when the permissions are not granted see "Handle the permissions request response" in this article.
Sounds like you're not managing runtime permissions for sdk 23 and higher. The phone with the sdk of 23 will either silently ignore any requests that require runtime permissions or crash.
Also see in the docs System Permissions.
If your app lists normal permissions in its manifest (that is, permissions that don't pose much risk to the user's privacy or the device's operation), the system automatically grants those permissions. If your app lists dangerous permissions in its manifest (that is, permissions that could potentially affect the user's privacy or the device's normal operation), the system asks the user to explicitly grant those permissions. The way Android makes the requests depends on the system version, and the system version targeted by your app:
If the device is running Android 6.0 (API level 23) or higher, and the app's targetSdkVersion is 23 or higher, the app requests permissions from the user at run-time. The user can revoke the permissions at any time, so the app needs to check whether it has the permissions every time it runs. For more information about requesting permissions in your app, see the Working with System Permissions training guide.
If the device is running Android 5.1 (API level 22) or lower, or the app's targetSdkVersion is 22 or lower, the system asks the user to grant the permissions when the user installs the app. If you add a new permission to an updated version of the app, the system asks the user to grant that permission when the user updates the app. Once the user installs the app, the only way they can revoke the permission is by uninstalling the app.
Often times a permission failure will result in a SecurityException being thrown back to the application. However, this is not guaranteed to occur everywhere. For example, the sendBroadcast(Intent) method checks permissions as data is being delivered to each receiver, after the method call has returned, so you will not receive an exception if there are permission failures. In almost all cases, however, a permission failure will be printed to the system log.
The permissions provided by the Android system can be found at Manifest.permission. Any application may also define and enforce its own permissions, so this is not a comprehensive list of all possible permissions.
A particular permission may be enforced at a number of places during
your program's operation:
At the time of a call into the system, to prevent an application from
executing certain functions.
When starting an activity, to prevent
applications from launching activities of other applications.
Both
sending and receiving broadcasts, to control who can receive your
broadcast or who can send a broadcast to you.
When accessing and
operating on a content provider.
Binding to or starting a service.
As for the app crashing:
Everything every Android Developer must know about new Android's Runtime Permission
Next question in your head right now. So will my application crash?
Such a kindness sent from god delivered through the Android team. When we call a function that requires a permission user revoked on application with targetSdkVersion less than 23, no any Exception will be thrown. Instead it will just simply do nothing. For the function that return value, it will return either null or 0 depends on the case.
But don't be too happy. Although application would not be crashed from calling a function. It may still can crash from what that application does next with those returned value.
Some more details in these answers Require dangerous permissions during installation When asking for runtime permission for location
After further research, i found that requestPermission only works on Android M. If i just include the permissions i needed in android manifest file, how does android ask user for the permission granted? For example, access fine location permission. I try including the requestPermission but never see the dialog.
Before Marshmallow, all the permissions are granted at installation time. That's why you don't see a dialog requesting permission on Lollipop and previous versions on runtime.
Check this out: Runtime Permissions. It only applies to Marshmallow and above.
I am trying to check for permissions being granted/revoked by user in Android Marshmallow. Unfortunately ContextCompat.checkSelfPermission() (which is a warpper around Context.checkCallingOrSelfPermission) seems to always return PackageManager.PERMISSION_GRANTED (0) if you have included that specific permission in your manifest regardless of the current state of the permission (e.g. if the user has revoked the permission). I also tried someContext.checkCallingOrSelfPermission(), but the result is the same.
Has anyone experienced this? I am using Android Marshmallow on nVidia Shield console (using nVidia's Beta program).
As it turns out, The targetSdkVersion in the manifest must be 23, mine was 22. If your target SDK is 23 (Android 6), all of the permissions (in your manifest) are disabled by default, whereas if your target SDK is 22 (Android 5.1) and your app is running on Android 6, all of the permissions are enabled by default when the user installs the app, and even if the user revokes the permissions later on, the mentioned API returns incorrect value (which is a bug in my opinion).
I have a (FOSS) app out there which can, among other features, enable and disable Wifi.
AndroidManifest.xml contains android.permission.CHANGE_WIFI_STATE, unit tests on the emulator pass and the feature works on a real device, a HTC Desire running 2.2.2.
The SDK versions are android:minSdkVersion="7" and android:targetSdkVersion="10", so I can't say about newer releases of Android.
I have received one single crash report:
java.lang.SecurityException: Permission Denial: writing com.android.providers.settings.SettingsProvider
uri content://settings/secure from pid=6191,
uid=10114 requires android.permission.WRITE_SETTINGS
Is android.permission.WRITE_SETTINGS possibly required on recent versions of Android? The reference says the permission exists since API 1, so I'd be surprised why it wasn't on older releases.
The user message is weird, it just says "lies", so I am unsure if I should just follow this report and add android.permission.WRITE_SETTINGS.
Any thoughts?
Cheers,
Torsten
That's weird, cause I needed to check exactly the same issue, so i just wrote a few lines of code doing exactly just that : enable/disable wifi and bluetooth.
My conclusion: you dont need the WRITE_SETTINGS permission to toggle the wifi, nor the bluetooth for that matter.
wifi = access_wifi_state + change_wifi_state
BT = bluetooth + bluetooth_admin
(with 4.2.2)
Check whether you were trying something else too, which may trigger the exception ?