異常:java.lang.RuntimeException: setParameters failed
Android調用camera錯誤setParameters failed深層解析
真機測試報錯ERROR/AndroidRuntime: java.lang.RuntimeException: setParameters failed解決辦法
Android關閉自定義相機拍照聲音
android 自定義相機Camera2
Android提供了Camera來控制拍照,步驟如下:
(1)調用Camera的open()方法打開相機。
(2)調用Camera的getParameters()獲取拍照參數,該方法返回一個Cmera.Parameters對象。
(3)調用Camera.Parameters對象對照相的參數進行設置。
(4)調用Camera的setParameters(),并將Camera.Parameters對象作為參數傳入,這樣就可以對拍照進行參數控制,Android2.3.3以后不用設置。
(5)調用Camerade的startPreview()的方法開始預覽取景,在之前需要調用Camera的setPreviewDisplay(SurfaceHolder holder)設置使用哪個SurfaceView來顯示取得的圖片。
(6)調用Camera的takePicture()方法進行拍照。
(7)程序結束時,要調用Camera的stopPreview()方法停止預覽,并且通過Camera.release()來釋放資源。
需要賦予Camera的權限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.CAMERA"/>
具體代碼:
package com.lyj.camera;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
public class MyCameraActivity extends Activity implements SurfaceHolder.Callback {
private ImageView back, position;//返回和切換前后置攝像頭
private SurfaceView surface;
private ImageButton shutter;//快門
private SurfaceHolder holder;
private Camera camera;//聲明相機
private String filepath = "";//照片保存路徑
private int cameraPosition = 1;//0代表前置攝像頭,1代表后置攝像頭
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//沒有標題
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//設置全屏
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//拍照過程屏幕一直處于高亮
//設置手機屏幕朝向,一共有7種
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
//SCREEN_ORIENTATION_BEHIND: 繼承Activity堆棧中當前Activity下面的那個Activity的方向
//SCREEN_ORIENTATION_LANDSCAPE: 橫屏(風景照) ,顯示時寬度大于高度
//SCREEN_ORIENTATION_PORTRAIT: 豎屏 (肖像照) , 顯示時高度大于寬度
//SCREEN_ORIENTATION_SENSOR 由重力感應器來決定屏幕的朝向,它取決于用戶如何持有設備,當設備被旋轉時方向會隨之在橫屏與豎屏之間變化
//SCREEN_ORIENTATION_NOSENSOR: 忽略物理感應器——即顯示方向與物理感應器無關,不管用戶如何旋轉設備顯示方向都不會隨著改變("unspecified"設置除外)
//SCREEN_ORIENTATION_UNSPECIFIED: 未指定,此為默認值,由Android系統自己選擇適當的方向,選擇策略視具體設備的配置情況而定,因此不同的設備會有不同的方向選擇
//SCREEN_ORIENTATION_USER: 用戶當前的首選方向
setContentView(R.layout.main);
back = (ImageView) findViewById(R.id.camera_back);
position = (ImageView) findViewById(R.id.camera_position);
surface = (SurfaceView) findViewById(R.id.camera_surface);
shutter = (ImageButton) findViewById(R.id.camera_shutter);
holder = surface.getHolder();//獲得句柄
holder.addCallback(this);//添加回調
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//surfaceview不維護自己的緩沖區,等待屏幕渲染引擎將內容推送到用戶面前
//設置監聽
back.setOnClickListener(listener);
position.setOnClickListener(listener);
shutter.setOnClickListener(listener);
}
//響應點擊事件
OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.camera_back:
//返回
MyCameraActivity.this.finish();
break;
case R.id.camera_position:
//切換前后攝像頭
int cameraCount = 0;
CameraInfo cameraInfo = new CameraInfo();
cameraCount = Camera.getNumberOfCameras();//得到攝像頭的個數
for(int i = 0; i < cameraCount; i ) {
Camera.getCameraInfo(i, cameraInfo);//得到每一個攝像頭的信息
if(cameraPosition == 1) {
//現在是后置,變更為前置
if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表攝像頭的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
camera.stopPreview();//停掉原來攝像頭的預覽
camera.release();//釋放資源
camera = null;//取消原來攝像頭
camera = Camera.open(i);//打開當前選中的攝像頭
try {
camera.setPreviewDisplay(holder);//通過surfaceview顯示取景畫面
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();//開始預覽
cameraPosition = 0;
break;
}
} else {
//現在是前置, 變更為后置
if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表攝像頭的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
camera.stopPreview();//停掉原來攝像頭的預覽
camera.release();//釋放資源
camera = null;//取消原來攝像頭
camera = Camera.open(i);//打開當前選中的攝像頭
try {
camera.setPreviewDisplay(holder);//通過surfaceview顯示取景畫面
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();//開始預覽
cameraPosition = 1;
break;
}
}
}
break;
case R.id.camera_shutter:
//快門
camera.autoFocus(new AutoFocusCallback() {//自動對焦
@Override
public void onAutoFocus(boolean success, Camera camera) {
// TODO Auto-generated method stub
if(success) {
//設置參數,并拍照
Parameters params = camera.getParameters();
params.setPictureFormat(PixelFormat.JPEG);//圖片格式
params.setPreviewSize(800, 480);//圖片大小
camera.setParameters(params);//將參數設置到我的camera
camera.takePicture(null, null, jpeg);//將拍攝到的照片給自定義的對象
}
}
});
break;
}
}
};
/*surfaceHolder他是系統提供的一個用來設置surfaceView的一個對象,而它通過surfaceView.getHolder()這個方法來獲得。
Camera提供一個setPreviewDisplay(SurfaceHolder)的方法來連接*/
//SurfaceHolder.Callback,這是個holder用來顯示surfaceView 數據的接口,他必須實現以下3個方法
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
//當surfaceview創建時開啟相機
if(camera == null) {
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);//通過surfaceview顯示取景畫面
camera.startPreview();//開始預覽
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
//當surfaceview關閉時,關閉預覽并釋放資源
camera.stopPreview();
camera.release();
camera = null;
holder = null;
surface = null;
}
//創建jpeg圖片回調數據對象
PictureCallback jpeg = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//自定義文件保存路徑 以拍攝時間區分命名
filepath = "/sdcard/Messages/MyPictures/" new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) ".jpg";
File file = new File(filepath);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//將圖片壓縮的流里面
bos.flush();// 刷新此緩沖區的輸出流
bos.close();// 關閉此輸出流并釋放與此流有關的所有系統資源
camera.stopPreview();//關閉預覽 處理數據
camera.startPreview();//數據處理完后繼續開始預覽
bitmap.recycle();//回收bitmap空間
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}