当前位置:首页 > 行业动态 > 正文

安卓存储图片资源

安卓存储图片资源可通过文件系统(内部/外部 存储)、SQLite数据库或ContentProvider实现,内部存储使用getFilesDir(),外部需申请权限并遵循MediaStore规范,数据库适合结构化管理,ContentProvider支持跨应用共享,缓存机制可优化加载

存储位置选择

内部存储(Internal Storage)

  • 路径/data/data/包名/files/
  • 特点
    • 无需申请存储权限(默认可读写)
    • 数据仅限当前应用访问
    • 卸载应用时自动清除
  • 适用场景:私密图片存储(如用户头像、缓存图片)

外部存储(External Storage)

  • 路径
    • 公有目录:/sdcard/DCIM//sdcard/Pictures/
    • 应用专属目录:/sdcard/Android/data/包名/
  • 特点
    • 需申请WRITE_EXTERNAL_STORAGE权限(Android 6.0+需动态申请)
    • 数据可被其他应用或用户访问
    • Android 10+ 受Scoped Storage限制
  • 适用场景:用户生成的媒体文件(如拍照保存)

SD卡存储

  • 注意:Android 11后直接访问SD卡受限,需通过MediaStore API
  • 特点
    • 可移除存储介质
    • 兼容性较差(部分设备不支持)
  • 替代方案:使用外部存储公有目录

存储格式对比

存储方式 优点 缺点 适用场景
文件系统 简单直接,支持标准IO操作 大文件管理困难,无索引查询 本地缓存、临时图片
SQLite数据库 支持事务、索引查询 存储BLOB效率低,不适合大量图片 结构化数据+少量图片
ContentProvider 跨应用共享数据 实现复杂,需处理URI解析 图片分享、多应用协作
云存储 无限扩容、多端同步 依赖网络、存在流量消耗 用户数据备份、多设备同步

图片压缩与优化

压缩策略

  • 质量压缩:通过Bitmap.compress()方法降低JPEG质量(0-100)
  • 尺寸压缩:使用BitmapFactory.Options设置inSampleSize按比例缩放
  • 格式转换:WebP格式相比JPEG/PNG体积减少30%-50%

代码示例

// 尺寸压缩
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; // 宽高缩小为1/4
Bitmap bitmap = BitmapFactory.decodeFile("path", options);
// WebP压缩
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.WEBP, 80, baos); // 质量80%

权限处理(Android 6.0+)

权限类型 申请方式 说明
READ_EXTERNAL_STORAGE 危险权限,需动态申请 读取外部存储图片
WRITE_EXTERNAL_STORAGE 危险权限,需动态申请 写入/删除外部存储文件
MANAGE_EXTERNAL_STORAGE 系统设置页申请(Android 11+) 管理所有文件权限(谨慎使用)

常见问题与解决方案

Android 10+ 沙盒机制适配

  • 问题:直接访问外部存储路径会报FileUriExposedException
  • 解决方案
    • 使用MediaStore.Images.Media.insertImage()插入系统图库
    • 通过ContentResolver操作MediaStore数据库
    • 申请READ_MEDIA_IMAGES等细分权限(Android 13+)

大图片内存溢出(OOM)

  • 原因:直接加载超过VM堆大小的图片
  • 解决方案
    • 分区域加载:BitmapRegionDecoder
    • 采样率压缩:options.inSampleSize
    • 异步加载:配合LruCache缓存

问题与解答

Q1:如何动态申请外部存储写入权限?

A

安卓存储图片资源  第1张

  1. AndroidManifest.xml声明权限:
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  2. 运行时检查并申请:
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
    }
  3. 处理回调结果:
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限已授予
        } else {
            // 权限被拒绝
        }
    }

Q2:如何将图片保存到系统相册并刷新媒体库?

A

  1. 通过MediaStore插入图片:
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.DATA, filePath);
    getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
  2. 发送广播通知媒体库更新(Android 4.4+):
    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    intent.setDataAndType(Uri.fromFile(new File(filePath)), "image/");
    sendBroadcast(intent);
0