为什么当我请求 ACCESS_MEDIA_LOCATION 权限时没有显示权限框?

Hil*_*ryN 5 android android-permissions

我正在尝试为 Android 10 实现 ACCESS_MEDIA_LOCATION 权限,以便访问照片的位置。

首先,应用程序请求 READ_EXTERNAL_STORAGE 权限,以便使用 MediaStore 访问照片。

然后应用程序使用 ExifInterface 读取照片的位置。在 Android 10 中,ExifInterface 失败,因为它没有权限。

我尝试为 ACCESS_MEDIA_LOCATION 添加权限请求,但没有出现权限请求框。但是,该许可随后被授予!

如果我在获得 READ_EXTERNAL_STORAGE 权限之前先请求 ACCESS_MEDIA_LOCATION,那么权限请求框就会出现。

如果我然后请求 READ_EXTERNAL_STORAGE 权限,则权限请求框不会出现,但同样,随后授予权限。(我知道这样做没有意义,但我只是想看看发生了什么。)

我真的很困惑。应该请求用户的许可才能访问照片的位置是有道理的,但是如果之前已授予 READ_EXTERNAL_STORAGE 权限,为什么 ACCESS_MEDIA_LOCATION 的权限框没有出现,为什么在没有用户同意的情况下授予权限?

有什么我遗漏的东西会使权限框出现吗?

下面的代码片段。

安卓清单:

<manifest ...>

        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        …
Run Code Online (Sandbox Code Playgroud)

片段1:

public class Fragment1 extends Fragment {
…
        public View onCreateView(...
                …
                Log.d(TAG, "Entering Fragment1 requestPermissions operation for permission READ_EXTERNAL_STORAGE");
                Log.d(TAG, "Permission ACCESS_MEDIA_LOCATION, " + this.requireContext().checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION));
                Log.d(TAG, "Permission READ_EXTERNAL_STORAGE, " + this.requireContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));

                String[] permission = {Manifest.permission.READ_EXTERNAL_STORAGE};
                this.requestPermissions(permission, 1);

                Log.d(TAG, "Exiting Fragment1 requestPermissions operation for permission READ_EXTERNAL_STORAGE");
                Log.d(TAG, "Permission ACCESS_MEDIA_LOCATION, " + this.requireContext().checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION));
                Log.d(TAG, "Permission READ_EXTERNAL_STORAGE, " + this.requireContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));

                ...



        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
                Log.d(TAG, "Fragment1 Request Permissions callback");

                for (int i = 0; i < permissions.length; i++)
                    Log.d(TAG, "Permission " + permissions[0] + ", " + grantResults[0] );

                Log.d(TAG, "Permission ACCESS_MEDIA_LOCATION, " + this.requireContext().checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION));
                Log.d(TAG, "Permission READ_EXTERNAL_STORAGE, " + this.requireContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));
    }
Run Code Online (Sandbox Code Playgroud)

片段2:

public class Fragment2 extends Fragment {
        ...
        public View onCreate(...
                …
                Log.d(TAG, "Entering Fragment2 requestPermissions operation for permission ACCESS_MEDIA_LOCATION");
                Log.d(TAG, "Permission ACCESS_MEDIA_LOCATION, " + this.requireContext().checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION));
                Log.d(TAG, "Permission READ_EXTERNAL_STORAGE, " + this.requireContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));

                String[] permission = {Manifest.permission.ACCESS_MEDIA_LOCATION};
                this.requestPermissions(permission, 1);     // No permission box appears here :-(

                Log.d(TAG, "Exiting Fragment2 requestPermissions operation for permission ACCESS_MEDIA_LOCATION");
                Log.d(TAG, "Permission ACCESS_MEDIA_LOCATION, " + this.requireContext().checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION));
                Log.d(TAG, "Permission READ_EXTERNAL_STORAGE, " + this.requireContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));
                …
        
        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
                    Log.d(TAG, "Fragment2 Request Permissions callback");

                    for (int i = 0; i < permissions.length; i++)
                        Log.d(TAG, "Permission " + permissions[0] + ", " + grantResults[0] );

                    Log.d(TAG, "Permission ACCESS_MEDIA_LOCATION, " + this.requireContext().checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION));
                    Log.d(TAG, "Permission READ_EXTERNAL_STORAGE, " + this.requireContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));
        }
Run Code Online (Sandbox Code Playgroud)

当在 Nexus 6 API 29 模拟器上运行时,READ_EXTERNAL_STORAGE 的第一个 UI 框会弹出,我点击“允许”。然后我转到第二个片段,但在调用 requestPermissions 时没有弹出 UI 框。

这是日志。您可以看到当 requestPermissions 被调用时,权限是不允许的,但是当它到达回调时,权限已被授予:

2020-10-20 12:17:38.154 8830-8830/com.example.example1 D/ContentValues: Entering Fragment1 requestPermissions operation for permission READ_EXTERNAL_STORAGE
2020-10-20 12:17:38.155 8830-8830/com.example.example1 D/ContentValues: Permission ACCESS_MEDIA_LOCATION, -1
2020-10-20 12:17:38.155 8830-8830/com.example.example1 D/ContentValues: Permission READ_EXTERNAL_STORAGE, -1
2020-10-20 12:17:38.162 8830-8830/com.example.example1 D/ContentValues: Exiting Fragment1 requestPermissions operation for permission READ_EXTERNAL_STORAGE
2020-10-20 12:17:38.163 8830-8830/com.example.example1 D/ContentValues: Permission ACCESS_MEDIA_LOCATION, -1
2020-10-20 12:17:38.164 8830-8830/com.example.example1 D/ContentValues: Permission READ_EXTERNAL_STORAGE, -1
2020-10-20 12:17:49.544 8830-8830/com.example.example1 D/ContentValues: Fragment1 Request Permissions callback
2020-10-20 12:17:49.544 8830-8830/com.example.example1 D/ContentValues: Permission android.permission.READ_EXTERNAL_STORAGE, 0
2020-10-20 12:17:49.545 8830-8830/com.example.example1 D/ContentValues: Permission ACCESS_MEDIA_LOCATION, -1
2020-10-20 12:17:49.546 8830-8830/com.example.example1 D/ContentValues: Permission READ_EXTERNAL_STORAGE, 0
2020-10-20 12:17:55.312 8830-8830/com.example.example1 D/ContentValues: Entering Fragment2 requestPermissions operation for permission ACCESS_MEDIA_LOCATION
2020-10-20 12:17:55.313 8830-8830/com.example.example1 D/ContentValues: Permission ACCESS_MEDIA_LOCATION, -1
2020-10-20 12:17:55.318 8830-8830/com.example.example1 D/ContentValues: Permission READ_EXTERNAL_STORAGE, 0
2020-10-20 12:17:55.327 8830-8830/com.example.example1 D/ContentValues: Exiting Fragment2 requestPermissions operation for permission ACCESS_MEDIA_LOCATION
2020-10-20 12:17:55.328 8830-8830/com.example.example1 D/ContentValues: Permission ACCESS_MEDIA_LOCATION, -1
2020-10-20 12:17:55.329 8830-8830/com.example.example1 D/ContentValues: Permission READ_EXTERNAL_STORAGE, 0
2020-10-20 12:17:55.621 8830-8830/com.example.example1 D/ContentValues: Fragment2 Request Permissions callback
2020-10-20 12:17:55.622 8830-8830/com.example.example1 D/ContentValues: Permission android.permission.ACCESS_MEDIA_LOCATION, 0
2020-10-20 12:17:55.623 8830-8830/com.example.example1 D/ContentValues: Permission ACCESS_MEDIA_LOCATION, 0
2020-10-20 12:17:55.623 8830-8830/com.example.example1 D/ContentValues: Permission READ_EXTERNAL_STORAGE, 0
Run Code Online (Sandbox Code Playgroud)