美文网首页半栈工程师程序员
升级Android8.0带了的第一个SecurityExcept

升级Android8.0带了的第一个SecurityExcept

作者: 小追兵 | 来源:发表于2018-12-10 08:23 被阅读45次

    因为帮人维护一个APP,改APP在Google Play商店发布,最近Google Play的修改了规则。
    上传APP报错:

    Your app currently targets API level 25 and must target at least API level 26
    

    第一眼看到,就明白了,上传的APP的targetSdkVersion 必须升级到 26,也就是说Google强行要求Android 的开发API要升级到Android 8,不然不能在Google Play上线。

    好吧,升级吧。果然和想的一样,APP开启的时候就Crash了,错误如下(包名我隐去了):

     java.lang.SecurityException: Permission Denial: opening provider com.******.provider.SeafileProvider from ProcessRecord{6c7a7ea 18676:com.******.debug/u0a809} (pid=18676, uid=10809) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
            at android.os.Parcel.readException(Parcel.java:1967)
            at android.os.Parcel.readException(Parcel.java:1913)
            at android.content.IContentService$Stub$Proxy.notifyChange(IContentService.java:821)
            at android.content.ContentResolver.notifyChange(ContentResolver.java:2052)
            at android.content.ContentResolver.notifyChange(ContentResolver.java:2003)
            at android.content.ContentResolver.notifyChange(ContentResolver.java:1973)
            at com.******.provider.SeafileProvider$1.onAccountsUpdated(SeafileProvider.java:121)
            at android.accounts.AccountManager$19.run(AccountManager.java:2206)
            at android.os.Handler.handleCallback(Handler.java:789)
            at android.os.Handler.dispatchMessage(Handler.java:98)
            at android.os.Looper.loop(Looper.java:164)
            at android.app.ActivityThread.main(ActivityThread.java:6938)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
    
    

    只是第一个问题。
    来看下代码怎么实现的:

    ······
    public static final Uri NOTIFICATION_URI = DocumentsContract.buildRootsUri(Utils.AUTHORITY);
    ······
     private OnAccountsUpdateListener accountListener = new OnAccountsUpdateListener() {
            @Override
            public void onAccountsUpdated(android.accounts.Account[] accounts) {
                Context c = SeadroidApplication.getAppContext();
                c.getContentResolver().notifyChange(NOTIFICATION_URI, null);//这里发生了crash
            }
        };
    
    

    Utils中的包名是写死的。

     public static final String AUTHORITY = "com.sea***.***oid2";
    

    并且在build.gradle中做了如下配置

     buildTypes {
            debug {
                  ······
                 applicationIdSuffix ".debug"  // 在打debug 包时,将APP的包名后面加debug,修改了原有的包名。
                  ······
             }
    }
    

    不明所以的找了不少博客,文字,官网也说的简单一句,没有提供修改的方法。

    分析:

    翻阅资料,查看源码得知,Android 8.0 生成URI,在notifyChange 的时候,要有authorities, 这个就是应用的包名,因为上面代码的原因,导致在调试模式下的debug包的包名是com.sea***.***oid2.debug,而代码中写死的是com.sea***.***oid2,所以奔溃了。(Android 8.0 之前的版本没事)

    修复:

    将包名改为动态生成,不要用Utils中写死的代码

      public static final Uri NOTIFICATION_URI = DocumentsContract.buildRootsUri(BuildConfig.APPLICATION_ID);//传入真正的包名。
    

    问题解决。

    该问题最具参考价值的资料:

    1、https://blog.csdn.net/weixin_37077539/article/details/80067073

    相关文章

      网友评论

        本文标题:升级Android8.0带了的第一个SecurityExcept

        本文链接:https://www.haomeiwen.com/subject/aeykhqtx.html