Jelly Bean (api 16) 的 READ_LOGS 权限

Posted

技术标签:

【中文标题】Jelly Bean (api 16) 的 READ_LOGS 权限【英文标题】:READ_LOGS permission on Jelly Bean (api 16) 【发布时间】:2012-07-12 18:47:03 【问题描述】:

由于android Jelly Bean不支持logs reading permission(根据this google io 2012 video和this one too),我想知道root设备(或非root设备)是否可以绕过这个限制并且能够读取日志。

我该怎么做?我真的需要将应用程序设为系统应用程序,还是足够扎根?

【问题讨论】:

除非您拥有制造商密钥或root设备,否则不可能成为系统应用程序。 一切似乎仍然在模拟器上工作。有人用 JB 在真机上测试过 read_logs 吗? 那是因为我听不懂你的意思。对不起 。我真的不是故意让你失望。 您是要读取应用程序的日志,还是读取整个系统的日志? 整个系统日志。这就是为什么我说如果需要根(或作为系统应用程序),就这样吧。 【参考方案1】:

您可以通过在您的应用程序中执行 pm grant 命令来获得 root 设备上的权限。不过,您可能必须在此之后重新启动应用程序才能使更改生效:

String pname = getPackageName();
String[] CMDLINE_GRANTPERMS =  "su", "-c", null ;
if (getPackageManager().checkPermission(android.Manifest.permission.READ_LOGS, pname) != 0) 
    Log.d(TAG, "we do not have the READ_LOGS permission!");
    if (android.os.Build.VERSION.SDK_INT >= 16) 
        Log.d(TAG, "Working around JellyBeans 'feature'...");
        try 
            // format the commandline parameter
            CMDLINE_GRANTPERMS[2] = String.format("pm grant %s android.permission.READ_LOGS", pname);
            java.lang.Process p = Runtime.getRuntime().exec(CMDLINE_GRANTPERMS);
            int res = p.waitFor();
            Log.d(TAG, "exec returned: " + res);
            if (res != 0)
                throw new Exception("failed to become root");
         catch (Exception e) 
            Log.d(TAG, "exec(): " + e);
            Toast.makeText(context, "Failed to obtain READ_LOGS permission", Toast.LENGTH_LONG).show();
        
    
 else
    Log.d(TAG, "we have the READ_LOGS permission already!");

应该从您的 onCreate() 调用此代码。授予权限后,不再需要 root 权限。

P.S:超级用户应用程序上的 p.waitFor() 块会延迟您的应用程序启动并可能导致 ANR。

【讨论】:

似乎工作得很好(在带有 android 4.1.1 的 Galaxy s3 上测试)。只需要记住将 targetSdk 设置为 16 。太感谢了 。您还知道如何使用 root 启用 gps 吗?如果有,请在此回答:***.com/questions/11373234/… 这种方法需要 root。如果在没有su 的情况下运行pm grant ...,您将得到以下输出:Operation not allowed: java.lang.SecurityException: Neither user 100xx nor current process has android.permission.GRANT_REVOKE_PERMISSIONS. GRANT_REVOKE_PERMISSIONS 也是系统级别的,因此您不能在清单中要求它。 这段代码应该在 UI 线程之外执行...最好的方法是使用 AsyncTask 并在 PreExecute 上显示一个对话框,以便让用户知道应用程序正在执行任务【参考方案2】:

编辑:原来adb shell pm grant 只适用于模拟器。生产设备不允许shell 授予和撤销可选权限。


您不需要拥有根。对非系统应用程序启用 READ_LOGS 唯一需要做的就是安装 Android SDK。

基本上,你需要调用:

adb shell pm grant <pkg.name> android.permission.READ_LOGS

&lt;pkg.name&gt; 是您的应用程序包名称。这是可能的,因为 READ_LOGS 不仅是“系统”权限,还是“开发”权限(这个术语在 JB 中引入)。这实际上允许用户将此权限授予任何应用程序。无需root。

更多信息可通过此google groups thread 与来自 Dianne Hackborn 的 cmets 获得。

【讨论】:

有趣。当您调用此命令时,它会向最终用户显示任何内容吗?你在 JB 版本上测试过吗? 是的,我确实测试过了。它不会向最终用户显示任何内容。这大部分是开发人员的事情,不适合普通用户。 所以即使在根设备上也无法读取日志?肯定有办法的,不是吗? 仅限模拟器!我刚刚在我的 Nexus 6 上设置了它,但我没有 root! 使用此代码的应用会通过 Google Play 恶意垃圾邮件过滤器吗?【参考方案3】:

我通过使用 su 调用 logcat 并从标准输出读取数据,在有根设备上解决了这个问题

... .getRuntime().exec("su -c logcat -d");

【讨论】:

这是第一个答案的较短版本:***.com/a/12642918/878126,但它也应该可以工作。【参考方案4】:

还有另一种无需 root 权限即可访问所有日志的方法。您可以使用远程调试。看看开源rootless Logcat app。

【讨论】:

有趣。它在连接到 PC 时使用 adb 工具来启用远程访问。但是它有什么作用呢?应用程序本身是否连接到此端口,然后以某种方式从中读取?怎么样? 是的,该应用程序连接到手机上的本地 adb 守护程序并直接从那里读取日志。 它是怎么做到的? 通过网络连接到手机上的“localhost”。当您启用远程调试时,手机开始侦听 TCP 连接。现在你可以连接到它监听的端口,并使用ADB协议发送命令,包括读取日志的命令。 它在 MainActivity 中。实际的协议实现是 adblib 库。

以上是关于Jelly Bean (api 16) 的 READ_LOGS 权限的主要内容,如果未能解决你的问题,请参考以下文章

在 Jelly Bean 等旧设备上获取 Samsung KNOX api 版本

Android版本和API Level的对应关系

在 Jelly Bean 中使用 systrace 失败

相机在 android jelly bean 中崩溃

WifiManager.getScanResults() 未在 Android Jelly Bean 上提供 SSID

Android 4.3 Jelly Bean 中的打印支持