Android 是否可以通过root使用adb授予包使用权统计信息的权限? 背景

Android 是否可以通过root使用adb授予包使用权统计信息的权限? 背景,android,adb,android-permissions,Android,Adb,Android Permissions,adb可用于授予各种权限,但此权限是特殊的,通过root将其用于此权限似乎无法正常工作: pm grant packageName android.permission.PACKAGE_USAGE_STATS 问题 操作系统说它被授权了,但应用程序本身无法检测到它 我发现了什么 请参阅应用程序的代码以将其签出: class MainActivity : AppCompatActivity() { companion object { @TargetApi(Build.V

adb可用于授予各种权限,但此权限是特殊的,通过root将其用于此权限似乎无法正常工作:

pm grant packageName android.permission.PACKAGE_USAGE_STATS
问题 操作系统说它被授权了,但应用程序本身无法检测到它

我发现了什么 请参阅应用程序的代码以将其签出:

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
    }
}
class MainActivity:AppCompatActivity(){
伴星{
@TargetApi(Build.VERSION\u code.LOLLIPOP)
@JvmStatic
权限(上下文:上下文):布尔值{
if(Build.VERSION.SDK\u INT
清单:

<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,我会得到一个奇怪的结果,操作系统说应用程序获得了权限,但应用程序无法检测到它


我应该怎么做才能在应用程序中使用root真正授予权限,并正确检测它?

使用adb shell pm grant[PACKAGE\u NAME]android.permission.PACKAGE\u USAGE\u STATS
在多台设备上对我有效

确保已将以下内容添加到
AndroidManifest

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
  tools:ignore="ProtectedPermissions"/>

正如Sagar所提到的,你也可以要求用户在设置应用程序中授予权限,这是谷歌推荐的方法


我不认为你可以通过这种方式向任何应用程序授予系统应用程序权限。@MehulMohan我希望有一种方法。也许用root?顺便说一句,我不认为它被归类为系统权限。我刚刚测试过它。即使操作系统的用户界面显示权限已被授予(使用意图),应用程序也无法检测到它。测试了各种检查权限是否被授予的方法,请访问:stackoverflow.com/q/28921136/878126。对于该应用程序,权限似乎没有被真正授予。@androiddeveloper请看以下要点:我能够使用adb和USAGestasManager返回的结果,并通过一个无根Samsun S8进行权限检查。我说的是从应用程序本身内部使用此命令(使用root)。请在那里试一试。我已对其进行了测试,但应用程序未能检测到它具有此权限。@androiddeveloper您是否尝试使用该库以root用户身份运行该命令?如果是这样,请登录
stderr
stdout
并粘贴结果。@androiddeveloper在运行Android 5.1的根HTC M8上进行了测试,结果正常。在以root用户身份运行
pm grant$packageName android.permission.PACKAGE\u USAGE\u STATS
后,权限检查返回true。
String packageName = context.getPackageName();
CommandResult result = Shell.SU.run("pm grant " + packageName + " android.permission.PACKAGE_USAGE_STATS");
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));