編輯:關於Android編程
Camera在手機中有著舉足輕重的地位,不管是二維碼還是照片、識別,都離不開攝像頭,本文將對Android中的Camera進行全面解析。
權限鎮樓:
通過系統定義的Intent Action,我們可以很方便的使用所有實現了Camera功能的App。
這個action是最常用的一個調用系統Camera的action。
使用方式如下:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
通過這樣一個Action,我們就可以調用所有聲明了Camera的App。
那麼如何收到拍攝的圖片呢?我們自然是需要使用startActivityForResult方法。
這裡我們先來看最簡單的:
我們在:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
onActivityResult方法中,通過data參數來獲取圖像:
/**
* 通過data取得圖片
*/
Bundle extras = data.getExtras();
Bitmap bitmap = (Bitmap) extras.get(data);
mImageViewShow.setImageBitmap(bitmap);
但是,現在手機像素這麼高,萬一圖片特別大呢,會不會data過大而FC呢?放心,Android早就考慮到了,所以,data裡面壓根就不是完整的圖片,它只是一張縮略圖,對,真的是縮略圖。所以,我們需要獲取到拍攝的原圖,就不能使用這種方法。但是我們可以這樣做,我們可以指定MediaStore類的一個EXTRA_OUTPUT來指定拍攝圖像保存的位置,相當於建立一個臨時文件。在onActivityResult中,我們不使用data來獲取圖像,而是直接去讀這個臨時文件即可。
指定EXTRA_OUTPUT:
String tempPath = Environment.getExternalStorageDirectory().getPath();
mFilePath = tempPath + / + test1.png;
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri photoUri = Uri.fromFile(new File(mFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, CAMERA_CODE1);
onActivityResult:
/**
* 通過暫存路徑取得圖片
*/
FileInputStream fis = null;
Bitmap bitmap = null;
try {
fis = new FileInputStream(mFilePath);
bitmap = BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
這樣我們就可以獲取到完整的拍攝圖片了。後面你可以讓圖像顯示出來,顯示的時候,同樣需要考慮大圖的處理,避免圖像尺寸帶來的問題,這些東西,請參考這裡:
http://blog.csdn.net/eclipsexys/article/details/44459771
這裡就不贅述了。如果你的App僅僅是需要非常簡單的拍攝功能,那麼通過調用系統Intent就足夠了,但是大部分時候,這都是不可能的,所以下面我們來看看如何自定義Camera。
根據Google Android Doc,自定義一個Camera需要如下幾個步驟:
1.檢查Camera是否存在,並在AndroidManifest.xml中賦予相關的權限;
2.創建一個繼承於SurfaceView並實現SurfaceHolder接口的Camera Preview類;
3.新建一個Camera Preview布局文件;
4.設置一個拍照的監聽事件,例如單擊按鈕事件等;
5.實現拍照,並保存拍照後的圖片到設備;
6.釋放Camera。
看上去還是比較復雜的。所以我們一步步來。
首先,我們創建預覽Camera的界面:
非常簡單,兩個button下面一個surfaceview:
然後,我們創建一個Activity,用來展示Camera的預覽:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPtXiuPZBY3Rpdml0ecDvw+a/z7ao09BTdXJmYWNlVmlld6Osy/nS1KOsU3VyZmFjZVZpZXe1xMTH0rvM17arzvejrNfUyLvKx8nZsrvBy6Ossru2rrXEx+vX1NDQxNSyuaGjPC9wPg0KPHA+xMfDtNTa1eK49kFjdGl2aXR5wO/D5qOsztLDx9Do0qrX9sqyw7TE2KO/wb28/srCx+mjujwvcD4NCrP1yry7r8/gu/ogvavE2sjdz9TKvrW9U3VyZmFjZVZpZXcNCjxwPkFuZHJvaWS1xENhbWVyYcrHtsDP7bXEo6zI57n7tuC0prX308OjrL7Nu+HF17P20uyzo6Osy/nS1KOsztLDx9Do0qq9q0NhbWVyYbXEyfrD/NbcxtrT60FjdGl2aXR5tcTJ+sP81tzG2rDztqijujwvcD4NCm9uUmVzdW1lt723qNbQs/XKvLuvz+C7+iBvblBhdXNlt723qNbQys23xc/gu/oNCjxwPrP1yry7r8/gu/q3x7OjvPK1paO6PC9wPg0KPHByZSBjbGFzcz0="brush:java;">
/**
* 初始化相機
*
* @return camera
*/
private Camera getCamera() {
Camera camera;
try {
camera = Camera.open();
} catch (Exception e) {
camera = null;
}
return camera;
}
釋放相機也非常簡單:
/**
* 釋放相機資源
*/
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
那麼下面我們再來看如何把相機圖像設置到SurfaceView中進行預覽:
/**
* 在SurfaceView中預覽相機內容
*
* @param camera camera
* @param holder SurfaceHolder
*/
private void setStartPreview(Camera camera, SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
尼瑪,是不是也非常簡單,camera的一個方法已經幫我們自動關聯了SurfaceView。
PS 這裡需要注意下這個方法camera.setDisplayOrientation(90),通過這個方法,我們可以調整攝像頭的角度,不然默認是橫屏,圖像會顯示的比較奇怪。當然,即使你設置的90,圖像也有可能比較奇怪,這是因為你沒有對圖像進行正確的縮放,比例不對。
通過上面的設置,我們已經可以正常預覽攝像頭的圖像內容了,下面我們就可以拍照了。
唉,拍照真的也非常簡單,就一句話:
mCamera.takePicture(null, null, mPictureCallback);
當然,為了配合拍照,我們需要做一些設定,設置拍照的參數,並且給拍照之後的動作設定一個回調:
參數:
Camera.Parameters params = mCamera.getParameters();
params.setPictureFormat(ImageFormat.JPEG);
params.setPreviewSize(800, 400);
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(params);
// 使用自動對焦功能
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
mCamera.takePicture(null, null, mPictureCallback);
}
});
回調:
/**
* Camera回調,通過data[]保持圖片數據信息
*/
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Intent intent = new Intent(CustomCamera.this, CameraResult.class);
intent.putExtra(picPath, pictureFile.getAbsolutePath());
startActivity(intent);
CustomCamera.this.finish();
} catch (IOException e) {
e.printStackTrace();
}
}
};
在回調中,我們將拍攝好的圖片地址傳遞給用於展示的ImageView。這樣就完成了相機的拍攝與圖片的展示。
由於我們自己在布局中創建了一個SurfaceView,而且我們之間讓他match_parent了,所以,圖像在preview的時候,肯定是會有拉伸的。那麼如何處理這些變形呢?
我們可以通過改變SurfaceView大小的方式來實現,在Android API Demo中,Google也給我們提供了這樣一個實例:
路徑如下:
android-22/legacy/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
Google就是通過設置新的大小來適應預覽區域大小的方式來解決變形問題的,所以說,內事不懂看源碼,外事不懂看Demo。
聽上去非常高大上,其實,真的非常簡單,你只需要用一個FrameLayout把用來Preview的SurfaceView包起來就OK了,下面你想加什麼,就直接在FrameLayout中加吧,like this:
<framelayout android:layout_below="@id/ll" android:layout_height="match_parent" android:layout_width="match_parent">
</framelayout>
不光了ImageView,ViewPager也可以,這樣甚至可以做一個可切換的水印相機了。是不是非常簡單,而且加入的一切都是可操作的,加動效、顏色,分分鐘搞定。
以上。
起步之後,我們要開始跑了。
Paint類 *Paint類代表畫筆,用來描述圖形的顏色和風格,如線寬,顏色,透明度和填充效果等信息。 *使用Paint類時,需要先創建該類的對象,可以通過該類的構造函數
一、Service的種類1.按運行地點分類: 類別 區別 優點 缺點 應用 本地服務 (Local) 該服務依附在主進程上 服務依附在主進程上而不是獨立
工作中有做過手機App項目,前端和android或ios程序員配合完成整個項目的開發,開發過程中與ios程序配合基本沒什麼問題,而android各種機子和rom的問題很多
剛開始學習Android,由於之前比較熟悉OpenCV,於是就想先在Android上運行OpenCV試試 ================================