從手機中獲取圖片遇到的OOM問題解析

在安卓開發過程中,一個無可避免的功能就是通過圖庫或者拍照來獲取圖片。

在這個過程中,一個最經典的錯誤就是由於圖片過大而造成的OOM問題。

首先調用圖庫或者是拍照功能

    /**
     * 圖庫選擇
     */
    public static void choicephoto(Activity activity) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Intent intent = new Intent();
            intent.setType(IMAGE_UNSPECIFIED);
            intent.setAction(Intent.ACTION_GET_CONTENT);
            activity.startActivityForResult(intent, CHOICEPHOTO);
        } else {
            Toast.makeText(activity, "請先插入SD卡", Toast.LENGTH_LONG).show();
        }
    }
    /**
     * 拍照
     */
    public static void takephoto(Activity activity) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            activity.startActivityForResult(intent, TAKEPHOTO);
        } else {
            Toast.makeText(activity, "請先插入SD卡", Toast.LENGTH_LONG).show();
        }
    }

  • 上面兩個方法使用的Activity類型作爲參數,如果是在Fragment啓用該功能的話,參數處應傳遞Fragment類型
  • CHOICEPHOTO和TAKEPHOTO和兩個int類型常量,可自行定義他們的數值。

當選擇圖片完成後,通過onActivityResult方法得到返回的數據

 @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (resultCode != RESULT_OK || data == null) {
            return;
        }
        switch (requestCode) {
            case CHOICEPHOTO:
                //從圖庫選擇的圖片根據手機不同,會有兩種返回數據方式
                Uri uri = data.getData();
                if (uri != null) {
                    //OOM問題主要出現在此處,需對Bitmap進行壓縮處理後再返回
                    photo = ImageUtils.compressImage(this, uri);
                    //對圖片進行展示或者其他操作
                    showImg();
                } else {
                    Bundle extras = data.getExtras();
                    if (extras != null) {
                        photo = extras.getParcelable("data");
                        showImg();
                    }
                }
                break;
            case TAKEPHOTO:
                photo = data.getExtras().getParcelable("data");
                showImg();
                break;
        }
    }


  • 如果此處發生OOM,往往是由於Bitmap的分辨率過大造成的,因此需要對圖片分辨率進行壓縮處理後,再次展示

ImageUtils.compressImage(this, uri);方法的代碼如下

    public static Bitmap compressImage(Context context, Uri uri) {
        //壓縮參考尺寸(PX)
        float hh = 1280f;
        float ww = 720f;
        //圖片寬高
        BitmapFactory.Options options = new BitmapFactory.Options();
        //開始讀入圖片,此時把options.inJustDecodeBounds 設爲true
        options.inJustDecodeBounds = true;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        //根據uri得到圖片的具體地址
        String path = FileUtils.getImageAbsolutePath(context, uri);
        //此時返回bm爲空
        BitmapFactory.decodeFile(path, options);
        //得到圖片的寬高
        float w = options.outWidth;
        float h = options.outHeight;
        //壓縮倍率
        float be = 1.0f;
        if (w > h) {
            be = ((w / hh + h / ww) / 2.0f);
        } else {
            be = ((w / ww + h / hh) / 2.0f);
        }
        //個人邏輯,僅供參考
        if (be <= 1.5f) {
            be = 1;
        }
        options.inSampleSize = (int) be;//設置縮放比例
        options.inJustDecodeBounds = false;
        //得到處理後的bitmap並返回
        Bitmap bitmap = BitmapFactory.decodeFile(path, options);
        return bitmap;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章