1. 程式人生 > >Android拍照和相簿選擇圖片上傳所遇到的一些坑

Android拍照和相簿選擇圖片上傳所遇到的一些坑

微信公眾號:IT小頑童
前段時間做拍照和相簿選擇圖片上傳,遇到一些坑,最近閒來沒事,就整理一篇部落格,並寫了個demo,專案中使用純java,這次採用java + kotlin混合,GitHub的地址戳此

1、首先遇到的的是Android7.0的坑

說是坑,有點欲加之罪的感覺,其實就是Android7.0的一個行為變更,以拍照為例,程式碼如下:

val file = File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME)
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file))
startActivityForResult(intent, REQUEST_IMAGE_PHOTO)

一經執行,在7.0以下的系統是可以正常執行,7.0及以上,便出現以下閃退,提示“android.os.FileUriExposedException: file:///storage/emulated/0/icon.jpg exposed beyond app through ClipData.Item.getUri()”,如圖所示:
Android7.0

查閱資料,根據官方文件提供Android 7.0 行為變更

Android7.0變更圖

官方已經指出問題所在,並給出瞭解決方案,通過FileProvider操作來解決閃退的問題。解決方案現在已經好多,今天這裡不做多餘的贅述,有興趣可以通過 GitHub 去下載我的demo。

2、無法載入此圖片

  • Intent.FLAG_GRANT_READ_URI_PERMISSION:臨時訪問讀許可權 intent的接受者將被授予 INTENT 資料uri 或者 在ClipData 上的讀許可權。
  • Intent.FLAG_GRANT_WRITE_URI_PERMISSION:臨時訪問寫許可權 intent的接受者將被授予 INTENT 資料uri 或者 在ClipData 上的寫許可權。

程式碼如下:

fun startSmallPhotoZoom(activity: Activity, uri: Uri?, code: Int) {
            val intent = Intent("com.android.camera.action.CROP")
            intent.setDataAndType(uri, "image/*")
            //以下兩行新增,解決無法載入此圖片的提示
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
            intent.putExtra("crop", "true")
            intent.putExtra("aspectX", 1) // 裁剪框比例
            intent.putExtra("aspectY", 1)
            intent.putExtra("outputX", 300) // 輸出圖片大小
            intent.putExtra("outputY", 300)
            intent.putExtra("scale", true)
            intent.putExtra("return-data", true)
            activity.startActivityForResult(intent, code)
        }

3、儲存時發生錯誤,儲存失敗

部分手機會出現這種情況,小米居多,造成此原因主要是onActivityResult回撥時,必要資訊沒有得到返回。

解決方案如下:

/**
     * 將URI轉為圖片的路徑
     *
     * @param context
     * @param uri
     * @return
     */
    public static String getRealFilePath(final Context context, final Uri uri) {
        if (null == uri)
            return null;
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null)
            data = uri.getPath();
        else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = context.getContentResolver().query(uri,
                    new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return data;
    }

後續有啥問題,會持續更新,如有錯誤,歡迎指正(__) 嘻嘻……


微信掃我