查询设备视频列表触发SecurityException问题求助(三星S7/S8等机型)
搞定三星Galaxy S7/S8获取视频列表的SecurityException问题
嘿,遇到这个问题太闹心了——明明加了权限、做了动态申请,三星这俩机型还是搞事情。我帮你梳理几个核心排查点和解决方案,亲测有效:
1. 先把权限申请流程补全
你提到了requestPermission()方法,但大概率是权限申请的逻辑不够完整,或者没处理好授权结果。比如用户拒绝权限后,你有没有做后续提示?还有,Android 6.0+里,WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE属于同一权限组,只要申请读权限就行,写权限会自动附带。
给你贴个完整的权限申请示例,直接用就行:
private static final int REQUEST_STORAGE_PERM = 1001; private void checkAndRequestStoragePermission() { // 先检查是否已经拿到权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 如果用户之前拒绝过,弹个对话框说明为啥要权限 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) { new AlertDialog.Builder(this) .setTitle("需要存储权限") .setMessage("要获取你的视频列表,得允许应用访问存储哦") .setPositiveButton("好的", (dialog, which) -> { // 发起权限请求 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERM); }) .setNegativeButton("算了", null) .show(); } else { // 第一次申请,直接弹系统权限框 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERM); } } else { // 已有权限,直接加载视频 loadVideos(); } } // 必须处理权限申请结果! @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_STORAGE_PERM) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { loadVideos(); } else { Toast.makeText(this, "没权限就没法看视频列表啦", Toast.LENGTH_SHORT).show(); } } }
2. 适配三星的特殊“脾气”
三星定制系统有时候会搞点特殊限制,比如查询视频的URI不对,或者访问了受保护的目录。
用标准的媒体查询URI
别自己瞎写URI,就用系统提供的:
Uri videoUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
避免访问敏感目录
三星的一些预装应用私有目录,哪怕有存储权限也碰不得。查询的时候尽量别用DATA字段(Android 9及以下虽然能用,但三星可能限制),换成RELATIVE_PATH或者只查询必要字段:
String[] projection = { MediaStore.Video.Media._ID, MediaStore.Video.Media.DISPLAY_NAME, MediaStore.Video.Media.DURATION };
捕获异常兜底
哪怕前面都做好了,还是可能触发异常,记得加个try-catch:
private void loadVideos() { ContentResolver resolver = getContentResolver(); Uri videoUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; String[] projection = { MediaStore.Video.Media._ID, MediaStore.Video.Media.DISPLAY_NAME, MediaStore.Video.Media.DURATION }; try (Cursor cursor = resolver.query(videoUri, projection, null, null, null)) { if (cursor != null && cursor.moveToFirst()) { do { // 处理每一条视频数据 String videoName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)); long videoDuration = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)); // ... 你的业务逻辑 } while (cursor.moveToNext()); } } catch (SecurityException e) { e.printStackTrace(); Toast.makeText(this, "哎呀,访问视频列表时碰到权限问题了", Toast.LENGTH_SHORT).show(); } }
3. 检查Manifest权限声明
别把权限写到<application>标签里了,要放在<manifest>根标签下,而且针对高版本系统做适配:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 10+ 不需要写权限,除非你要修改媒体文件 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
最后几个排查小细节
- 去系统设置看看,是不是用户手动把你的应用存储权限关掉了?
- 三星的Knox安全套件可能会限制应用访问存储,让用户去安全设置里给你开个绿灯。
按这个步骤来,应该能解决问题啦!
内容的提问来源于stack exchange,提问作者Piyush-Ask Any Difference
相关产品推荐
相关产品推荐

