本講內容:Android手機攝像頭編程入門
智能手機中的攝像頭和普通手機中的攝像頭最大的區別在於,智能機上的攝像頭可以由程序員寫程序控制,做一些有趣的應用譬如,畫中畫,做一些有用的應用譬如二維碼識別,等等。本講打算通過一個實例,來介紹一下攝像頭編程,相關解釋都寫在代碼中了,請注意看代碼註釋。
實例:窈窈照相機,功能很簡單,就是點擊程序彈出照相預覽界面,點擊相機按鈕完成照相功能,所照相片會存儲在手機存儲卡根目錄。
1、創建一個項目 Lesson36_Camera ,主程序文件爲 MainActivity.java
2、AndroidManifest.xml 中設置屏幕爲橫屏,並且聲明攝像頭和存儲卡的使用權限,具體代碼如下:
01 |
<?xml version= "1.0"
encoding= "utf-8" ?>
|
03 |
<APPLICATION android:icon= "@drawable/icon"
android:label= "@string/app_name" >
|
04 |
<ACTIVITY android:label= "@string/app_name"
android:configchanges= "orientation|keyboardHidden|keyboard"
android:screenorientation= "landscape"
android:name= ".MainActivity" >
|
06 |
<ACTION android:name= "android.intent.action.MAIN"
/> |
07 |
<CATEGORY android:name= "android.intent.category.LAUNCHER"
/> |
12 |
<USES android:minsdkversion= "8"
-sdk /> |
13 |
<USES android:name= "android.permission.CAMERA"
-permission></USES> |
14 |
<USES android:name= "android.permission.WRITE_EXTERNAL_STORAGE"
-permission></USES> |
15 |
<USES android:name= "android.hardware.camera"
-feature /> |
16 |
<USES android:name= "android.hardware.camera.autofocus"
-feature /> |
3、本例中不需要佈局文件main.xml,因爲本例中的UI組建都是動態添加上去的。
4、最後MainActivity.java的代碼如下:
001 |
package
basic.android.lesson36; |
003 |
import
java.io.BufferedOutputStream; |
005 |
import
java.io.FileOutputStream; |
006 |
import
java.io.IOException; |
007 |
import
java.util.Calendar; |
008 |
import
java.util.Locale; |
010 |
import
android.app.Activity; |
011 |
import
android.content.Context; |
012 |
import
android.graphics.Bitmap; |
013 |
import
android.graphics.BitmapFactory; |
014 |
import
android.graphics.PixelFormat; |
015 |
import
android.hardware.Camera; |
016 |
import
android.os.Bundle; |
017 |
import
android.text.format.DateFormat; |
018 |
import
android.util.Log; |
019 |
import
android.view.KeyEvent; |
020 |
import
android.view.SurfaceHolder; |
021 |
import
android.view.SurfaceView; |
022 |
import
android.view.Window; |
023 |
import
android.view.WindowManager; |
024 |
import
android.widget.FrameLayout; |
025 |
import
android.widget.TextView; |
026 |
import
android.widget.Toast; |
028 |
public
class
MainActivity extends
Activity { |
030 |
private
CameraView cv; |
032 |
private
Camera mCamera = null ;
|
034 |
private
Bitmap mBitmap = null ;
|
037 |
public
Camera.PictureCallback pictureCallback = new
Camera.PictureCallback() { |
039 |
public
void
onPictureTaken( byte [] data, Camera camera) {
|
040 |
Log.i( "yao" , "onPictureTaken" );
|
041 |
Toast.makeText(getApplicationContext(),
"正在保存……" , Toast.LENGTH_LONG).show();
|
043 |
mBitmap = BitmapFactory.decodeByteArray(data,
0 , data.length);
|
045 |
File file =
new
File( "/sdcard/YY" +
new
DateFormat().format( "yyyyMMdd_hhmmss" , Calendar.getInstance(Locale.CHINA)) +
".jpg" );
|
047 |
file.createNewFile();
|
048 |
BufferedOutputStream os =
new
BufferedOutputStream( new
FileOutputStream(file)); |
049 |
mBitmap.compress(Bitmap.CompressFormat.PNG,
100 , os);
|
052 |
Toast.makeText(getApplicationContext(),
"圖片保存完畢,在存儲卡的根目錄" , Toast.LENGTH_LONG).show();
|
053 |
}
catch
(IOException e) { |
062 |
public
void
onCreate(Bundle savedInstanceState) { |
063 |
super .onCreate(savedInstanceState);
|
066 |
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
068 |
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
070 |
getWindow().setFormat(PixelFormat.TRANSLUCENT);
|
073 |
FrameLayout fl =
new
FrameLayout( this );
|
076 |
cv =
new
CameraView( this );
|
080 |
TextView tv =
new
TextView( this );
|
081 |
tv.setText( "請按\"相機\"按鈕拍攝" );
|
090 |
public
boolean
onKeyDown( int
keyCode, KeyEvent event) { |
091 |
Log.i( "yao" , "MainActivity.onKeyDown" );
|
092 |
if
(keyCode == KeyEvent.KEYCODE_CAMERA) { |
093 |
if
(mCamera != null ) {
|
094 |
Log.i( "yao" , "mCamera.takePicture" );
|
096 |
mCamera.takePicture( null ,
null , pictureCallback);
|
099 |
return
cv.onKeyDown(keyCode, event); |
103 |
class
CameraView extends
SurfaceView { |
105 |
private
SurfaceHolder holder = null ;
|
108 |
public
CameraView(Context context) { |
110 |
Log.i( "yao" , "CameraView" );
|
113 |
holder =
this .getHolder();
|
115 |
holder.addCallback( new
SurfaceHolder.Callback() { |
118 |
public
void
surfaceDestroyed(SurfaceHolder holder) { |
120 |
mCamera.stopPreview();
|
127 |
public
void
surfaceCreated(SurfaceHolder holder) { |
129 |
mCamera = Camera.open();
|
132 |
mCamera.setPreviewDisplay(holder);
|
133 |
}
catch
(IOException e) { |
143 |
public
void
surfaceChanged(SurfaceHolder holder, int
format, int
width, int
height) { |
146 |
Camera.Parameters parameters = mCamera.getParameters();
|
148 |
parameters.setPictureFormat(PixelFormat.JPEG);
|
150 |
parameters.setPreviewSize( 854 ,
480 );
|
152 |
parameters.setFocusMode( "auto" );
|
154 |
parameters.setPictureSize( 2592 ,
1456 );
|
156 |
mCamera.setParameters(parameters);
|
158 |
mCamera.startPreview();
|
162 |
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
5、連接Milestone,編譯並運行程序:悲劇的是,截圖只能看到黑黑的一片,無法截取到攝像頭傳輸過來SurfaceView信息,而在真機中是能看到預覽效果的。
還是上一張照好的圖片給大家吧,