For a very limited number of users, my app is crashing with the following:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.cloud3squared.meteogram.pro/com.cloud3squared.meteogram.MeteogramWidgetConfigureActivity}:
java.lang.SecurityException: Permission denial: writing to settings requires android.permission.WRITE_SETTINGS
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2693)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2758)
at android.app.ActivityThread.access$900(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
Caused by: java.lang.SecurityException: Permission denial: writing to settings requires android.permission.WRITE_SETTINGS
at android.os.Parcel.readException(Parcel.java:1540)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:185)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
at android.content.ContentProviderProxy.call(ContentProviderNative.java:643)
at android.provider.Settings$NameValueCache.putStringForUser(Settings.java:1204)
at android.provider.Settings$System.putStringForUser(Settings.java:1505)
at android.provider.Settings$System.putIntForUser(Settings.java:1616)
at android.provider.Settings$System.putInt(Settings.java:1607)
at android.app.WallpaperManager$Globals.getDefaultWallpaperLocked(WallpaperManager.java:483)
at android.app.WallpaperManager$Globals.peekWallpaperBitmap(WallpaperManager.java:303)
at android.app.WallpaperManager.getDrawable(WallpaperManager.java:550)
at com.cloud3squared.meteogram.ax.c(Unknown Source)
at com.cloud3squared.meteogram.MeteogramWidgetConfigureActivity.a(Unknown Source)
at com.cloud3squared.meteogram.MeteogramWidgetConfigureActivity.c(Unknown Source)
at com.cloud3squared.meteogram.MeteogramWidgetConfigureActivity.onCreate(Unknown Source)
at android.app.Activity.performCreate(Activity.java:6288)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
... 10 more
Whilst a solution to the issue is given in the crash report (just add android.permission.WRITE_SETTINGS
to the Manifest), it troubles me that I need to, because my app doesn't knowingly write to settings, and the vast majority of users don't have any issue without the permission.
It is particularly troubling because the docs say that:
There are a couple of permissions that don't behave like normal and dangerous permissions. SYSTEM_ALERT_WINDOW and WRITE_SETTINGS are particularly sensitive, so most apps should not use them. If an app needs one of these permissions, it must declare the permission in the manifest, and send an intent requesting the user's authorization. The system responds to the intent by showing a detailed management screen to the user.
I want to do everything I can to avoid having this permission in my app, given that it's apparently "dangerous", and having to request this permission at runtime is enough to scare off even non-tin-hatted users. I really don't need to write to settings... I write to SharedPreferences
and that's about it.
So is there any way of avoiding this problem without requiring the permission?
EDIT to add code as per comment below (this function is called from my Activity
):
static String getAverageWallpaperColour(Context context) {
final WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
final Drawable wallpaperDrawable = wallpaperManager.getDrawable();
Bitmap bmp = ((BitmapDrawable)wallpaperDrawable).getBitmap();
int color = getAverageColour(bmp); // details of function not relevant... just reads the bmp to work out an average colour
return colorToHexString(color); // details of function not relevant... just converts into color to String in particular format
}