標籤:android 照相 intent imageview onactivityresult
最近在做Android的項目,其中部分涉及到影像處理的內容.這裡先講述如何調用Camera應用程式進行拍照,並和儲存顯示在ImageView控制項中以及遇到的困難和解決方案.
PS:作者購買了本《Android第一行代碼 著:郭霖》,參照裡面的內容完成(推薦該書,前面的布局及應用非常不錯).網上這類資料非常多,作者僅僅分享給初學者同時線上記錄些內容,希望對大家有所協助.
首先,設定activity_main.xml為LinearLayout布局且 android:orientation="vertical"
<Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="TakePhoto Button" /> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" />
然後,在MainActivity.java檔案中public class MainActivity extends Activity修改原始碼.添加自訂變數:
//自訂變數public static final int TAKE_PHOTO = 1;public static final int CROP_PHOTO = 2;private Button takePhotoBn;private ImageView showImage;private Uri imageUri; //圖片路徑private String filename; //圖片名稱
添加函數實現點擊拍照功能:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); takePhotoBn = (Button) findViewById(R.id.button1); showImage = (ImageView) findViewById(R.id.imageView1); //點擊"Photo Button"按鈕照相 takePhotoBn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //圖片名稱 時間命名 SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); Date date = new Date(System.currentTimeMillis()); filename = format.format(date); //建立File對象用於儲存拍照的圖片 SD卡根目錄 //File outputImage = new File(Environment.getExternalStorageDirectory(),"test.jpg"); //儲存至DCIM檔案夾 File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); File outputImage = new File(path,filename+".jpg"); try { if(outputImage.exists()) { outputImage.delete(); } outputImage.createNewFile(); } catch(IOException e) { e.printStackTrace(); } //將File對象轉換為Uri並啟動照相程式 imageUri = Uri.fromFile(outputImage); Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); //照相 intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //指定圖片輸出地址 startActivityForResult(intent,TAKE_PHOTO); //啟動照相 //拍完照startActivityForResult() 結果返回onActivityResult()函數 } }); if (savedInstanceState == null) { getFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()) .commit(); }}
通過startActivityForResult和onActivityResult方法實現拍照和儲存功能:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode != RESULT_OK) { Toast.makeText(MainActivity.this, "ActivityResult resultCode error", Toast.LENGTH_SHORT).show();return; }switch(requestCode) {case TAKE_PHOTO:Intent intent = new Intent("com.android.camera.action.CROP"); //剪裁intent.setDataAndType(imageUri, "image/*");intent.putExtra("scale", true);//設定寬高比例intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); //設定裁剪圖片寬高 intent.putExtra("outputX", 340); intent.putExtra("outputY", 340);intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);Toast.makeText(MainActivity.this, "剪裁圖片", Toast.LENGTH_SHORT).show();//廣播重新整理相簿 Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);intentBc.setData(imageUri); this.sendBroadcast(intentBc); startActivityForResult(intent, CROP_PHOTO); //設定裁剪參數顯示圖片至ImageViewbreak;case CROP_PHOTO:try { //圖片解析成Bitmap對象Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));Toast.makeText(MainActivity.this, imageUri.toString(), Toast.LENGTH_SHORT).show();showImage.setImageBitmap(bitmap); //將剪裁後照片顯示出來} catch(FileNotFoundException e) {e.printStackTrace();}break;default:break;}}
由於涉及到SD卡中寫資料操作和Camera操作,需要在AndroidMainfest.xml檔案中聲明許可權:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.CAMERA" />
運行結果如所示:
需要注意以下幾個問題:
1.拍照和都涉及到startActivityForResult和onActivityResult的互動操作.
startActivityForResult(Intent intent, //Intent對象int requestCode //>=0 當Activity結束時requestCode將歸還在onActivityResult()中)onActivityResult(int requestCode, //提供給onActivityResult,以確認返回的資料是從哪個Activity返回的int resultCode, //由子Activity通過其setResult()方法返回 通常為RESULT_CANCELED或RESULT_OKIntent data //一個Intent對象,帶有返回的資料)
其中onActivityResult的requestCode和startActivityForResult中的requestCode相對應.同時結合Intent意圖實現拍照和,核心代碼如下:(intent的參數設定省略)
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent,TAKE_PHOTO);
Intent intent = new Intent("com.android.camera.action.CROP");
startActivityForResult(intent, CROP_PHOTO);
2.使用Android拍照儲存在系統相簿,圖庫不能立刻顯示最新照片.解決方案是發送系統內建的廣播去重新整理相簿實現顯示.代碼如下:
Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);intentBc.setData(imageUri); this.sendBroadcast(intentBc);
可能你會使用下面這條廣播掃描整個SD卡,但4.4已禁止這樣的操作:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(...)))
參考資料 http://blog.csdn.net/xiaanming/article/details/8990627
3.當運行程式是可能會發現結果映像顯示很小,當通過一個Intent意圖觸發時,Camera程式不會將全尺寸映像返回給主調活動,這樣需要大量的記憶體,而行動裝置記憶體會有一定限制.通常Camera將在返回的意圖中返回一幅很小的縮圖,大圖可能會導致OOM問題.參考:《Android多媒體開發進階編程 著:Shawn Van Every》
針對大映像Android提供BitmapFactory類,允許通過各種資源載入Bitmap映像.調用BitmapFactory.Options類可以定義如何將Bitmap讀入記憶體,當載入映像時,可設定BitmapFactory採樣大小.並指定inSampleSize參數表明載入時結果Bitmap映像所佔的比例.如inSampleSize=8表明產生一副大小為原始映像1/8的映像.參考下面代碼:
if(resultCode==RESULT_OK) {DisplayMetrics dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);int width = dm.widthPixels; //寬度int height = dm.heightPixels ; //高度//載入映像尺寸而不是映像本身BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();bmpFactoryOptions.inJustDecodeBounds = true; //bitmap為null 只是把圖片的寬高放在Options裡int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);//設定圖片壓縮比例 如果兩個比例大於1 映像一邊將大於螢幕if(heightRatio>1&&widthRatio>1) {if(heightRatio>widthRatio) {bmpFactoryOptions.inSampleSize = heightRatio;}else {bmpFactoryOptions.inSampleSize = widthRatio;}}//映像真正解碼bmpFactoryOptions.inJustDecodeBounds = false;Bitmap bitmap = BitmapFactory.decodeFile(imageUri.toString(), bmpFactoryOptions);showImage.setImageBitmap(bitmap); //將剪裁後照片顯示出來}
4.使用nexus 4 剪裁圖片後不能setImageBitmap顯示在ImageView控制項中,其中只有儲存按鈕,沒有剪裁按鈕.測試發現沒有返回RESULT_OK.這個問題不能解決.Why?
參考:Unable to Save Photo Edits
最後希望文章對大家有所協助,這是我學習Android影像處理部分的基礎性文章與解決過程.
參考資料和推薦博文:(都是非常不錯的資料-.-)
《Android第一行代碼》著郭霖 參考8.3 調用網路攝影機和相簿
android拍照圖片選取與圖片剪裁 By:Lee_Allen
Android_照相機Camera_調用系統照相機返回data為空白 By:strawberry2013
Android圖片剪裁功能實心詳解 By:小馬
Android開發 拍照、圖片集儲存照片技巧
Android 拍照並顯示在ImageView中(進階) By:leesa
android調動系統的照相機並把照片顯示在ImageView上
cameraintent data null in onActivityResult(int requestCode, int resultCode, Intentdata)
Android高效載入大圖、多圖解決方案,有效避免程式OOM By:guolin
Android相機、相簿擷取圖片顯示並儲存到SD卡 By:唐韌_Ryan
android、擷取本地圖片|直接擷取照相圖片 By:zcljy0318
(By:Eastmount 2014-10-23 晚10點http://blog.csdn.net/eastmount/)
[Android] 拍照、、儲存並顯示在ImageView控制項中