Issue
Background
adb can be used to grant various permissions, but this permission is special, and using it for this permission via root doesn't seem to work properly:
pm grant packageName android.permission.PACKAGE_USAGE_STATS
The problem
The OS says it's granted, but the app itself can't detect it.
What I've found
See code of the app to check it out:
class MainActivity : AppCompatActivity() {
companion object {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@JvmStatic
fun hasPermission(context: Context): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return false
val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
val mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName())
val granted = if (mode == AppOpsManager.MODE_DEFAULT) {
(context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) == PackageManager.PERMISSION_GRANTED)
} else {
(mode == AppOpsManager.MODE_ALLOWED)
}
return granted
// val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
// val granted = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.packageName) == AppOpsManager.MODE_ALLOWED
// return granted
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val granted = hasPermission(this@MainActivity)
Toast.makeText(this@MainActivity, "has permission:" + granted, Toast.LENGTH_SHORT).show()
}
button2.setOnClickListener {
startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
}
// extra code for granting the app the permission using root
}
}
manifest:
<manifest package="com.example.user.myapplication" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions"/>
<application
android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
layout file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="check the permission using below buttons before and after you grant it via root"/>
<Button
android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="check permission via code"/>
<Button
android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="go to settings screen"/>
</LinearLayout>
The question
How come if I use adb via PC, it works fine, yet if I use root within the app itself, I get a weird result, that the OS says the app got the permission, yet the app can't detect it ?
What should I do in order to truly grant the permission using root, within the app, and also detect it properly ?
Solution
Using adb shell pm grant [PACKAGE_NAME] android.permission.PACKAGE_USAGE_STATS worked for me on several devices.
Make sure you added the following to the AndroidManifest:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/>
I was also able to use root to grant the permission. Again, the app must declare the permission in the AndroidManifest.
You can use AndroidShell to run the command as root. Example:
String packageName = context.getPackageName();
CommandResult result = Shell.SU.run("pm grant " + packageName + " android.permission.PACKAGE_USAGE_STATS");
As mentioned by Sagar, you can also ask the user to grant the permission in the settings app, which is Google's recommended way to do this:
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
Answered By - Jared Rummler
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.