是否可以通过root使用adb来授予PACKAGE_USAGE_STATS的权限?
Is it possible using adb via root to grant the permission of PACKAGE_USAGE_STATS?
背景
adb可以用来授予各种权限,但是这个权限比较特殊,通过root来使用这个权限好像不太行:
pm grant packageName android.permission.PACKAGE_USAGE_STATS
问题
OS 表示已授权,但应用程序本身无法检测到它。
我发现了什么
查看应用程序代码以进行检查:
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 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>
布局文件
<?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>
问题
为什么如果我通过 PC 使用 adb,它工作正常,但是如果我在应用程序本身中使用 root,我得到一个奇怪的结果,OS 说应用程序获得了许可,但是应用程序无法检测到它?
我应该怎么做才能真正在应用程序中使用 root 授予权限,并正确检测到它?
使用 adb shell pm grant [PACKAGE_NAME] android.permission.PACKAGE_USAGE_STATS
在多个设备上对我有用。
确保将以下内容添加到 AndroidManifest
:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/>
我还能够使用 root 来授予权限。同样,应用程序必须在 AndroidManifest
.
中声明权限
您可以使用 AndroidShell 到 运行 作为 root 的命令。示例:
String packageName = context.getPackageName();
CommandResult result = Shell.SU.run("pm grant " + packageName + " android.permission.PACKAGE_USAGE_STATS");
如 Sagar 所述,您还可以要求用户在设置应用中授予权限,这是 Google 推荐的方法:
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
如果你遇到同样的问题,我找到了这个答案
并结合 Jared Rummler 的回答,它终于在有根设备上对我有用。
public void setMissingPermissions(String pkg){
try {
String[] Commands = new String[]{"su", "-c", "pm", "grant", pkg, "android.permission.PACKAGE_USAGE_STATS"};
Runtime.getRuntime().exec(Commands);
Commands = new String[]{"su", "-c", "appops", "set", pkg, "GET_USAGE_STATS", "allow"};
Runtime.getRuntime().exec(Commands);
}
catch(Exception e){
}
}
背景
adb可以用来授予各种权限,但是这个权限比较特殊,通过root来使用这个权限好像不太行:
pm grant packageName android.permission.PACKAGE_USAGE_STATS
问题
OS 表示已授权,但应用程序本身无法检测到它。
我发现了什么
查看应用程序代码以进行检查:
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 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>
布局文件
<?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>
问题
为什么如果我通过 PC 使用 adb,它工作正常,但是如果我在应用程序本身中使用 root,我得到一个奇怪的结果,OS 说应用程序获得了许可,但是应用程序无法检测到它?
我应该怎么做才能真正在应用程序中使用 root 授予权限,并正确检测到它?
使用 adb shell pm grant [PACKAGE_NAME] android.permission.PACKAGE_USAGE_STATS
在多个设备上对我有用。
确保将以下内容添加到 AndroidManifest
:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/>
我还能够使用 root 来授予权限。同样,应用程序必须在 AndroidManifest
.
您可以使用 AndroidShell 到 运行 作为 root 的命令。示例:
String packageName = context.getPackageName();
CommandResult result = Shell.SU.run("pm grant " + packageName + " android.permission.PACKAGE_USAGE_STATS");
如 Sagar 所述,您还可以要求用户在设置应用中授予权限,这是 Google 推荐的方法:
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
如果你遇到同样的问题,我找到了这个答案
public void setMissingPermissions(String pkg){
try {
String[] Commands = new String[]{"su", "-c", "pm", "grant", pkg, "android.permission.PACKAGE_USAGE_STATS"};
Runtime.getRuntime().exec(Commands);
Commands = new String[]{"su", "-c", "appops", "set", pkg, "GET_USAGE_STATS", "allow"};
Runtime.getRuntime().exec(Commands);
}
catch(Exception e){
}
}