網站首頁 編程語言 正文
本文實例為大家分享了Android自定義Camera實現拍照的具體代碼,供大家參考,具體內容如下
本篇文章就項目開發遇到問題記錄下;
1.拍照圖片被壓縮問題
2.拍照圖片被旋轉問題
首先實現一個自定義拍照功能。
自定義布局
<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) {
? ? ? ?// 當holder被回收時 釋放硬件
? ? ? ?// ? releaseCamera();
? ?}
? ? ?@Override
? ? protected void onPause() {
? ? ? ? super.onPause();
? ? ? ? releaseCameraSource();
? ? }
? @Override
? ? protected void onResume() {
? ? ? ? super.onResume();
? ? ? ? // TODO: ?看看退出到其他頁面是否有黑屏現象
? ? ? ? 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);
? ? ? ? ? ? }
? ? ? ? ? ? // 設置對焦模式
? ? ? ? ? ? List<String> supportedFocusModes = parameters.getSupportedFocusModes();
? ? ? ? ? ? if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
? ? ? ? ? ? ? ? // 快速對焦
? ? ? ? ? ? ? ? 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;
? ? ? ? }
? ? }
調用相機的拍攝功能:
點擊拍照調用camera.takePicture(null,null,this);
獲取拍照回調回來的圖片數據
public void onPictureTaken(final byte[] bytes,final Camera camera){
? ?// 拍照回掉回來的 圖片數據。
? ? ? ? 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();
}
接下來要說的就是我們上面說到的保存圖片被旋轉的問題:
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();
? ? }
*#額外要說明的是,android 6.0權限問題,可能會導致首次進入拍照界面黑屏,解決方案在拍照界面之前請求權限;
最后附上請求權限代碼:
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("設置", 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);
? ? }
原文鏈接:https://blog.csdn.net/qq_31664497/article/details/80020524
相關推薦
- 2022-04-02 Python+Tkinter繪制一個數字時鐘_python
- 2022-09-28 C++List容器常用函數接口刨析_C 語言
- 2022-04-19 C#中的類繼承詳解_C#教程
- 2022-05-13 python實現簡易圖書管理系統_python
- 2022-11-20 Rust指南之泛型與特性詳解_Rust語言
- 2023-11-13 matplotlib圖例(legend)如何自由設置其位置、大小以及樣式
- 2023-03-04 Google大佬都用的廣播goAsync源碼分析_Android
- 2023-05-10 clickhouse系統表日志清理方式詳解_數據庫其它
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支