1. 程式人生 > >[安卓開發基礎] 拍照Camera

[安卓開發基礎] 拍照Camera

安卓 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);



            }
        }


    }
}