1. 程式人生 > >Android拍照和相簿+系統裁剪功能返回圖片

Android拍照和相簿+系統裁剪功能返回圖片

最近在使用一加3手機,Android系統6.0,進行測試的時候,發現呼叫手機的拍照和相簿選擇圖片的功能返回的時候都無法呼叫系統的裁剪功能,Log日誌也沒有輸出有用的資訊。經過在網上大量的查詢資料,拍照的問題解決了,但是用網上提供的方法都無法進行相簿選擇圖片後進行裁剪。

測試的時候使用一加手機拍照,拍出來的照片居然能達到10M~~15M,照片太大了,用intent.getParcelableExtra("data")方法獲取圖片的時候OOM了,所以這裡我指定了一個具體的File檔案來儲存拍照返回的圖片,設定MediaStore.EXTRA_OUTPUT

<pre name="code" class="java">    // 呼叫系統相機
    protected void startCamera() {
        // 呼叫系統的拍照功能
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra("camerasensortype", 2); // 呼叫前置攝像頭
        intent.putExtra("autofocus", true); // 自動對焦
        intent.putExtra("fullScreen", false); // 全屏
        intent.putExtra("showActionIcons", false);
        // 指定呼叫相機拍照後照片的儲存路徑
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
        startActivityForResult(intent, PHOTO_CARMERA);
    }

tempFile為指定的File檔案,在onActivityResult中通過Uri對圖片進行裁剪
<pre name="code" class="java">    @Override
    public void onActivityResult(int requestCode, int responseCode, Intent data) {
        switch (requestCode) {
            case PHOTO_CARMERA:
                startPhotoZoom(300);// 拍照返回後裁剪
                break;
            case PHOTO_PICK:
                copyFile(data);// 相簿選擇圖片後進行裁剪
                break;
            case PHOTO_CUT:
		decodeUriAsBitmap(Uri.fromFile(tempFile));// 獲取bitmap
                break;
            default:
                break;
        }
    }
呼叫系統的圖片裁剪
<pre name="code" class="java"><pre name="code" class="java">    /**
     * 呼叫裁剪功能
     *
     * @param size
     */
    private void startPhotoZoom(int size) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(Uri.fromFile(tempFile), "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", size);
        intent.putExtra("outputY", size);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
        intent.putExtra("return-data", false);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
        startActivityForResult(intent, PHOTO_CUT);
    }
通過Uri去獲取裁剪後的圖片
    /**
     * 通過URI獲取Bitmap
     * @param uri
     * @return
     */
    private Bitmap decodeUriAsBitmap(Uri uri) {
        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }
        return bitmap;
    }
這樣拍照算是解決了,但是相簿選擇圖片後想通過呼叫startPhotoZoom方法進行圖片的裁剪,在一加手機上總是提示"圖片載入時出錯",在三星,華為上都可以,唯獨一加手機不可以。看了看簡書APP的頭像上傳功能,發現這個APP在一加上是可以進行相簿-->裁剪的,但是選擇的圖片比較大的時候,比如,3M、4M以上的圖片,也是直接就返回了原來頁面。
<pre name="code" class="java">開啟相簿:
<pre name="code" class="java">    // 呼叫系統相簿
    protected void startPick() {
        Intent intent = new Intent(Intent.ACTION_PICK, null);
        intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                "image/*");
        startActivityForResult(intent, PHOTO_PICK);
    }

在一加手機上選中圖片返回後,沒辦法直接對圖片進行裁剪,這時候我試著通過Uri得到選中圖片的絕對路徑,把該圖片複製到tempFile檔案中,複製完成後再呼叫startPhotoZoom方法進行裁剪
獲取相簿選中圖片路徑並且複製到指定資料夾中
<pre name="code" class="java">    /**
     * 處理相簿選擇圖片後無法裁剪
     * 將選中的圖片寫入到目標檔案中
     * 將目標檔案的path作為裁剪的URI
     * @param data
     */
    private void copyFile(final Intent data){
        showProgressDialog("");
        new Thread(new Runnable() {
            @Override
            public void run() {
                Uri selectedImage = data.getData(); //獲取系統返回的照片的Uri
                String picturePath = "";// 相簿中的檔案路徑
                String[] filePathColumn = { MediaStore.Images.Media.DATA };
                Cursor cursor =getContentResolver().query(selectedImage,
                        filePathColumn, null, null, null);//從系統表中查詢指定Uri對應的照片
                if(null != cursor){
                    cursor.moveToFirst();
                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                    picturePath = cursor.getString(columnIndex);  //獲取照片路徑
                    cursor.close();
                }else{
                    picturePath = selectedImage.getPath();
                }
                try {
                    if(!tempFile.exists()){
                        tempFile.createNewFile();
                    }
                    InputStream fosfrom = new FileInputStream(new File(picturePath));
                    OutputStream fosto = new FileOutputStream(tempFile);
                    byte bt[] = new byte[1024];
                    int c;
                    while ((c = fosfrom.read(bt)) > 0)
                    {
                        fosto.write(bt, 0, c);
                    }
                    fosfrom.close();
                    fosto.flush();
                    fosto.close();
                    mHandler.sendEmptyMessage(COPY_FILE_COMPLETE);
                } catch (Exception e) {
                    e.printStackTrace();
                    mHandler.sendEmptyMessage(NO_PHOTO);
                }
            }
        }).start();
    }

COPY_FILE_COMPLETE完成後,在Handler中呼叫startPhotoZoom方法進行裁剪。經過測試,這個方法可行,唯一不好的地方是多了一步複製檔案的操作......
哪位大神有更好的方法,希望多多指教,不勝感激!




</pre><pre name="code" class="java">