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
<pkg.name>
是您的应用程序包名称。这是可能的,因为 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 版本