[安卓開發基礎] 拍照Camera
阿新 • • 發佈:2019-01-13
安卓 6.0 以上除了清單檔案申明許可權外,還要動態申請許可權。
<!-- 授予程式可以向SD卡中儲存檔案的許可權 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 授予程式使用攝像頭的許可權 --> <uses-permission android:name="android.permission.CAMERA"/> <uses-feature android:name="android.hardware.camera.autofocus"/> <uses-feature android:name="android.hardware.camera"/>
1.幀布布局:
package com.camera; import android.Manifest; import android.annotation.SuppressLint; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.widget.ImageButton; import android.widget.Toast; import com.zengjx.androidbaseproject.R; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import permissions.dispatcher.NeedsPermission; import permissions.dispatcher.OnShowRationale; import permissions.dispatcher.RuntimePermissions; import permissions.dispatcher.PermissionRequest; @RuntimePermissions public class CameraActivity extends AppCompatActivity { private ImageButton imageButton_Camera,imageButton_PreView; private SurfaceView surfaceView; SurfaceHolder surfaceHolder; private boolean isPreView=false; private Camera camera; private final String TAG="CameraActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); setTitle("相機"); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); //sdcard if(!android.os.Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ Toast.makeText(this,"SD未安裝",Toast.LENGTH_SHORT).show(); } initView(); } //實現將照片儲存到系統圖庫中 final Camera.PictureCallback jpeg2 = new Camera.PictureCallback() { //照片回撥函式 @Override public void onPictureTaken(byte[] data, Camera camera) { // 根據拍照所得的資料建立點陣圖 final Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length); camera.stopPreview(); //停止預覽 isPreView = false; //設定為非預覽狀態 //獲取sd卡根目錄 File appDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/Camera/"); if (!appDir.exists()) { //如果該目錄不存在 appDir.mkdir(); //就建立該目錄 } String fileName = System.currentTimeMillis() + ".jpg"; //將獲取當前系統時間設定為照片名稱 File file = new File(appDir, fileName); //建立檔案物件 try { //儲存拍到的圖片 FileOutputStream fos = new FileOutputStream(file); //建立一個檔案輸出流物件 bm.compress(Bitmap.CompressFormat.JPEG, 100, fos); //將圖片內容壓縮為JPEG格式輸出到輸出流物件中 fos.flush(); //將緩衝區中的資料全部寫出到輸出流中 fos.close(); //關閉檔案輸出流物件 } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //將照片插入到系統圖庫 try { MediaStore.Images.Media.insertImage(CameraActivity.this.getContentResolver(), file.getAbsolutePath(), fileName, null); } catch (FileNotFoundException e) { e.printStackTrace(); } // 最後通知相簿更新 CameraActivity.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + ""))); Toast.makeText(CameraActivity.this, "照片儲存至:" + file, Toast.LENGTH_LONG).show(); resetCamera(); //呼叫重新預覽resetCamera()方法 } }; final Camera.PictureCallback jpeg = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] bytes, Camera camera) { //1根據拍照建立點陣圖物件 final Bitmap bitmap= BitmapFactory.decodeByteArray(bytes,0,bytes.length); camera.stopPreview(); // 2停止預覽 //3標誌位 復位為 非預覽 isPreView=false; //4獲取Sd 目錄 目錄不存在 建立目錄 // String dir=Environment.getExternalStorageDirectory(),"/DICM/Camera/"; // Log.i(TAG,"dir="+dir); File appDir=new File( Environment.getExternalStorageDirectory(),"/DICM/Camera/"); if(!appDir.exists()){ Log.i(TAG,"建立目錄"); appDir.mkdir();//目錄不存在建立 Log.i(TAG,"建立目錄--2"+appDir.exists()); }else{ Log.i(TAG,"目錄存在"); } //儲存拍到的圖片 String fileName=System.currentTimeMillis()+".jpg";//系統時間作為圖片名稱 File file= new File(appDir,fileName);//建立檔案物件 try{ //拍到圖片 FileOutputStream fos =new FileOutputStream(file); //建立檔案輸出流物件 //將圖片壓縮為JPEG 格式 輸出到檔案輸出流 bitmap.compress(Bitmap.CompressFormat.JPEG,100,fos); fos.flush();//將緩衝區中的資料全部寫出到輸出流中 fos.close();//關閉檔案輸出流物件 Log.i(TAG,"關閉檔案輸出流物件"); }catch (FileNotFoundException e){ e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //將圖片插入到系統圖庫 try{ MediaStore.Images.Media.insertImage(CameraActivity.this.getContentResolver(), file.getAbsolutePath(), fileName, null); }catch (FileNotFoundException e){ e.printStackTrace(); } //最後通知相簿更新 // CameraActivity.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+""))); // 最後通知相簿更新 CameraActivity.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + ""))); Toast.makeText(CameraActivity.this,"圖片儲存至"+file,Toast.LENGTH_SHORT).show(); resetCamera();//重新預覽 } }; public void resetCamera(){ if(!isPreView){ isPreView=true; camera.startPreview(); } } public void initView(){ surfaceView =(SurfaceView) findViewById(R.id.surface); //獲取 SurfaceHolder surfaceHolder =surfaceView.getHolder(); //設定 sufaceholder 不自己維護緩衝 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); imageButton_Camera= (ImageButton) findViewById(R.id.btn_camera) ; imageButton_PreView= (ImageButton)findViewById(R.id.btn_preview); imageButton_Camera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(camera!=null){ camera.takePicture(null,null,jpeg); } } }); imageButton_PreView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(!isPreView){ // cameratest(); // checkselfPermisssion2(); cameratest(); } } }); } /* @NeedsPermission(Manifest.permission.CAMERA,Manifest.p) void camera() { { camera=Camera.open(); if(camera==null){ Toast.makeText(this,"無許可權",Toast.LENGTH_SHORT).show(); return; } isPreView=true; try { camera.setPreviewDisplay(surfaceHolder); //獲取攝像頭引數 Camera.Parameters parameters = camera.getParameters(); parameters.setPictureSize(640,480); parameters.setPictureFormat(PixelFormat.JPEG); parameters.set("jpeg-quality",80); //重新設定攝像頭引數 camera.setParameters(parameters);//重新設定預覽 camera.startPreview();//開始預覽 camera.autoFocus(null);//設定自動對焦 } catch (IOException e) { e.printStackTrace(); } } } */ @SuppressLint("NeedOnRequestPermissionsResult") @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); CameraActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults); } @OnShowRationale(Manifest.permission.CAMERA) void camera_show(PermissionRequest request) { } @NeedsPermission({Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}) void cameratest() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1); camera=Camera.open(); if(camera==null){ Toast.makeText(this,"無許可權",Toast.LENGTH_SHORT).show(); return; }else{ Toast.makeText(this,"開啟成功",Toast.LENGTH_SHORT).show(); } isPreView=true; try { camera.setPreviewDisplay(surfaceHolder); //獲取攝像頭引數 Camera.Parameters parameters = camera.getParameters(); // parameters.setPictureSize(480,480); parameters.setPictureFormat(PixelFormat.JPEG); parameters.set("jpeg-quality",80); //重新設定攝像頭引數 camera.setParameters(parameters);//重新設定預覽 camera.startPreview();//開始預覽 camera.autoFocus(null);//設定自動對焦 } catch (IOException e) { e.printStackTrace(); } Toast.makeText(this,"cameratest",Toast.LENGTH_SHORT).show(); } @OnShowRationale({Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}) void cameratest_show(final PermissionRequest request) { Toast.makeText(this,"cameratest_show",Toast.LENGTH_SHORT).show(); } //當停止Activity 暫停時候 停止 @Override protected void onPause() { //當暫停Activity時,停止預覽並釋放資源 if (camera != null) { //如果相機不為空 Toast.makeText(this,"onPause!!!!!",Toast.LENGTH_SHORT).show(); // camera.stopPreview(); //停止預覽---這種方式在 安卓6.0 7.0 會不顯示預覽介面 // camera.release(); //釋放資源 } super.onPause(); } @Override protected void onStop() { Toast.makeText(this,"onStop!!!!!",Toast.LENGTH_SHORT).show(); // camera.stopPreview(); //停止預覽-- 安卓6.0 7.0 會不顯示預覽介面 // camera.release(); //釋放資源 super.onStop(); } @Override protected void onDestroy() { Toast.makeText(this,"onDestroy!!!!!",Toast.LENGTH_SHORT).show(); camera.stopPreview(); //停止預覽 camera.release(); //釋放資源 super.onDestroy(); } public void checkselfPermisssion2(){ if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { //第一次全新進入時,shouldShowRequestPermissionRationale方法將返回false,這裡將會執行。 //請求許可權時如果點了拒絕但是沒勾選不再提醒,shouldShowRequestPermissionRationale方法將返回true,這裡將不執行。 //點了拒絕且勾選了不再提醒,再次進入時,shouldShowRequestPermissionRationale方法也將返回false,並且許可權請求將無任何響應,然後可以在下面方法中做些處理,提示使用者開啟許可權。 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);//1 表示使用者唯一標識一個許可權請求以便回撥時進行判斷 Log.i("permission","request"); } else { Log.i("permission","request2"); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1); } } } }