很多應用程序都可能會使用到調用攝像頭拍照的功能,比如說程序里需要上傳一張圖片 作為用戶的頭像,這時打開攝像頭拍張照是最簡單快捷的。下面就讓我們通過一個例子來學 習一下,如何才能在應用程序里調用手機的攝像頭進行拍照。
新建一個 ChoosePicTest 項目,然后修改 activity_main.xml 中的代碼,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical" >
<Button android:id="@+id/take_photo" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Take Photo" />
<ImageView android:id="@+id/picture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" />
</LinearLayout>
可以看到,布局文件中只有兩個控件,一個 Button 和一個 ImageView。Button 是用於打 開攝像頭進行拍照的,而 ImageView 則是用於將拍到的圖片顯示出來。
然后開始編寫調用攝像頭的具體邏輯,修改 MainActivity 中的代碼,如下所示:
public class MainActivity extends Activity { public static final int TAKE_PHOTO = 1; public static final int CROP_PHOTO = 2; private Button takePhoto;
private ImageView picture;
private Uri imageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
takePhoto = (Button) findViewById(R.id.take_photo);
picture = (ImageView) findViewById(R.id.picture);takePhoto.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 創建File對象,用於存儲拍照后的圖片
File outputImage = new File(Environment. getExternalStorageDirectory(), "tempImage.jpg");
try {
if (outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
imageUri = Uri.fromFile(outputImage);
Intent intent = new Intent("android.media.action. IMAGE_CAPTURE"); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, TAKE_PHOTO); // 啟動相機程序
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case TAKE_PHOTO:
if (resultCode == RESULT_OK) {
Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(imageUri, "image/*"); intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CROP_PHOTO); // 啟動裁剪程序
}
break;
case CROP_PHOTO:
if (resultCode == RESULT_OK) {
try {
Bitmap bitmap = BitmapFactory.decodeStream
(getContentResolver()
.openInputStream(imageUri));
picture.setImageBitmap(bitmap); // 將裁剪后的照片顯示出來
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
}
上述代碼稍微有點復雜,我們來仔細地分析一下。在 MainActivity 中要做的第一件事自 然是分別獲取到 Button 和 ImageView 的實例,並給 Button 注冊上點擊事件,然后在 Button 的點擊事件里開始處理調用攝像頭的邏輯,我們重點看下這部分代碼。
首先這里創建了一個 File 對象,用於存儲攝像頭拍下的圖片,這里我們把圖片命名為 output_image.jpg , 並 將 它 存 放 在 手 機 SD 卡 的 根 目 錄 下 , 調 用 Environment 的 getExternalStorageDirectory() 方法獲取到的就是手機 SD 卡的根目錄。然后再調用 Uri 的 fromFile()方法將 File 對象轉換成 Uri 對象,這個 Uri 對象標識着 output_image.jpg 這張圖片 的唯一地址。接着構建出一個 Intent 對象,並將這個 Intent 的 action 指定為 android.media.action. IMAGE_CAPTURE,再調用 Intent 的 putExtra()方法指定圖片的輸出地址,這里填入剛剛得 到的 Uri 對象,最后調用 startActivityForResult()來啟動活動。由於我們使用的是一個隱式 Intent,系統會找出能夠響應這個 Intent 的活動去啟動,這樣照相機程序就會被打開,拍下的 照片將會輸出到 output_image.jpg 中。
注意剛才我們是使用 startActivityForResult()來啟動活動的,因此拍完照后會有結果返回 到 onActivityResult()方法中。如果發現拍照成功,則會再次構建出一個 Intent 對象,並把它 的 action 指定為 com.android.camera.action.CROP。這個 Intent 是用於對拍出的照片進行裁剪的,因為攝像頭拍出的照片都比較大,而我們可能只希望截取其中的一小部分。然后給這個
Intent 設置上一些必要的屬性,並再次調用 startActivityForResult()來啟動裁剪程序。裁剪后 的照片同樣會輸出到 output_image.jpg 中。
裁剪操作完成之后,程序又會回調到 onActivityResult()方法中,這個時候我們就可以調 用 BitmapFactory 的 decodeStream()方法將 output_image.jpg 這張照片解析成 Bitmap 對象,然 后把它設置到 ImageView 中顯示出來。
由於這個項目涉及到了向 SD 卡中寫數據的操作,因此我們還需要在 AndroidManifest.xml中聲明權限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.choosepictest"
android:versionCode="1" android:versionName="1.0" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
……
</manifest>
這樣代碼就都編寫完了,現在將程序運行到手機上,然后點擊 Take Photo 按鈕就可以進 行拍照了,如圖 8.13 所示。
圖 8.13
拍照完成后點擊確定則可以對照片進行裁剪,如圖 8.14 所示。
圖 8.14
點擊完成,就會回到我們程序的界面。同時,裁剪后的照片當然也會顯示出來了,如圖
8.15 所示。
圖 8.15