为何Android共享存储打开外部图片无需Manifest权限?
为什么无需存储权限就能打开共享存储的图片?
这是因为你用的是Android的存储访问框架(SAF),走的是系统文件选择器的授权逻辑,和直接访问共享存储的权限要求完全不同:
- 传统存储权限的适用场景:当你想直接通过文件路径(比如
new File("/sdcard/xxx.jpg"))读写共享存储里的文件时,才需要在Manifest里声明READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE这类权限——因为这是你的应用直接绕过系统管控去访问存储。 - SAF的授权逻辑:你代码里的
Intent.ACTION_OPEN_DOCUMENT会唤起系统自带的文件选择器,这个选择器是系统级应用,本身已经拥有访问所有存储的权限。当用户手动选择某张图片后,系统会给你的应用授予该单个文件的临时访问权限,并返回一个受管控的Uri。你后续通过这个Uri操作文件(比如imageView.setImageURI(uri)),本质是通过系统的ContentProvider间接读取内容,全程不需要你的应用拥有存储权限。 - 版本适配的补充:从Android 10(API 29)开始,谷歌就大力推荐用SAF替代直接存储权限;到了Android 11+,更是直接限制了直接访问共享存储的权限范围,SAF已经是访问非应用私有文件的标准方式。
你的代码核心就是触发SAF的逻辑:
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); activityResultLauncher.launch(intent); } }); } ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { Uri uri = result.getData().getData(); imageView.setImageURI(uri); } });
其中ACTION_OPEN_DOCUMENT是触发系统文件选择器的关键,CATEGORY_OPENABLE限定了只能选择可打开的文件,返回的Uri直接交给ImageView加载,全程由系统管控权限,所以不需要额外声明存储权限。
内容的提问来源于stack exchange,提问作者steeveKA1
相关产品推荐
相关产品推荐

