輕鬆的拍照
hasSystemFeature(PackageManager.FEATURE_CAMERA).
用一個相機APP來照相
上面那段代碼,標註的那個位置,開發的時候看不懂,於是去翻了官方的文檔。
給所有有照相功能的APP發去一個照相併返回數據的Intent.
調用者可以傳入一個EXTRA_OUTPUT的extra,用來控制圖片存儲位置。如果這個EXTRA_OUTPUT不存在的話,小尺寸的圖片將會以Bitmap對象,放到extra裏返回。這對於那種只需要小圖片的應用來說很爽。如果EXTRA_OUTPUT存在的話,全尺寸圖片將會存在EXTRA_OUT的URI值所寫的位置。(官方文檔後面還有兩句話是關於版本不同的,我就不翻譯了)
這個教程可以教你如何用一個已經安裝的相機APP來拍照
首先來請求一個相機權限
如果拍照這個功能在你的應用裏是很核心的功能,那麼你可以在商店裏要求用戶的設備必須要有攝像頭才能下載安裝,你只需要在你的Manifest文件里加入下面幾行代碼就可以了:
<manifest ... > <uses-feature android:name="android.hardware.camera" android:required="true" /> ... </manifest>
同時你可以用代碼來檢測設備是不是具有攝像頭:
hasSystemFeature(PackageManager.FEATURE_CAMERA);
Android請求使用其他APP一般是用Intent對象,並在這個對象裏描述你的要求。
下面這段程序進行了三個工作:實例化了一個Intent,激活了外部的一個Activity,並且寫了一些代碼,用於當焦點返回這個Activity時,處理圖片數據。
這是一段拍照的function:
static final int REQUEST_IMAGE_CAPTURE = 1; private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } }
注意這個startActivityForResult()方法,這個方法如果你調用了一個Intent但是沒有APP能夠響應(比如你的手機裏沒有可以照相的軟件)那麼程序就會崩潰,爲了安全起見,可以用這個resolvActivity()保護它,代碼就可以像上面那樣寫,具體的東西就不深入挖掘了,畢竟是爲了更快的寫出照相功能。
得到縮略圖
如果這種簡單的功能無法滿足你應用的需求——你可能需要把拍到的照片先處理一下。
安卓照相應用把圖片編碼以後轉成Bitmap對象放到extras裏,然後提交到onActivityResult(),在Intent的data鍵下。
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { Bundle extras = data.getExtras(); Bitmap imageBitmap = (Bitmap) extras.get("data"); mImageView.setImageBitmap(imageBitmap); } }
注意:這個從data返回的縮略圖可能適合當一個圖標,但是它除了當圖標也不能當別的了。因爲太小了。。如果想處理大圖的話,我們需要一些其他的工作。
搞定大圖!
getExternalStoragePublicDirectory()
,
方法的DIRECTORY_PICTURES
屬性來獲取這個存儲區的路徑。READ_EXTERNAL_STORAGE
和 WRITE_EXTERNAL_STORAGE
權限。<manifest ...> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>不過如果你不想存儲到公共區,想存儲到你的自己的應用專屬空間,你可以用這個方法:
getExternalFilesDir()
.maxSdkVersion
:<manifest ...> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" /> ... </manifest>注意:當你使用
getExternalFilesDir()
.的時候,裏面存儲的照片會隨着你卸載應用而被刪除。String mCurrentPhotoPath; private File createImageFile() throws IOException { // Create an image file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); File image = File.createTempFile( imageFileName, /* prefix */ ".jpg", /* suffix */ storageDir /* directory */ ); // Save a file: path for use with ACTION_VIEW intents mCurrentPhotoPath = "file:" + image.getAbsolutePath(); return image; }用這個方法可以爲你創建一個圖片文件,現在你可以創建或者調用一個Intent了,就像這樣:
static final int REQUEST_TAKE_PHOTO = 1; private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // Ensure that there's a camera activity to handle the intent if (takePictureIntent.resolveActivity(getPackageManager()) != null) { // Create the File where the photo should go File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { // Error occurred while creating the File ... } // Continue only if the File was successfully created if (photoFile != null) { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile)); startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO); } } }這裏補充一句:MediaStore.EXTRA_OUTPUT這個字段在官網的說明是:
把照片加入相冊
getExternalFilesDir()
.
方法獲得路徑,那麼你的相冊是無法看到你拍攝的照片的。
private void galleryAddPic() { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); File f = new File(mCurrentPhotoPath); Uri contentUri = Uri.fromFile(f); mediaScanIntent.setData(contentUri); this.sendBroadcast(mediaScanIntent); }
處理文件縮放
private void setPic() { // Get the dimensions of the View int targetW = mImageView.getWidth(); int targetH = mImageView.getHeight(); // Get the dimensions of the bitmap BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; // Determine how much to scale down the image int scaleFactor = Math.min(photoW/targetW, photoH/targetH); // Decode the image file into a Bitmap sized to fill the View bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); mImageView.setImageBitmap(bitmap); }