引言

权限设置与基本流程

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
}

从相机/相册获取图片

调用相机拍照

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
    startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}

打开相册选取图片

Intent pickImageIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickImageIntent, REQUEST_IMAGE_PICK);

处理返回的URI

onActivityResult方法中,我们会收到一个URI数组。处理这些URI时,需要注意不同Android版本的差异。

Android 4.4(KitKat)及以下版本

在这些版本中,URI通常是文件路径的形式,可以直接使用。

if (requestCode == REQUEST_IMAGE_PICK && resultCode == RESULT_OK && data != null) {
    Uri uri = data.getData();
    String imagePath = getPath(this, uri);
    // 处理图片
}

Android 4.4(KitKat)及以上版本

从Android 4.4开始,URI的形式发生了变化,需要特殊处理。

@SuppressLint("NewApi")
public String getPath(Context context, Uri uri) {
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }
        }
        // 其他类型的URI处理
    } else if ("content".equalsIgnoreCase(uri.getScheme())) {
        return getDataColumn(context, uri, null, null);
    } else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }
    return null;
}

高效处理URI数组

AsyncTask<Uri, Void, List<String>> processImagesTask = new AsyncTask<Uri, Void, List<String>>() {
    @Override
    protected List<String> doInBackground(Uri... uris) {
        List<String> imagePaths = new ArrayList<>();
        for (Uri uri : uris) {
            String imagePath = getPath(getApplicationContext(), uri);
            imagePaths.add(imagePath);
        }
        return imagePaths;
    }

    @Override
    protected void onPostExecute(List<String> imagePaths) {
        // 处理图片路径
    }
};

processImagesTask.execute(uris);

使用Glide优化图片加载

集成Glide

build.gradle中添加依赖:

implementation 'com.github.bumptech.glide:glide:4.x'
annotationProcessor 'com.github.bumptech.glide:compiler:4.x'

使用Glide加载图片

Glide.with(context)
    .load(imagePath)
    .into(imageView);

内存与磁盘缓存策略

Glide提供了强大的缓存机制,包括内存缓存和磁盘缓存。

内存缓存

Glide默认使用LruCache作为内存缓存策略,可以根据需要自定义缓存大小。

GlideBuilder builder = new GlideBuilder();
builder.setMemoryCache(new LruResourceCache(yourCacheSize));
Glide.init(context, builder);

磁盘缓存

Glide也支持磁盘缓存,可以通过配置来优化缓存策略。

Glide.with(context)
    .load(imagePath)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .into(imageView);

总结