Android权限checkSelfPermission不起作用

时间:2019-09-12 23:28:05

标签: android android-permissions

在我的应用程序的AndroidManifest.xml中,我将目标API指定为26:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.javasrv"
android:minSdkVersion="23"
android:targetSdkVersion="26"
android:versionCode="6"
android:versionName="1.0.0">
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

但是,当我在Android x86 8.1上运行该应用程序并通过系统菜单禁用存储访问权限时,它会说:“此应用程序是为较旧版本的Android设计的。拒绝权限可能导致其不再按预期运行。”

怎么可能?

我在运行时权限检查方面也遇到了问题:即使我在系统设置中将其禁用,它始终认为已授予访问权限:

if (ContextCompat.checkSelfPermission(LoaderActivity.this, permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    Toast.makeText(LoaderActivity.this, "PERMISSION_DENIED", Toast.LENGTH_SHORT).show();
    Log.d("*** Loader::onCreate ***", "PERMISSION_DENIED");
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission.WRITE_EXTERNAL_STORAGE)) {
    } else {
    }
    ActivityCompat.requestPermissions(this, new String[]{permission.WRITE_EXTERNAL_STORAGE}, 0);
} else {
    Toast.makeText(LoaderActivity.this, "PERMISSION_GRANTED", Toast.LENGTH_SHORT).show();
    Log.d("*** Loader::onCreate ***", "PERMISSION_GRANTED");
}

同样,目前还不清楚。有什么想法吗?

编辑:我正在使用android api v26和android支持库v23。

编译脚本:

file=javasrv.apk

# export CLASSPATH=/opt/android-sdk/platforms/android-26/android.jar:/opt/android-sdk/extras/android/support-library/23.2.1/android-support-v4.jar
#
rm -f com/javasrv/*.class
javac -cp $CLASSPATH -source 1.8 -target 1.8 com/javasrv/*.java
#dx --dex --output classes.dex com/javasrv/*.class
dx --dex --output classes.dex com/javasrv/*.class android/support/v4/app/*.class android/support/v4/content/*.class

#aapt package -f -m -F "$file" -M AndroidManifest.xml -S res -I "$CLASSPATH"
#aapt add "$file" classes.dex
rm -rf build && mkdir build
find ./res -type f  | grep -vE '\.sw.$' | xargs -I{} aapt2 compile -o build "{}" --no-crunch
aapt2 link -R build/* --manifest AndroidManifest.xml $(echo "$CLASSPATH" | tr -d '\n' | xargs -d':' -L1 -I{} echo " -I {} ") -o "$file" --auto-add-overlay
zip -uj "$file" classes.dex

zipalign -f 4 "$file" "$file.aligned"
mv -f "$file.aligned" "$file"
apksigner sign --ks-pass pass:pwd --ks javasrv.keystore "$file"

Edit2 :这可能是另一个与aapt2有关的问题。如果我在AndroidManifest.xml中指定 compileSdkVersion ,则会引发错误:

AndroidManifest.xml:2: error: attribute android:compileSdkVersion not found.
error: failed processing manifest.

我只是通过从清单中删除 compileSdkVersion 来忽略它。我现在想知道我是否应该...

Edit3 :与该权限检查的日志有关。我只能访问/data/log.txt。但这应该足够了。不?

08-16 19:24:39.236 18965 18965 E /system/bin/webview_zygote32: Failed to make and chown /acct/uid_99182: Permission denied
08-16 19:24:39.236 18965 18965 E Zygote  : createProcessGroup(99182, 0) failed: Permission denied
08-16 19:24:39.239  2219  2900 I am_proc_start: [0,18965,99182,com.android.chrome:sandboxed_process0,webview_service,com.javasrv/org.chromium.content.app.SandboxedProcessService0]
08-16 19:24:39.239  2219  2900 I ActivityManager: Start proc 18965:com.android.chrome:sandboxed_process0/u0i182 for webview_service com.javasrv/org.chromium.content.app.SandboxedProcessService0
08-16 19:24:39.255 18965 18965 W /system/bin/webview_zygote32: Unexpected CPU variant for X86 using defaults: x86_64
08-16 19:24:39.256 18931 18931 I auditd  : type=1400 audit(0.0:3392): avc: denied { read } for comm="com.javasrv" name="vmstat" dev="proc" ino=4026531858 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
08-16 19:24:39.256 18931 18931 I com.javasrv: type=1400 audit(0.0:3392): avc: denied { read } for name="vmstat" dev="proc" ino=4026531858 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
08-16 19:24:39.256 18931 18931 I auditd  : type=1400 audit(0.0:3393): avc: denied { open } for comm="com.javasrv" path="/proc/vmstat" dev="proc" ino=4026531858 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
08-16 19:24:39.256 18931 18931 I com.javasrv: type=1400 audit(0.0:3393): avc: denied { open } for path="/proc/vmstat" dev="proc" ino=4026531858 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
08-16 19:24:39.263 18959 18959 W zygote  : Unexpected CPU variant for X86 using defaults: x86_64
08-16 19:24:39.281  1022  1022 I auditd  : type=1400 audit(0.0:3395): avc: denied { read } for comm="loop0" path="/mnt/android-8.1-r2/system.img" dev="vda2" ino=1422631 scontext=u:r:kernel:s0 tcontext=u:object_r:unlabeled:s0 tclass=file permissive=1
08-16 19:24:39.281  1022  1022 I loop0   : type=1400 audit(0.0:3395): avc: denied { read } for path="/mnt/android-8.1-r2/system.img" dev="vda2" ino=1422631 scontext=u:r:kernel:s0 tcontext=u:object_r:unlabeled:s0 tclass=file permissive=1
08-16 19:24:39.289  2671  2691 D SubscriptionController: [getPhoneId] asked for default subId=-1
08-16 19:24:39.290  2671  2691 D SubscriptionController: [getSubId]- invalid slotIndex=-1
08-16 19:24:39.336 18931 18931 D *** Loader::onCreate ***: PERMISSION_GRANTED
08-16 19:24:39.336 18931 18931 D *** getListFiles ***: [W]/sdcard/Download/FDroid.apk
08-16 19:24:39.336 18931 18931 D *** getListFiles ***: [W]/sdcard/Download/javasrv.apk

编辑4: 这是我向其请求权限的活动的开始方式:

Intent intent = new Intent(this, LoaderActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the activity to be cleared before the activity is started. That is, the activity becomes the new root of an otherwise empty task, and any old activities are finished. This can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

修改5: 天啊!我只是反编译了生成的apk,并注意到我的 android:versionCode android:versionName 以某种方式变成了 platformbuildversioncode platformbuildversionname 分别。真是疯了!我不知道这是怎么发生的。 已添加:嗯。它与aapt2的版本有关。我使用的是构建工具28.0.3。在将其更改为26.0.2时,它的行为没有这种疯狂。

编辑6: 由于aapt2的错误,我回到了aapt。至少它不会过多地破坏清单:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:minSdkVersion="23" android:targetSdkVersion="26" package="com.javasrv" platformBuildVersionCode="26" platformBuildVersionName="8.0.0">

由于某种原因,它删除了我的应用自定义版本号和版本代码。但这至少不应该影响应用程序的工作。 我仍然在努力的是,由于与在软件包 android 中找不到 compileSdkVersion 的错误相同,我无法指定compileSdkVersion。

编辑7:。这是我从最终apk(使用aapt2 v26构建的)中反编译的清单的头部:

<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:minSdkVersion="23" android:targetSdkVersion="26" package="com.javasrv">
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

因此唯一缺少的是 compileSdkVersion 。我仍然不知道如何使aapt2将该值放入清单中。但是我测试了apk,并且具有运行时权限的bug仍然存在。很奇怪。

编辑8: 安装了最新的aapt2版本。从这里:https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/3.6.0-alpha11-5720371/aapt2-3.6.0-alpha11-5720371-linux.jar 还是一样-它不会插入 compileSdkVersion

编辑9: 实际上,很明显,我正在使用的命名空间中没有 compiledSdkVersion 。我也无法在文档的任何地方找到它:https://developer.android.com/guide/topics/manifest/uses-sdk-element 在我看来,我根本不应该使用它-实际上,我看不到任何目的。如果我可以指定最低版本和目标版本,那么到底谁在乎我编译我的应用程序的哪个版本?因此,该错误应该在其他地方。

修改10: 更新了最新的Android支持库24.1.1版本。对于运行时权限的检查,斯蒂尔还是不走运。

编辑11: 试图调用requestPermissions,即使它错误地将其检测为GRANTED并出现运行时错误:未找到类 android.support.v4.app.ActivityCompatApi23 。有趣... 嗯显然,我应该使用与我的SDK相同版本的Android支持库。但是对于我来说,目前尚不清楚如何获取最新版本的支持库(请参阅Install latest android support library CLI) 是的。仅从24.1.1的aar中提取jar文件可能不是一个好主意-显然,它不是整个库,而是一个补丁。因此,我决定使用某些人编译的jar 23.2.1:https://github.com/pbakondy/cordova-plugin-android-support-v4-jar

编辑12: 有了v23.2.1 android支持库,我决定在用PERMISSION_GRANTED消息调用Log.d之后立即调用requestPermissions。输出如下:

08-17 12:50:15.132 28837 28837 D *** Loader::onCreate ***: PERMISSION_GRANTED
08-17 12:50:15.136 28837 28891 I com.javasrv: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
08-17 12:50:15.139  2219  2600 I ActivityManager: START u0 {act=android.content.pm.action.REQUEST_PERMISSIONS pkg=com.google.android.packageinstaller cmp=com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity (has extras)} from uid 10081
08-17 12:50:15.141  2219  2600 I wm_task_moved: [179,1,6]
08-17 12:50:15.142  2219  2600 I am_create_activity: [0,28890900,179,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity,android.content.pm.action.REQUEST_PERMISSIONS,NULL,NULL,8388608]
08-17 12:50:15.147  2219  2600 I am_pause_activity: [0,43511476,com.javasrv/.LoaderActivity]
08-17 12:50:15.182  2446  2446 V StatusBar: setLightsOn(true)
08-17 12:50:15.183 28837 28837 I am_on_resume_called: [0,com.javasrv.LoaderActivity,LAUNCH_ACTIVITY]
08-17 12:50:15.254 28837 28873 W cr_media: Requires BLUETOOTH permission
08-17 12:50:15.273 28837 28837 I am_on_paused_called: [0,com.javasrv.LoaderActivity,handlePauseActivity]
08-17 12:50:15.284  2219  2259 I am_restart_activity: [0,28890900,179,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity]
08-17 12:50:15.285  2219  2259 I am_set_resumed_activity: [0,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity,minimalResumeActivityLocked]
08-17 12:50:15.291  2219  2298 I sysui_count: [window_time_0,3]
08-17 12:50:15.291  2219  2298 I sysui_multi_action: [757,803,799,window_time_0,802,3]
08-17 12:50:15.297  2446  2446 V StatusBar: setLightsOn(true)
08-17 12:50:15.304  2219  5022 I am_finish_activity: [0,28890900,179,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity,app-request]
08-17 12:50:15.305  2219  5022 I am_pause_activity: [0,28890900,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity]
08-17 12:50:15.308  2219  2298 I sysui_count: [window_time_0,0]
08-17 12:50:15.308  2219  2298 I sysui_multi_action: [757,803,799,window_time_0,802,0]
08-17 12:50:15.439  2219  2259 I am_set_resumed_activity: [0,com.javasrv/.LoaderActivity,resumeTopActivityInnerLocked]
08-17 12:50:15.446  2219  2259 I am_resume_activity: [0,43511476,179,com.javasrv/.LoaderActivity]
08-17 12:50:15.457  2219  2298 I sysui_count: [window_time_0,0]
08-17 12:50:15.457  2219  2298 I sysui_multi_action: [757,803,799,window_time_0,802,0]
08-17 12:50:15.557  2446  2446 I chatty  : uid=10030(com.android.systemui) identical 5 lines
08-17 12:50:15.594  2446  2446 V StatusBar: setLightsOn(true)

没有对话框出现。看来系统使应用程序认为已授予该权限。

我想知道为什么...清单一定有问题,但是什么?

我将通过apkanalyzer输出整个清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:minSdkVersion="23"
    android:versionCode="6"
    android:versionName="1.0.0"
    android:targetSdkVersion="26"
    package="com.javasrv">

    <uses-permission
        android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:label="@ref/0x7f060000"
        android:icon="@ref/0x7f020000">

        <activity
            android:theme="@ref/0x010300f0"
            android:label="@ref/0x7f060000"
            android:name="com.javasrv.MainActivity">

            <intent-filter>

                <action
                    android:name="android.intent.action.MAIN" />

                <category
                    android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:theme="@ref/0x010300f0"
            android:label="@ref/0x7f060000"
            android:name="com.javasrv.LoaderActivity">

            <intent-filter>

                <action
                    android:name="android.intent.action.MAIN" />

                <category
                    android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <activity
            android:theme="@ref/0x01030011"
            android:label="@string/0xb"
            android:icon="@ref/0x7f010000"
            android:name="com.javasrv.TestActivity"
            android:screenOrientation="1">

            <intent-filter>

                <action
                    android:name="android.intent.action.MAIN" />

                <category
                    android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyTestService" />

        <service
            android:name=".MyJobService"
            android:permission="android.permission.BIND_JOB_SERVICE" />

        <receiver
            android:name="Boot">

            <intent-filter
                android:priority="100">

                <action
                    android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

有什么想法吗?

问题已解决

3 个答案:

答案 0 :(得分:0)

也许这可以帮助您。

只需在您的应用程序中设置compileSdkVersion和targetSdkVersion为26。

答案 1 :(得分:0)

如果checkpermission无效,则可以尝试对话框权限

当您的应用从checkSelfPermission()收到PERMISSION_DENIED时,您需要提示用户该权限。 Android提供了几种可用于请求权限的方法,例如requestPermissions()。

  ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    1);

然后覆盖方法

  @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case 1: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted

            } else {
                // permission denied

                Toast.makeText(BiggerScreen.this, "Permission denied to write your External storage", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        // other 'case' lines to check for other
        // permissions this app might request
    }
}

答案 2 :(得分:0)

哇。一直以来,问题出在AndroidManifest.xml。我在错误的位置指定了minSdkVersion。我应该在 uses-sdk xml标签中完成此操作,而不是在 manifest 标签中完成此操作,就像在Android Developer网站上这样写:https://developer.android.com/guide/topics/manifest/uses-sdk-element

我不知道该从哪里想到这些属性应该用 manifest 标记编写。也许这就是gradle所做的-在编译apk时会传递属性。

编辑::此外,必须在授予权限后重新启动应用。否则, checkSelfPermission 会通知您已授予访问权限,但该应用将无权访问文件:Writing external storage doesn't work until I restart the application on Android M