Android開(kāi)發(fā)中經(jīng)常需要獲取攝像頭所支持的分辨率列表,然而獲取的參數(shù)列表是List形式,而且每個(gè)分辨率并不是按大小進(jìn)行排列,不方便查看和返回,所以寫(xiě)了一個(gè)重新排列并且格式化輸出的方法。
Camera.Parameters有三個(gè)方法獲取分辨率:
獲取攝像頭支持的視頻分辨率列表
getSupportedVideoSizes();
獲取攝像頭支持的圖像分辨率列表
getSupportedPictureSizes();
獲取攝像頭預(yù)覽分辨率(一般是預(yù)設(shè)的推薦分辨率)
getSupportedPreviewSizes();
理論上需要獲取預(yù)覽分辨率和支持分辨率兩個(gè)值,用來(lái)保證設(shè)置攝像頭的分辨率后不會(huì)出現(xiàn)一些玄學(xué)概率問(wèn)題(通常是攝像頭推薦的分辨率和最高分辨率的沖突),在實(shí)際開(kāi)發(fā)中我用getSupportedVideoSizes()和getSupportedPreviewSizes()死活獲取不到值,只能通過(guò)getSupportedPictureSizes()拉取列表,獲取到的分辨率也是一致的。
需要注意的是,CPU型號(hào)也會(huì)影響分辨率的獲取,同一個(gè)攝像頭在不同CPU上拉取到的支持分辨率是不一樣的,所以還需要對(duì)不同CPU機(jī)型的攝像頭分辨率進(jìn)行適配。
數(shù)據(jù)定義
public static List<Camera.Size> supportedVideoSizes;
public static List<Camera.Size> previewSizes;
獲取攝像頭信息,然后循環(huán)取最大的width和height,(最大值一般是List的第一個(gè)元素,可以直接get(0)),但是有些攝像頭拉去到的list是亂序的,所以對(duì)他們進(jìn)行重新按大小排序,方便取值。width*height就是攝像頭的像素,例如500百萬(wàn)像素。
public String getCameraInfo(){
int cameracount = 0;//攝像頭數(shù)量
Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); //獲取攝像頭信息
cameracount = Camera.getNumberOfCameras();
Log.i("CameraTest","攝像頭數(shù)量"+String.valueOf(cameracount));
for(int cameraId=0; cameraId<Camera.getNumberOfCameras(); cameraId++)
{
Camera.getCameraInfo( cameraId, cameraInfo);
Camera camera = Camera.open(cameraId); //開(kāi)啟攝像頭獲得一個(gè)Camera的實(shí)例
Camera.Parameters params = camera.getParameters(); //通過(guò)getParameters獲取參數(shù)
supportedVideoSizes = params.getSupportedPictureSizes();
previewSizes = params.getSupportedPreviewSizes();
camera.release();//釋放攝像頭
//重新排列后設(shè)下攝像頭預(yù)設(shè)分辨率在所有分辨率列表中的地址,用以選擇最佳分辨率(保證適配不出錯(cuò))
int index=bestVideoSize(previewSizes.get(0).width);
Log.i("CameraTest", "預(yù)覽分辨率地址: " + index );
if (null != previewSizes && previewSizes.size() > 0){ //判斷是否獲取到值,否則會(huì)報(bào)空對(duì)象
Log.i("CameraTest", "攝像頭最高分辨率寬: " + String.valueOf(supportedVideoSizes.get(0).width) ); //降序后取最高值,返回的是int類(lèi)型
Log.i("CameraTest", "攝像頭最高分辨率高: " + String.valueOf(supportedVideoSizes.get(0).height) );
Log.i("CameraTest", "攝像頭分辨率全部: " + cameraSizeToSting( supportedVideoSizes) );
}else{
Log.i("CameraTest", "沒(méi)取到值啊什么鬼" );
Log.i("CameraTest", "攝像頭預(yù)覽分辨率: " + String.valueOf(previewSizes.get(0).width) );
}
}
return cameraSizeToSting( supportedVideoSizes );
}
重新排列分辨率列表
//重新排列獲取到的分辨率列表
public static int bestVideoSize(int _wid) {
//降序排列
Collections.sort(supportedVideoSizes, new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size lhs, Camera.Size rhs) {
if (lhs.width > rhs.width) {
return -1;
} else if (lhs.width == rhs.width) {
return 0;
} else {
return 1;
}
}
});
for (int i = 0; i < supportedVideoSizes.size(); i++) {
if (supportedVideoSizes.get(i).width < _wid) {
return i;
}
}
return 0;
}
格式化輸出成常見(jiàn)的寬x高格式
//分辨率格式化輸出String值
public static String cameraSizeToSting(Iterable<Camera.Size> sizes)
{
StringBuilder s = new StringBuilder();
for (Camera.Size size : sizes)
{
if (s.length() != 0)
s.append(",\n");
s.append(size.width).append('x').append(size.height);
}
return s.toString();
}
使用完相機(jī)之后一定要記得用 Camera.release()來(lái)釋放相機(jī)的實(shí)例,否則后續(xù)調(diào)用相機(jī)的請(qǐng)求(系統(tǒng)內(nèi)其他app或本應(yīng)用)都會(huì)失敗,導(dǎo)致Camera.open()方法報(bào)錯(cuò)“Failed to connect to camera service”。所以同理,出現(xiàn)這種問(wèn)題的時(shí)候也可以排查系統(tǒng)中其他apps是否正在占用攝像頭沒(méi)有釋放。
在Android 6.0版本的攝像頭開(kāi)發(fā)中,使用Camera.open()方法時(shí),需要在onCreate()方法中加入下面的權(quán)限申請(qǐng),否則同樣會(huì)報(bào)錯(cuò)"Failed to connect to camera service"
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//android6.0需要加申請(qǐng)權(quán)限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[] {Manifest.permission.CAMERA}, 1);
}
}
}
運(yùn)行結(jié)果如下
