Android自定義Camera實(shí)現(xiàn)拍照小功能
本文實(shí)例為大家分享了Android自定義Camera實(shí)現(xiàn)拍照的具體代碼,供大家參考,具體內(nèi)容如下
本篇文章就項(xiàng)目開發(fā)遇到問題記錄下;
1.拍照?qǐng)D片被壓縮問題
2.拍照?qǐng)D片被旋轉(zhuǎ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: ?看看退出到其他頁面是否有黑屏現(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)回來的圖片數(shù)據(jù)
public void onPictureTaken(final byte[] bytes,final Camera camera){
? ?// 拍照回掉回來的 圖片數(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();
}接下來要說的就是我們上面說到的保存圖片被旋轉(zhuǎ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();
? ? }*#額外要說明的是,android 6.0權(quá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);
? ? }以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android入門之PopupWindow用法實(shí)例解析
這篇文章主要介紹了Android入門之PopupWindow用法,對(duì)于Android初學(xué)者來說有一定的學(xué)習(xí)借鑒價(jià)值,需要的朋友可以參考下2014-08-08
Android中的深度鏈接技術(shù)實(shí)戰(zhàn)
本文主要介紹了Android中的深度鏈接技術(shù)實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Flutter實(shí)戰(zhàn)教程之酷炫的開關(guān)動(dòng)畫效果
這篇文章主要給大家介紹了關(guān)于Flutter實(shí)戰(zhàn)教程之酷炫的開關(guān)動(dòng)畫效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Android 雙進(jìn)程守護(hù)的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 雙進(jìn)程守護(hù)的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08
Android中用Builder模式自定義Dialog的方法
在任何軟件操作系統(tǒng)中,Dialog即對(duì)話框都是一種重要的交互模式與信息載體,而Android系統(tǒng)本身的Dialog擁有固定的樣式,并且在5.0后采用Material Design設(shè)計(jì)風(fēng)格的Dialog美觀大氣。這篇文章將詳細(xì)介紹Android中用Builder模式自定義Dialog的方法,有需要的可以參考借鑒。2016-10-10
RecyclerView實(shí)現(xiàn)側(cè)滑和網(wǎng)絡(luò)斷點(diǎn)續(xù)傳
這篇文章主要為大家詳細(xì)介紹了RecyclerView實(shí)現(xiàn)側(cè)滑和網(wǎng)絡(luò)斷點(diǎn)續(xù)傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
Android開發(fā)實(shí)現(xiàn)在TextView前面加標(biāo)簽示例
這篇文章主要為大家介紹了Android開發(fā)實(shí)現(xiàn)TextView前面加標(biāo)簽示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
android?studio實(shí)驗(yàn):?UI設(shè)計(jì)?ListView及事件響應(yīng)
這篇文章主要介紹了android?studio實(shí)驗(yàn):?UI設(shè)計(jì)?ListView及事件響應(yīng),主要是ListView及其事件響應(yīng)方法?彈出菜單PopupMenu及其事件響應(yīng)方法,下面來看看具文章體的介紹吧2021-12-12
Android開發(fā)基礎(chǔ)使用ProgressBar加載進(jìn)度條示例
這篇文章主要介紹了安卓開發(fā)基礎(chǔ)使用ProgressBar加載進(jìn)度條示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02

