In my code I have:
Settings.System.putInt(this.getContentResolver(), "vibrate_when_ringing", isVibrateWhenRinging ? 1 :0);
Using the following permission:
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
This was working fine from Jelly Bean (API 16) till Lollipop (API 22).
In Android M, I know that for using that permission I need to prompt the user to Settings.ACTION_MANAGE_WRITE_SETTINGS.
However, even with that permission turned on, I see the following error:
E/AndroidRuntime: java.lang.IllegalArgumentException: You cannot change private secure settings.
E/AndroidRuntime: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:165)
E/AndroidRuntime: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
E/AndroidRuntime: at android.content.ContentProviderProxy.call(ContentProviderNative.java:646)
Well... Am I missing something? With proper permissions we can change ringtones, do not disturb mode, etc. But it also looks like that with Android M we won't be able to change such a normal setting like "Vibrate when ringing". I hope I'm wrong.
You should call Settings.System.canWrite() to see that you can to write this setting.
If function returns false then the user can agree to allow your app to write to settings:
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getApplicationContext().getPackageName()));
startActivity(intent);
I am going to answer my own question. There is an issue opened to Google: https://code.google.com/p/android/issues/detail?id=194376.
Basically, they partially fixed vibrate_when_ringing and it works again on Android N (24). Unfortunately, it does not work on Android M (23). For the response on the issue, it does not seem that is going to be fixed.
You can see a full example repo here: https://github.com/ferrannp/VibrateWhenRinging
So, basically, your code needs to check if your on Android M and if you are, do not use that setting.
Related
I want to enable floating notification using Android Code.Normally users didn't know about the setting. so i need to enable this as default.
Bad news I'm afraid.
As you probably are aware, this requires the permission SYSTEM_ALERT_WINDOW.
Since Android M google has begun locking down this permission to reduce clutter. What is a little unusual about this permission is it requires the user to go to an actual settings screen The ordinary Android M permission flow does not work for this. To quote the API:
If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen
You use the Settings class to check if you already have the permission and when you don't, you need to explain and direct the user to the relevant settings screen via intent:
Intent i = new Intent();
i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + context.getPackageName()));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(i);
This should only ever affect devices running 23+ as older devices should get the permission automatically, but don't rely on checking SDK_INT, rely instead on canDrawOverlays, as there are exceptions for some pre-marshmallow devices
I was also facing same issue and need to enable it from settings but after adding permission in manifest file it worked perfectly.
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
Tested on version 9.
I struggled with that and found a way.
(In my case I'm using the OneSignal React-Native SDK)
The solution was to create a "category" (on the OneSignal console) that has the "urgent" importance :)
After that, when you send a push, you have to refer to the channel_id of this category.
Doc: https://documentation.onesignal.com/docs/android-notification-categories
I was wondering if it's possible for third-party apps to dynamically add permission to the system or not. According to this book, it is possible through the use of the public addPermission() API; however, I am getting a SecurityException that says "java.lang.SecurityException: You either need MANAGE_USERS or CREATE_USERS permission to: query users". I just wanted to make sure it is really because the system doesn't allow it and not because I messed up something in my code. If it is the case, dynamic addition of permissions is not allowed to third-party apps not signed with the system certificate, it would be great if somebody could explain the reasoning behind this choice.
Here is how I add the permission programmatically:
public void addDynamicPermission() {
PermissionInfo pi = new PermissionInfo();
pi.name = "com.somedomain.permission.MY_PERMISSION";
pi.labelRes = R.string.permission_label;
pi.protectionLevel = PermissionInfo.PROTECTION_DANGEROUS;
final PackageManager packageManager = getApplicationContext().getPackageManager();
packageManager.addPermission(pi);
}
This is what I have in my manifest file:
<permission-tree android:name="com.somedomain.permission" />
and this is the full java stack for the exception:
FATAL EXCEPTION: main
Process: com.example.myapp, PID: 11824
java.lang.SecurityException: You either need MANAGE_USERS or CREATE_USERS permission to: query users
at android.os.Parcel.readException(Parcel.java:1684)
at android.os.Parcel.readException(Parcel.java:1637)
at android.content.pm.IPackageManager$Stub$Proxy.addPermission(IPackageManager.java:2870)
at android.app.ApplicationPackageManager.addPermission(ApplicationPackageManager.java:535)
at com.example.myapp.MainActivity.addDynamicPermission(MainActivity.java:183)
at com.example.myapp.MainActivity$6.onClick(MainActivity.java:64)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Thanks a lot!
TL;DR: The book is outdated and versions of Android newer than Lollipop do indeed require MANAGE_USERS or CREATE_USERS, both of which have a protectionLevel of 3 (signatureOrSystem).
Longer answer:
A while back, in the KitKat era, I wrote some test code similar to yours and I recall it working fine. That was a few years ago. I just fired up that old app in my current Nougat (7.0) environment and ended up with the exact same exception that you are seeing. Curious, I reinstalled KitKat (4.4.4), Lollipop (5.1), and Marshmallow (6.0) instances and tried the app on each.
For 4.4.4 and 5.1, everything works fine. I verified this by running the code and then checking for the existence of the custom permission as follows:
% adb shell dumpsys package packagename | grep -i com.example
...
Permission [com.example.permission.TEST_PERMISSION] (79c4d6d):
sourcePackage=com.example.myapplication
perm=Permission{2c725da2 com.example.permission.TEST_PERMISSION}
...
However, on 6.0 and 7.0, I'm getting the security exception. A quick check of androidxref.com indicates that the exception is coming from either the getPrimaryUser or getUsers method in UserManagerService.
getPrimaryUsers doesn't exist in 4.4.4 or 5.1, and getUsers has always been protected with checkManageOrCreateUsersPermission. Therefore, I think its reasonable to assume that the addPermission chain was modified starting in 6.0 to get a list of users for some reason. So addPermission does not require MANAGE_USERS or CREATE_USERS, but a method it now calls does.
Whether or not this additional access control check is intended and the reasoning behind why, are questions I cannot answer.
I'm using Android Studio 1.3.2 on win7(64-bit) machine, developing application with kitkat (API level 23).
I'm trying to set brightness using seekbar control and have mentioned permission in manifest file as below
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
Now i'm getting the below exception
java.lang.SecurityException: com.sam.shmiandan.androidbrightness was not granted this permission: android.permission.WRITE_SETTINGS
How can I solve below error ?
**
Note : You are using API 23 level which is not Kitkat.
**
To use WRITE_SETTINGS, based on the docs:
Have the element in the manifest as normal..
Call Settings.System.canWrite() to see if you are eligible to write out settings.
If canWrite() returns false, start up the ACTION_MANAGE_WRITE_SETTINGS activity so the user can agree there to allow your app to actually write to settings.
IOW, writing to settings is now a double-opt-in (agree to install, agree separately in Settings to allow), akin to device admin APIs, accessibility services, etc.
Also note that I have not tried using these yet — this is based on research that I did yesterday on Android 6.0 changes
Reference : Can't get WRITE_SETTINGS permission
I want to block incoming calls for android 4.0 devices.I tried with ITelephony but its only working upto 2.2.But i found some apps in market its working in ICS too.Then i came to know that Modify phoine state has beed removed and only can apply to system apps but i tried with older android sdk there i kept modify phone state permission in manifest file it did not show me any error but after running the app its not working in ICS. Then i used below code
if (this.checkCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
but its not going inside the if clause in ICS even the permission is present in Manifest file, so what i suspect is it is not reading the MODIFY_PHONE_STATE permission from manifest file.
Please suggest me
Thank you in advance
I am using Device Policy Manager in my Android App and I have a problem with Honeycomb devices. When attempting to call resetPassword I get an exception thrown. This is not the case in Froyo or Gingerbread, as both of those work fine.
The error is:
java.lang.RuntimeException: Unable to start receiver Package.Name.Test: java.lang.SecurityException: Permission Denial: writing com.android.providers.settings.SettingsProvider uri content://settings/secure from pid=x, uid=y requires android.permission.WRITE_SETTINGS
My Android Code is as follows:
DevicePolicyManager mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
if ((mDPM.getActiveAdmins() != null) && (mDPM.isAdminActive(new ComponentName(context, DeviceAdmin.class)))) {
mDPM.resetPassword(extra, DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);
mDPM.lockNow();
} else {
Log.d(TAG, "Could not lock because device admin not enabled");
}
The problem occurs at:
mDPM.resetPassword(extra, DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);
My Device_Admin.xml is:
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<force-lock />
<wipe-data />
<reset-password />
</uses-policies>
</device-admin>
Like I said the device admin works great on Froyo and Gingerbread devices, although I do have some problems with users using different keyguards, an example is the Droid X and HTC Sense. This problem is with timing. When I call lockNow the device will turn off the screen but HTC Sense or MotoBlur will not actually lock the keyguard until the time that was set in Settings, Security, Lock Phone After.
Any help would be awesome! I just recently got a honeycomb tablet at I/O and haven't tested the app out on this device yet, but I see the errors on the market website with users with the Xoom running 3.0. Have not seen any 3.1 devices yet.
I struggled with this also. The solution is also listed on one of your links, but I'll mention it here also in case it helps someone else.
If the device is brand new (or factory reset) the code fails as you describe.
If the user enters a password using the settings menu just once, somehow the same code starts working and keeps on working.
A very weird bug indeed!!
On Android Honeycomb 3.0 platform, the DevicePolicyServiceManager is very different from Gingerbread, the whole flow of resetPassword() is:
DevicePolicyServiceManager.resetPassword() -->
LockPatternUtils.checkPasswordInHistory() -->
LockPatternUtils.passwordToHash() -->
LockPatternUtils.getSalt() -->
LockPatternUtils.putLong(SALT_KEY, salt) -->
Settings.Secure.putLong(SALT_KEY, salt)
Here you should know why WRITE_SETTINGS is required, it seems that this is Google's mistake, they did not put the LockPatternUtils.checkPasswordInHistory() method in Binder.clearCallingIndentity() block.
One more thing, even if you add WRITE_SETTINGS permission in your AndroidManifest.xml file, it will tell you that WRTITE_SECURE_SETTINGS permission is also required.
Hope Google can fix this issue ASAP.
P.S. It seems that this issue has been fixed on ICS platform, Google has removed the checkPasswordInHistory() from resetPassword() block. I do not think this is a good solutoin and i don't know why? Maybe they wanna release ICS as soon as possible?
I also faced this problem, what i can tell is if you didn't set the password manually even single time, the it will give force close asking for write_settings permission but if you try once by setting password manually from there on-wards it will work like charm.
I was looking at this problem (which is readily reproducible on 3.1 as well, btw), but it appears that you already figured it out, based upon the issue you filed. I just wanted to note that here in case anyone else tried to research the answer.