在安卓系统中操作外部存储需要申请权限,尤其是 Android 6.0+ 需动态申请:
// 在 AndroidManifest.xml 中声明权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
// 动态申请权限(Android 6.0+) if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE); }
通过 File
类创建文件夹,若不存在则自动创建:
// 获取公共图片存储目录(兼容 Android Q+) File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File appDir = new File(picturesDir, "MyAppFolder"); // 自定义文件夹名称 if (!appDir.exists()) { appDir.mkdirs(); // 递归创建文件夹 }
将 Bitmap
压缩为图片文件并存储:
public void saveImage(Bitmap bitmap, String fileName) { File file = new File(appDir, fileName); // 组合路径 try (FileOutputStream fos = new FileOutputStream(file)) { // 压缩为 JPEG 格式,质量为 100(无损) bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); // 确保数据写入完成 } catch (IOException e) { e.printStackTrace(); } }
保存后需通知系统媒体库,否则部分设备可能无法立即识别新文件:
// 发送广播通知媒体库 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setDataAndType(Uri.fromFile(file), "image/jpeg"); sendBroadcast(intent);
public void saveImageToGallery(Bitmap bitmap) { // 1. 申请权限(已省略) // 2. 创建文件夹(已初始化) // 3. 生成唯一文件名 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); String fileName = timeStamp + ".jpg"; // 4. 保存图片 saveImage(bitmap, fileName); // 5. 通知媒体库 sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(appDir, fileName)))); }
问题 | 解答 |
---|---|
Q1:Android 11+ 保存失败怎么办? | A1:Android 11 限制了对 Environment.getExternalStoragePublicDirectory() 的访问,需改用应用专属目录(getExternalFilesDir() )或请求 MANAGE_EXTERNAL_STORAGE 权限。 |
Q2:保存后图片在相册不显示? | A2:可能原因: 未发送媒体库更新广播; 文件路径错误; 存储权限未授予,建议检查日志和文件路径。 |
优化点 | 说明 |
---|---|
文件名冲突处理 | 使用时间戳或 UUID 生成唯一文件名,避免覆盖现有文件。 |
异步保存 | 在子线程执行文件写入操作,避免阻塞主线程。 |
适配 Android Q+ | 使用 Scoped Storage 或 MediaStore API 替代文件路径操作。 |