Android 6及以上系统截图保存至相册功能失效问题求助
解决Android 6+截图保存相册失效的问题
嘿,这个问题我之前也碰到过!核心原因是Android 6.0(API 23)引入了运行时权限机制,存储权限属于「危险权限」,必须在运行时主动向用户申请;另外Android 10(API 29)开始的分区存储政策也会影响文件保存逻辑,咱们一步步来修复:
一、先明确核心问题
在Android 5及以下,只要在AndroidManifest.xml里声明权限就能直接使用;但Android 6+要求危险权限必须动态申请,用户同意后才能访问存储。你的代码里应该缺少了权限申请的逻辑,导致保存文件时被系统拦截。
二、具体修复步骤
1. 在Manifest中声明必要权限
先确保AndroidManifest.xml里有这些权限(兼顾新旧版本兼容):
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+ 需单独申请媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33" />
2. 动态申请存储权限
在你的Activity中,先判断权限状态,未授权则主动申请:
private static final int REQUEST_STORAGE_PERMISSION = 100; private ImageView imgSS; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.tes_screenshot); imgSS = findViewById(R.id.imgSS); // 替换为你的ImageView实际ID // 检查存储权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 未授权,发起权限申请 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION); } else { // 已授权,直接执行截图逻辑 takeScreenshotAndSave(); } } // 处理权限申请结果回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_STORAGE_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { takeScreenshotAndSave(); } else { Toast.makeText(this, "需要存储权限才能保存截图", Toast.LENGTH_SHORT).show(); } } }
3. 适配截图与保存逻辑(兼容Android 10+)
Android 10开始推荐使用MediaStore保存媒体文件,替代直接操作外部存储路径,适配分区存储政策:
private void takeScreenshotAndSave() { // 获取当前Activity的根View View view = getWindow().getDecorView().getRootView(); view.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(false); // 显示截图到ImageView imgSS.setImageBitmap(bitmap); // 保存到相册 saveBitmapToGallery(bitmap); // 回收Bitmap避免内存泄漏 if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); } } private void saveBitmapToGallery(Bitmap bitmap) { String displayName = "Screenshot_" + System.currentTimeMillis() + ".png"; String mimeType = "image/png"; ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DISPLAY_NAME, displayName); values.put(MediaStore.Images.Media.MIME_TYPE, mimeType); // 适配Android 10+的分区存储 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/Screenshots"); values.put(MediaStore.Images.Media.IS_PENDING, 1); } else { // 低版本直接创建文件夹 String savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/Screenshots"; File dir = new File(savePath); if (!dir.exists()) dir.mkdirs(); values.put(MediaStore.Images.Media.DATA, new File(dir, displayName).getAbsolutePath()); } ContentResolver resolver = getContentResolver(); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); if (uri != null) { try (OutputStream outputStream = resolver.openOutputStream(uri)) { bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); // Android 10+ 标记文件为已完成 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { values.put(MediaStore.Images.Media.IS_PENDING, 0); resolver.update(uri, values, null, null); } // 通知相册刷新文件 sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)); Toast.makeText(this, "截图已保存到相册", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "保存失败", Toast.LENGTH_SHORT).show(); resolver.delete(uri, null, null); // 删除失败的记录 } } }
三、额外注意事项
- 若仅针对Android 13+开发,可使用
READ_MEDIA_IMAGES替代旧存储权限,更贴合新权限政策 - 避免在
onCreate直接调用截图逻辑(此时View可能未绘制完成),可通过postDelayed延迟执行 - 始终记得回收Bitmap对象,防止内存泄漏
内容的提问来源于stack exchange,提问作者dayat
相关产品推荐
相关产品推荐

