Android自定義Camera實(shí)現(xiàn)拍照小功能
本文實(shí)例為大家分享了Android自定義Camera實(shí)現(xiàn)拍照的具體代碼,供大家參考,具體內(nèi)容如下
本篇文章就項(xiàng)目開(kāi)發(fā)遇到問(wèn)題記錄下;
1.拍照?qǐng)D片被壓縮問(wèn)題
2.拍照?qǐng)D片被旋轉(zhuǎn)問(wèn)題
首先實(shí)現(xiàn)一個(gè)自定義拍照功能。
自定義布局
<FrameLayout ? ? ? ? android:layout_below="@id/toolbar_layout" ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="match_parent" > ? ? ? ? <SurfaceView ? ? ? ? ? ? android:id="@+id/surface" ? ? ? ? ? ? android:layout_width="match_parent" ? ? ? ? ? ? android:layout_height="match_parent" ? ? ? ? ? ? android:keepScreenOn="true"/> ? ? </FrameLayout>
初始化控件:
surfaceView = (SurfaceView) findViewById(R.id.surface);
holder = surfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
btn.setOnCLickListener(new OnClickLister(View v){
? ? if(mCamera == null){
? ? ? ? mCamera = Camera.open();
? ? }
mCamera.takePicture(null,null,this);
});
?@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
? ? ? initStartCamera(surfaceHolder);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
? ? ? ? ? mCamera.autoFocus(new Camera.AutoFocusCallback() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onAutoFocus(boolean success, Camera camera) {
? ? ? ? ? ? ? ? isAutoFocus = success;
? ? ? ? ? ? ? ? initCameraParams();
? ? ? ? ? ? ? ? mCamera.cancelAutoFocus();
? ? ? ? ? ? ? ? mCamera.startPreview();
? ? ? ? ? ? }
? ? ? ? });
}
@Override
? ?public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
? ? ? ?// 當(dāng)holder被回收時(shí) 釋放硬件
? ? ? ?// ? releaseCamera();
? ?}
? ? ?@Override
? ? protected void onPause() {
? ? ? ? super.onPause();
? ? ? ? releaseCameraSource();
? ? }
? @Override
? ? protected void onResume() {
? ? ? ? super.onResume();
? ? ? ? // TODO: ?看看退出到其他頁(yè)面是否有黑屏現(xiàn)象
? ? ? ? if (surfaceView != null) {
? ? ? ? ? ? surfaceView.postDelayed(new Runnable() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? initCameraParams();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }, 50);
? ? ? ? }
? ? }
? private void initStartCamera(SurfaceHolder surfaceHolder) {
? ? ? ? try {
? ? ? ? ? ? mCamera = Camera.open();
? ? ? ? ? ? mCamera.setDisplayOrientation(90);
? ? ? ? ? ? mCamera.setPreviewDisplay(surfaceHolder);
? ? ? ? ? ? mCamera.startPreview();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
private void initCameraParams() {
? ? ? ? if (mCamera != null) {
? ? ? ? ? ? Camera.Parameters parameters = mCamera.getParameters();
? ? ? ? ? ? parameters.setPictureFormat(ImageFormat.JPEG);
? ? ? ? ? ? parameters.setJpegQuality(90);
? ? ? ? ? ? List<Camera.Size> supportedPictureSizes = parameters.getSupportedPictureSizes();
? ? ? ? ? ? WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
? ? ? ? ? ? Display display = manager.getDefaultDisplay();
? ? ? ? ? ? Point point = new Point();
? ? ? ? ? ? display.getSize(point);
? ? ? ? ? ? int screenWidth = point.x;
? ? ? ? ? ? int screenHeight = point.y;
? ? ? ? ? ? // 找到適合的圖片的尺寸
? ? ? ? ? ? if (supportedPictureSizes != null && !supportedPictureSizes.isEmpty()) {
? ? ? ? ? ? ? ? int screenSize = screenHeight * screenWidth;
? ? ? ? ? ? ? ? Camera.Size picSize = null;
? ? ? ? ? ? ? ? for (Camera.Size size : supportedPictureSizes) {
? ? ? ? ? ? ? ? ? ? int value = size.height * size.width;
? ? ? ? ? ? ? ? ? ? if (value <= screenSize) {
? ? ? ? ? ? ? ? ? ? ? ? if (picSize == null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? picSize = size;
? ? ? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 取最接近屏幕尺寸的
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (value > picSize.width * picSize.height) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? picSize = size;
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (picSize == null) {
? ? ? ? ? ? ? ? ? ? picSize = supportedPictureSizes.get(0);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? parameters.setPictureSize(picSize.width, picSize.height);
? ? ? ? ? ? }
? ? ? ? ? ? // 設(shè)置對(duì)焦模式
? ? ? ? ? ? List<String> supportedFocusModes = parameters.getSupportedFocusModes();
? ? ? ? ? ? if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
? ? ? ? ? ? ? ? // 快速對(duì)焦
? ? ? ? ? ? ? ? parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? parameters.setFocusMode(Camera.Parameters.FLASH_MODE_AUTO);
? ? ? ? ? ? }
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? mCamera.setParameters(parameters);
? ? ? ? ? ? ? ? mCamera.startPreview();
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
?private void releaseCameraSource() {
? ? ? ? if (mCamera != null) {
? ? ? ? ? ? mCamera.setPreviewCallback(null);
? ? ? ? ? ? mCamera.stopPreview();
? ? ? ? ? ? mCamera.release();
? ? ? ? ? ? mCamera = null;
? ? ? ? }
? ? }調(diào)用相機(jī)的拍攝功能:
點(diǎn)擊拍照調(diào)用camera.takePicture(null,null,this);
獲取拍照回調(diào)回來(lái)的圖片數(shù)據(jù)
public void onPictureTaken(final byte[] bytes,final Camera camera){
? ?// 拍照回掉回來(lái)的 圖片數(shù)據(jù)。
? ? ? ? final String filePath = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/";
? ? ? ? final String picturePath = System.currentTimeMillis() + ".jpg";
? ? ? ? final File file = new File(filePath, picturePath);
? ? ? ? new Thread(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
? ? ? ? ? ? ? ? bitmap = rotateBitmapByDegree(bitmap, 90);
? ? ? ? ? ? ? ? BufferedOutputStream bos = null;
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? //防止拍照保存圖片被壓縮
? ? ? ? ? ? ? ? ? ? bos = new BufferedOutputStream(new FileOutputStream(file));
? ? ? ? ? ? ? ? ? ? bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
? ? ? ? ? ? ? ? ? ? bos.flush();
? ? ? ? ? ? ? ? ? ? bos.close();
? ? ? ? ? ? ? ? ? ? bitmap.recycle();
? ? ? ? ? ? ? ? ? ? Intent intent = new Intent(TakePhotoActivity.this,TPreViewPicActivity.class);
? ? ? ? ? ? ? ? ? ? intent.putExtra("filePath",filePath);
? ? ? ? ? ? ? ? ? ? intent.putExtra("picturePath",picturePath);
? ? ? ? ? ? ? ? ? ? startActivityForResult(intent,102);
? ? ? ? ? ? ? ? } catch (FileNotFoundException e1) {
? ? ? ? ? ? ? ? ? ? e1.printStackTrace();
? ? ? ? ? ? ? ? } catch (IOException e1) {
? ? ? ? ? ? ? ? ? ? e1.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }).start();
}接下來(lái)要說(shuō)的就是我們上面說(shuō)到的保存圖片被旋轉(zhuǎn)的問(wèn)題:
public Bitmap rotateBitmapByDegree(Bitmap bm,int degree){
? Bitmap bitmap ;
? Matrix matrix = new Matrix();
? matrix.postRotate(degree);
? try{
? bitmap ?= Bitmap.createBitmap(bm,0,bm.getWidth,bm.getHeight,matrix,true);
}catch(OutOfMemoryError e){
? e.printStackTrace();
}
if(bitmap == null){
bitmap = bm;
}
if(bm != bitmap){
?bm.recycle();
}
return bitmap;
}
@Override
public void onPause(){
super.onPause();
if(camera != null){
? ? if(isPrevew){
? ? ? ? camera.stopPreview();
? ? ? ? camera.release();
? ? ? ? camera= null;
? ? ? ? isPreView= false;
? ? }
?}
}
@Override
? ? protected void onResume() {
? ? ? ? super.onResume();
? ? ? ? openCamera();
? ? }*#額外要說(shuō)明的是,android 6.0權(quán)限問(wèn)題,可能會(huì)導(dǎo)致首次進(jìn)入拍照界面黑屏,解決方案在拍照界面之前請(qǐng)求權(quán)限;
最后附上請(qǐng)求權(quán)限代碼:
public void checkPermission() {
? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
? ? ? ? ? ? requestPermissions(new String[]{Manifest.permission.CAMERA}
? ? ? ? ? ? ? ? ? ? , new TCallPhoneTool.PermissionListener() {
? ? ? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? ? ? public void onGranted() {
// ? ? ? ? ? ? ? ? ? ? ? ? ? ?openCamera();
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? ? ? public void onRefused(List<String> deniedPermissions) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? showMissingPermissionDialog();
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? });
? ? ? ? } else {
// ? ? ? ? ? ?openCamera();
? ? ? ? }
? ? }
? TCallPhoneTool.PermissionListener mListener ;
? ? final int REQUEST_CODE_STORAGE = 131;
? ? public void requestPermissions(String[] permissions, TCallPhoneTool.PermissionListener listener) {
? ? ? ? List<String> deniedPermissions = new ArrayList<>() ;
? ? ? ? mListener = listener ;
? ? ? ? for (String permission : permissions) {
? ? ? ? ? ? if (ContextCompat.checkSelfPermission(this,permission) == PackageManager.PERMISSION_DENIED) {
? ? ? ? ? ? ? ? deniedPermissions.add(permission);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if (deniedPermissions.size() > 0) {
? ? ? ? ? ? ActivityCompat.requestPermissions(this,deniedPermissions.toArray(new String[deniedPermissions.size()]),REQUEST_CODE_STORAGE);
? ? ? ? } else {
? ? ? ? ? ? mListener.onGranted();
? ? ? ? }
? ? }
? ?public void showMissingPermissionDialog() {
? ? ? ? android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(this);
? ? ? ? builder.setTitle(getString(com.to8to.baselib.R.string.tip_permision_miss));
? ? ? ? builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(DialogInterface dialog, int which) {
? ? ? ? ? ? ? ? finish();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? builder.setPositiveButton("設(shè)置", new DialogInterface.OnClickListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(DialogInterface dialog, int which) {
? ? ? ? ? ? ? ? startAppSetting();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? builder.setCancelable(false);
? ? ? ? builder.show();
? ?public void startAppSetting() {
? ? ? ? Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
? ? ? ? intent.setData(Uri.parse("package:" + this.getPackageName()));
? ? ? ? startActivity(intent);
? ? }以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
 使用Fragment來(lái)處理Andoird app的UI布局的實(shí)例分享
這篇文章主要介紹了使用Fragment來(lái)處理Andoird appUI布局的實(shí)例分享,Fragment的出現(xiàn)緩解了代碼依賴于Activity而造成的臃腫狀況,需要的朋友可以參考下2016-02-02
 Android ScrollView無(wú)法填充滿屏幕的解決辦法
這篇文章主要介紹了Android ScrollView無(wú)法填充滿屏幕的解決辦法的相關(guān)資料,這里提供實(shí)例和解決辦法,需要的朋友可以參考下2017-07-07
 Android實(shí)現(xiàn)可收縮和擴(kuò)展的TextView
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)可收縮和擴(kuò)展的TextView,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
 Android沉浸式狀態(tài)欄實(shí)現(xiàn)示例
本篇文章主要介紹了Android沉浸式狀態(tài)欄實(shí)現(xiàn)示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
 Android WebView userAgent 設(shè)置為桌面UA實(shí)例
這篇文章主要介紹了Android WebView userAgent 設(shè)置為桌面UA實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
 Android實(shí)現(xiàn)獲取未接來(lái)電和未讀短信數(shù)量的方法
這篇文章主要介紹了Android實(shí)現(xiàn)獲取未接來(lái)電和未讀短信數(shù)量的方法,是Android程序開(kāi)發(fā)中非常常見(jiàn)的重要功能,需要的朋友可以參考下2014-08-08

