今天我們來講一下在Android平台上開發相機的問題!這裡講的是調用系統相機。
1、從xml文件中得到surfaceview對象
[html] surfaceView = (SurfaceView) findViewById(R.id.g3_server_preview);
surfaceView = (SurfaceView) findViewById(R.id.g3_server_preview);
2、之後聲明一些回調方法,用於打開相機,設置相機的參數
[html] // SurfaceHodler 回調,處理打開相機,關閉相機以及照片尺寸的改變
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 打開相機
camera = Camera.open();
try {
// 設置預覽
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// 獲得相機參數
Camera.Parameters parameters = camera.getParameters();
// SDK版本選擇,兼容
if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
setDisplayOrientation(camera, 90);
} else {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
parameters.set("orientation", "portrait");
parameters.set("rotation", 90);
}
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
parameters.set("orientation", "landscape");
parameters.set("rotation", 90);
}
}
// 設置預覽大小
parameters.setPreviewSize(width, height);
pic_Width = g3_setting.getInt(AppData.G3_PIC_WIDTH, 640);
pic_Height = g3_setting.getInt(AppData.G3_PIC_HEIGHT, 800);
Log.i("Travel", pic_Width + ":" + pic_Height);
// 設置照片大小
parameters.setPictureSize(pic_Width, pic_Height);
// 設置照片格式
// parameters.setPictureFormat(PixelFormat.RGB_565);
// 開始預覽
camera.startPreview();
// 設置相機參數
camera.setParameters(parameters);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 停止預覽
if (camera != null) {
camera.stopPreview();
// 釋放相機資源
camera.release();
camera = null;
}
}
};
// SurfaceHodler 回調,處理打開相機,關閉相機以及照片尺寸的改變
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 打開相機
camera = Camera.open();
try {
// 設置預覽
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// 獲得相機參數
Camera.Parameters parameters = camera.getParameters();
// SDK版本選擇,兼容
if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
setDisplayOrientation(camera, 90);
} else {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
parameters.set("orientation", "portrait");
parameters.set("rotation", 90);
}
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
parameters.set("orientation", "landscape");
parameters.set("rotation", 90);
}
}
// 設置預覽大小
parameters.setPreviewSize(width, height);
pic_Width = g3_setting.getInt(AppData.G3_PIC_WIDTH, 640);
pic_Height = g3_setting.getInt(AppData.G3_PIC_HEIGHT, 800);
Log.i("Travel", pic_Width + ":" + pic_Height);
// 設置照片大小
parameters.setPictureSize(pic_Width, pic_Height);
// 設置照片格式
// parameters.setPictureFormat(PixelFormat.RGB_565);
// 開始預覽
camera.startPreview();
// 設置相機參數
camera.setParameters(parameters);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 停止預覽
if (camera != null) {
camera.stopPreview();
// 釋放相機資源
camera.release();
camera = null;
}
}
};[html] view plaincopyprint?protected void setDisplayOrientation(Camera camera, int angle) {
Method downPolymorphic;
try {
downPolymorphic = camera.getClass().getMethod(
"setDisplayOrientation", new Class[] { int.class });
if (downPolymorphic != null)
downPolymorphic.invoke(camera, new Object[] { angle });
} catch (Exception e1) {
}
}
protected void setDisplayOrientation(Camera camera, int angle) {
Method downPolymorphic;
try {
downPolymorphic = camera.getClass().getMethod(
"setDisplayOrientation", new Class[] { int.class });
if (downPolymorphic != null)
downPolymorphic.invoke(camera, new Object[] { angle });
} catch (Exception e1) {
}
}
3、然後設置surfaceview參數,加載回調方法
[html] // 設置屏幕常亮
surfaceView.setKeepScreenOn(true);
surfaceView.setFocusable(true);
releaseCamera();
// 從SurfaceView中獲得SurfaceHolder
surfaceView.getHolder().addCallback(surfaceCallback);
// 為SurfaceHolder 添加回調
// surfaceHolder.addCallback(surfaceCallback);
surfaceView.getHolder()
.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 設置屏幕常亮
surfaceView.setKeepScreenOn(true);
surfaceView.setFocusable(true);
releaseCamera();
// 從SurfaceView中獲得SurfaceHolder
surfaceView.getHolder().addCallback(surfaceCallback);
// 為SurfaceHolder 添加回調
// surfaceHolder.addCallback(surfaceCallback);
surfaceView.getHolder()
.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);釋放相機資源
[html] private void releaseCamera() {
// TODO Auto-generated method stub
if (camera != null) {
camera.stopPreview();
// 釋放相機資源
camera.release();
camera = null;
}
}
private void releaseCamera() {
// TODO Auto-generated method stub
if (camera != null) {
camera.stopPreview();
// 釋放相機資源
camera.release();
camera = null;
}
}
4、配置相機響聲音還是震動的回調方法
[html] Camera.ShutterCallback shutter = new ShutterCallback() {
@Override
public void onShutter() {
// TODO Auto-generated method stub
if (tone == null) {
// 發出提示用戶的聲音
tone = new ToneGenerator(AudioManager.STREAM_SYSTEM,
ToneGenerator.MAX_VOLUME);
}
if (g3_setting.getBoolean(AppData.G3_CONFIG_AUDIO, true)) {
tone.startTone(ToneGenerator.TONE_PROP_BEEP);
} else {
tone.stopTone();
Vibrator vibrator = (Vibrator) context
.getSystemService(Service.VIBRATOR_SERVICE);
vibrator.vibrate(100);
}
}
};
Camera.ShutterCallback shutter = new ShutterCallback() {
@Override
public void onShutter() {
// TODO Auto-generated method stub
if (tone == null) {
// 發出提示用戶的聲音
tone = new ToneGenerator(AudioManager.STREAM_SYSTEM,
ToneGenerator.MAX_VOLUME);
}
if (g3_setting.getBoolean(AppData.G3_CONFIG_AUDIO, true)) {
tone.startTone(ToneGenerator.TONE_PROP_BEEP);
} else {
tone.stopTone();
Vibrator vibrator = (Vibrator) context
.getSystemService(Service.VIBRATOR_SERVICE);
vibrator.vibrate(100);
}
}
};
小插曲,判斷系統聲音能否關閉
[html] File file = new File("/system/media/audio/ui/Camera_click.ogg");
if (!file.canWrite()) {
Tools.showToast(context, "設置聲音無效!");
} else {
file.renameTo(new File("/system/media/audio/ui/Camera_click.ogg1"));
}
File file = new File("/system/media/audio/ui/Camera_click.ogg");
if (!file.canWrite()) {
Tools.showToast(context, "設置聲音無效!");
} else {
file.renameTo(new File("/system/media/audio/ui/Camera_click.ogg1"));
}
5、自動對焦並拍照
[html] // 對焦成功再拍照
camera.autoFocus(new AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
// TODO Auto-generated method stub
// success為true表示對焦成功
if (success) {
if (camera != null) {
// 停止預覽
camera.stopPreview();
// 拍照
camera.takePicture(shutter, null, pictureCallback);
}
}
}
});
// 對焦成功再拍照
camera.autoFocus(new AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
// TODO Auto-generated method stub
// success為true表示對焦成功
if (success) {
if (camera != null) {
// 停止預覽
camera.stopPreview();
// 拍照
camera.takePicture(shutter, null, pictureCallback);
}
}
}
});
[html] // 照片回調
Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i("G3", "picture operating.............");
new SavePictureTask().execute(data);
camera.startPreview();
}
};
// 照片回調
Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i("G3", "picture operating.............");
new SavePictureTask().execute(data);
camera.startPreview();
}
};
[html] // 保存照片任務類
class SavePictureTask extends AsyncTask<byte[], String, String> {
@Override
protected String doInBackground(byte[]... params) {
Log.i("G3", "picture saving.............");
File path = new File(Tools.getSDPath());
if (!path.exists()) {
path.mkdirs();
}
// 創建文件
File picture = new File(Tools.getSDPath(), Tools.initPhotoName());
try {
// 獲得文件輸出流
FileOutputStream fos = new FileOutputStream(picture.getPath());
// 寫到該文件
fos.write(params[0]);
// 關閉文件流
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
// 保存照片任務類
class SavePictureTask extends AsyncTask<byte[], String, String> {
@Override
protected String doInBackground(byte[]... params) {
Log.i("G3", "picture saving.............");
File path = new File(Tools.getSDPath());
if (!path.exists()) {
path.mkdirs();
}
// 創建文件
File picture = new File(Tools.getSDPath(), Tools.initPhotoName());
try {
// 獲得文件輸出流
FileOutputStream fos = new FileOutputStream(picture.getPath());
// 寫到該文件
fos.write(params[0]);
// 關閉文件流
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
6、注意事項:
a.本項目代碼已經實現對焦功能,如果你的相機不能對焦,那是手機本身不支持,與硬件有關
b.分辨率的設置,在第3步的surfaceChanged方法裡已經實現,數據存在SharedPreference當中
但是有個小問題,配置分辨率頁面必須寫在另一頁面,因為surfaceCallback事件不能被remove
而且camera被釋放掉,仍然無作用,但原手機自帶系統相機可以實現當頁配置,所以如果你實現
此功能,還請賜教!