一個但凡涉及到用戶信息的應用,總少不了設置用戶圖像這個小功能。之前做這塊的時候只是簡單的複製粘貼導致最近再做這個功能的時候,卻發現問題很多,拍照及相冊選擇後啟動系統裁剪要不崩潰要不就是沒有返回數據,今天好好梳理一下這個功能。 調用系統拍照界面: 調用系統相冊界面: 這裡補充一下,很多網友都說andr ...
一個但凡涉及到用戶信息的應用,總少不了設置用戶圖像這個小功能。之前做這塊的時候只是簡單的複製粘貼導致最近再做這個功能的時候,卻發現問題很多,拍照及相冊選擇後啟動系統裁剪要不崩潰要不就是沒有返回數據,今天好好梳理一下這個功能。
調用系統拍照界面:
private void startTakePhotoActivity() { temp_file_name = String.valueOf(System.currentTimeMillis()) + FILE_SUFFIX; temp_photo_uri = Uri.fromFile(new File(DIRECTORY, temp_file_name)); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 預設情況下不需要指定拍照生成圖片的uri 系統預設返回照片縮略圖uri // 如果用戶指定了生成圖片的uri 系統就不會返回 intent.putExtra(MediaStore.EXTRA_OUTPUT, temp_photo_uri); startActivityForResult(intent, FLAG_CAMERA); }
調用系統相冊界面:
private void startPickPhotoActivity() { // temp_file_name未賦值 在這裡對其初始化 temp_file_name = System.currentTimeMillis() + FILE_SUFFIX; Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); startActivityForResult(intent, FLAG_GALLERY); }
這裡補充一下,很多網友都說android4.4以上怎麼怎麼了,其實不用想這麼多,看看代碼是不是還和以前沒什麼兩樣?看到有網友專門針對4.4以上版本及以下版本判斷,也只是因為4.4以上版本從相冊選擇圖片時提供另外一個意圖 Intent.ACTION_OPEN_DOCUMENT ,可以使用最近瀏覽過的圖片,代碼量卻大了不少。所以個人覺得就一個選擇圖片沒必要做這麼複雜,因此我還是使用相冊來選圖。
調用系統裁剪界面:
private void startCropPhotoActivity(Uri orgUri) { // 保存剪裁生成圖片的uri String _fileName = "_" + System.currentTimeMillis() + ".jpg"; temp_photo_uri = Uri.fromFile(new File(DIRECTORY, _fileName)); // 剪裁圖片意圖 Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(orgUri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 640); intent.putExtra("outputY", 640); intent.putExtra("scale", true); // 將剪切的圖片保存到目標Uri中 註釋同拍照 intent.putExtra(MediaStore.EXTRA_OUTPUT, temp_photo_uri); intent.putExtra("return-data", false); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG); intent.putExtra("noFaceDetection", true); startActivityForResult(intent, FLAG_CROP); }
雖然代碼中已經加了註釋,還是要和大伙啰嗦一下上面紅色加粗的代碼。之前沒有好好理解才導致在這裡栽個大跟頭。
intent.putExtra(MediaStore.EXTRA_OUTPUT, temp_photo_uri):用來指定拍照或裁剪後生成的圖片存儲在哪裡,如果指定了這個參數,那麼拍照後就不會返回生成縮略圖的Uri,當然再用 intent.getData 勢必會 NullPointException,這時候再要用到Uri就得從文件來或者乾脆造個成員變數來保存這個Uri。
到這裡問題基本上已經解決,但是現在是一個雲的時代,大多對android系統個性後的ROM,相冊這個功能看起來是很強大,但給開發者帶來卻是無盡的痛苦,接下來說說這個 雲相冊 引發的問題。
回到我的代碼,拍照已經OK,就是從相冊選擇圖片在 onActivityResult 返回得到 resultCode 始終為 0 (正常 RESULT_OK = -1),經過對比返回的Uri發現問題並不是大家所說的Uri格式不對,而是在測試的手機上 根本找不到選擇的照片 。但為什麼還顯示在這裡,並且選擇後返回的Uri看起來和本地照片沒什麼區別,這些三方廠商給開發者挖了這麼大個坑坑。好了,問題找到就好辦了,既然是圖片不存在,那我們就得讓用戶知道選擇的這張圖片不在手機上,避免了程式崩潰也提高了用戶體驗,如果有力氣的話,完全可以不用系統的相冊來選擇這樣就不會發生上面提到的這個問題。
說了這麼多,好像廢話一籮筐,針對這次出現的問題,參考了好幾個網友提供的代碼,裡面不乏有值得我借鑒的東西,也給大伙分享一下,CameraActivity是我修改過的,在android4.4及4.1上測試通過。有空再封裝一個工具類出來。
代碼下載:http://pan.baidu.com/s/1miq120g