1. 程式人生 > >Android 自定義相機Demo 入門學習

Android 自定義相機Demo 入門學習

Android 自定義相機Demo

本文是參考網上一些自定義相機示例,再結合自己對相機的功能需求寫的,基本上包含了很多基本功能,比如相機對焦、閃光燈,以及在手機預覽介面上繪製自己想要繪製的圖案。

話不多說,先上一張圖:
相機應用介面

應用是在Android Studio中開發的,java程式如下:

//主程式
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import
android.graphics.ImageFormat; import android.hardware.Camera; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; import android.widget.ImageView; import java.io.File; import
java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @SuppressLint("NewApi") public class CameraActivity extends AppCompatActivity { protected static final String TAG = "main"; private Camera mCamera; private CameraPreview mPreview; private static
int Cur_State = 0; public ImageView imgDu; public File pictureFile; Draw draw; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); imgDu = (ImageView) findViewById(R.id.img1); mCamera = getCameraInstance(); draw = new Draw(CameraActivity.this); // 建立預覽類,並與Camera關聯,最後新增到介面佈局中 mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); preview.addView(draw); Button captureButton = (Button) findViewById(R.id.button_capture); //button_capture captureButton.setOnClickListener(new View.OnClickListener() { @SuppressWarnings("deprecation") @Override public void onClick(View v) { Camera.Parameters parameters = mCamera.getParameters(); // 設定相片格式 parameters.setJpegQuality(100); //生成影象的質量 mCamera.setParameters(parameters); parameters.setPictureFormat(ImageFormat.JPEG); // 設定預覽大小 parameters.setPreviewSize(800, 480); parameters.setPictureSize(4160, 3120); //生成影象的風辨率 mCamera.setParameters(parameters); parameters.setRotation(90); //生成的影象旋轉90度 mCamera.setParameters(parameters); parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); mCamera.setParameters(parameters); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // 從Camera捕獲圖片 mCamera.takePicture(null, null, mPicture); } }); /*if (Cur_State < 2) { switch (Cur_State) { case 0: parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); mCamera.setParameters(parameters); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // 從Camera捕獲圖片 mCamera.takePicture(null, null, mPicture); } }); Cur_State++; break; case 1: parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);//FLASH_MODE_OFF mCamera.setParameters(parameters); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // 從Camera捕獲圖片 mCamera.takePicture(null, null, mPicture); } }); Cur_State++; break; } } else { Cur_State = 0; }*/ } }); } /** 檢測裝置是否存在Camera硬體 */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_CAMERA)) { // 存在 return true; } else { // 不存在 return false; } } /** 開啟一個Camera */ public static Camera getCameraInstance() { Camera c = null; try { c = Camera.open(); } catch (Exception e) { Log.d(TAG, "開啟Camera失敗失敗"); } return c; } private Camera.PictureCallback mPicture = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera arg1) { //將拍照得到的資料資訊儲存到本地 File tempFile=new File("/sdcard/temp.png"); try { FileOutputStream fos=new FileOutputStream(tempFile); fos.write(data); fos.close(); //注意,,,然後將這個照片的資料資訊傳送給要進行展示的Activity即可,這部 //分程式碼是我自己需要的,你使用時需要將他去掉修改成你的。 Intent intent=new Intent(CameraActivity.this,MainActivity.class); intent.putExtra("PicturePath", tempFile.getAbsolutePath()); startActivity(intent); //拍照結束之後銷燬當前的Activity,進入到圖片展示介面 CameraActivity.this.finish(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; @Override protected void onDestroy() { // 回收Camera資源 if(mCamera!=null){ mCamera.stopPreview(); mCamera.release(); mCamera=null; } super.onDestroy(); } }
/**
 * 定義一個預覽類  預覽介面設定
 */
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;

@SuppressLint("NewApi")
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = "main";
    private SurfaceHolder mHolder;
    @SuppressWarnings("deprecation")
    private Camera mCamera;

    @SuppressWarnings("deprecation")
    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        // 通過SurfaceView獲得SurfaceHolder
        mHolder = getHolder();
        // 為SurfaceHolder指定回撥
        mHolder.addCallback(this);
        mCamera.setDisplayOrientation(90);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // 當Surface被建立之後,開始Camera的預覽
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "預覽失敗");
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Surface發生改變的時候將被呼叫,第一次顯示到介面的時候也會被呼叫
        if (mHolder.getSurface() == null){
            // 如果Surface為空,不繼續操作
            return;
        }

        // 停止Camera的預覽
        try {
            mCamera.stopPreview();

        } catch (Exception e){
            Log.d(TAG, "當Surface改變後,停止預覽出錯");
        }

        // 重新開始預覽
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "預覽Camera出錯");
        }
    }
}
/**
 * Created by Administrator on 2018/1/24.
 * 這個是在預覽介面繪製圖案部分
 */
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.View;

public class Draw extends View
{
    private Canvas canvas;//宣告畫筆
    private Paint paint;//宣告畫布
    private Paint paint1;
    private Paint paint2;

    private Bitmap bitmap;//宣告點陣圖

    public Draw(Context context)
    {
        super(context);
        // TODO 自動生成的建構函式存根
        //建立一個畫筆
        paint = new Paint(Paint.DITHER_FLAG);
        paint1 = new Paint(Paint.DITHER_FLAG);
        paint2 = new Paint(Paint.DITHER_FLAG);
        //設定點陣圖的寬高,採用32位ARGB點陣圖模式
        bitmap = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(bitmap);

        paint.setStyle(Paint.Style.STROKE);//設定非填充
        paint.setStrokeWidth(2);//筆寬5畫素
        paint.setColor(Color.RED);//設定為紅筆
        paint.setAntiAlias(true);//鋸齒不顯示
        paint.setDither(true);//設定影象抖動處理
        paint.setStrokeJoin(Paint.Join.ROUND);//設定影象的結合方式
        paint.setStrokeCap(Paint.Cap.ROUND);//設定畫筆為圓形樣式

        paint1.setStyle(Paint.Style.FILL);//設定非填充
        paint1.setStrokeWidth(33);//筆寬5畫素
        paint1.setStrokeJoin(Paint.Join.ROUND);//設定影象的結合方式
        paint1.setStrokeCap(Paint.Cap.ROUND);//設定畫筆為圓形樣式
        paint1.setColor(Color.BLACK);//設定為黑筆
        paint.setAntiAlias(true);//鋸齒不顯示
        paint.setDither(true);//設定影象抖動處理

        paint2.setStyle(Paint.Style.FILL);//設定填充
        paint2.setStrokeWidth(12);//筆寬5畫素
        paint2.setAntiAlias(true);//鋸齒不顯示
        paint2.setDither(true);//設定影象抖動處理
        paint2.setStrokeJoin(Paint.Join.ROUND);//設定影象的結合方式
        paint2.setStrokeCap(Paint.Cap.ROUND);//設定畫筆為圓形樣式
        paint2.setColor(Color.BLACK);//設定為黑筆
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas)
    {
        // TODO 自動生成的方法存根
        super.onDraw(canvas);
        canvas.drawBitmap(bitmap, 0, 0, paint);

        float[] pts = {0,240,260,70};
        canvas.drawLines(pts , paint);   //在畫布上畫線  1
        float[] pts2 = {695,522,340,1040};
        canvas.drawLines(pts2, paint);   //在畫布上畫線 2

        Path mPath = new Path();
        mPath.moveTo(260, 70);
        mPath.quadTo(780, 0, 695, 522);
        canvas.drawPath(mPath, paint);    //塞爾塔曲線

        Path path = new Path();      //定義一條路徑
        path.moveTo(0,0);      //移動到 座標(0,0)
        path.lineTo(0,240);
        path.lineTo(270,62);
        path.lineTo(270,0);
        path.lineTo(0,0);
        canvas.drawPath(path, paint2);

        Path path1 = new Path();      //定義一條路徑
        path1.moveTo(260,0);    //移動到 座標(260,0)
        path1.lineTo(720,0);
        path1.lineTo(720,60);
        path1.lineTo(260,60);
        path1.lineTo(260,0);
        canvas.drawPath(path1, paint2);

        Path path2 = new Path();       //定義一條路徑
        path2.moveTo(720,60);    //移動到 座標(720,60)
        path2.lineTo(720,522);
        path2.lineTo(715,522);
        path2.lineTo(715,512);
        path2.lineTo(700,60);
        path2.lineTo(720,60);
        canvas.drawPath(path2, paint2);

        Path path3 = new Path();        //定義一條路徑
        path3.moveTo(340,1040);   //移動到 座標(340,1040)
        path3.lineTo(720,1040);
        path3.lineTo(720,522);
        path3.lineTo(710,512);
        path3.lineTo(340,1040);
        canvas.drawPath(path3, paint2);

        Path path4 = new Path();        //定義一條路徑
        path4.moveTo(720,200);   //移動到 座標(715,512)
        path4.lineTo(500,60);
        path4.lineTo(720,60);
        path4.lineTo(720,200);
        canvas.drawPath(path4, paint2);

        float[] pts3 = {720,108,450,56};
        canvas.drawLines(pts3, paint2);   //在畫布上畫線 3

        float[] pts4 = {715,230,630,110};
        canvas.drawLines(pts4, paint1);   //在畫布上畫線 4
        float[] pts5 = {660,130,718,272};
        canvas.drawLines(pts5, paint1);   //在畫布上畫線 5
        float[] pts6 = {714,522,720,440};
        canvas.drawLines(pts6, paint1);   //在畫布上畫線 6
    }
}

佈局檔案 activity_camera.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        />

    <Button
        android:id="@+id/button_capture"
        android:text="拍照"
        android:textColor="#6633cc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        />

</LinearLayout>

應用許可權:

    <uses-permission android:name="android.permission.CAMERA"/> >
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

具體的細節就不在說明,可以自己在網上搜一下相關知識,大家使用中有什麼問題可以留言哦,如果能解決儘量幫大家解決。