摘要:Android - 內部相機實作
沒做過Camera 還真不知道內建Camera還真的沒這麼好做。
遇到第一個問題就是方向的問題,手機相機預設是橫式,若要用直式相機拍,則要對Camera做90度的轉向
遇到第二個問題就是方向轉完,若要儲存還要再處理方向
第三個,就是拍照後,要再重新startPreview
第四個,就是為了在Gallery看到該相片,所以又做了一個傳送到Gallery的動作
除了從書中範例實作出來,為了要做成自己的樣子,還要參考網路兩、三個問題處理的文章才能達到我要的內建相機的方式
package com.tomlai.app;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.tomlai.demo.app.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
public class CameraActivity extends Activity implements SurfaceHolder.Callback,
Camera.AutoFocusCallback {
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Button mTaskPicture;
private Camera camera;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 全螢幕
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 無標題
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 直式
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_camera);
initViews();
}
private void initViews() {
mSurfaceView = (SurfaceView) this.findViewById(R.id.svPreview);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mTaskPicture = (Button) this.findViewById(R.id.taskPicture);
mTaskPicture.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
camera.autoFocus(CameraActivity.this);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
camera.takePicture(null, null, jpeg);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
if (Build.VERSION.SDK_INT >= 8)
camera.setDisplayOrientation(90);
try {
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
camera.release();
camera = null;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// 取得相機參數
Camera.Parameters parameters = camera.getParameters();
// 取得照片尺寸
List supportedPictureSizes = parameters.getSupportedPictureSizes();
int sptw = supportedPictureSizes.get(supportedPictureSizes.size() - 1).width;
int spth = supportedPictureSizes.get(supportedPictureSizes.size() - 1).height;
// 取得預覽尺寸
List supportedPreviewSizes = parameters.getSupportedPreviewSizes();
int prvw = supportedPreviewSizes.get(0).width;
int prvh = supportedPreviewSizes.get(0).height;
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.setPreviewSize(640, 480);
camera.setParameters(parameters);
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
public void saveBitmap(Bitmap bitmap) {
FileOutputStream fOut;
try {
File dir = new File("/sdcard/demo/");
if (!dir.exists()) {
dir.mkdir();
}
String tmp = "/sdcard/demo/takepicture.jpg";
fOut = new FileOutputStream(tmp);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
try {
fOut.flush();
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
sendToGallery(this, tmp);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Camera.PictureCallback jpeg = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imgData, Camera camera) {
if (imgData != null) {
Bitmap picture = BitmapFactory.decodeByteArray(imgData, 0, imgData.length);
picture = rotationBitmap(picture);
saveBitmap(picture);
}
camera.startPreview();
}
};
public Bitmap rotationBitmap(Bitmap picture) {
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(picture,picture.getWidth(),picture.getHeight(),true);
Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);
return rotatedBitmap;
}
public void sendToGallery(Context ctx, String path) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(new File(path));
intent.setData(contentUri);
ctx.sendBroadcast(intent);
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal|center_vertical" >
<SurfaceView android:id="@+id/svPreview"
android:visibility="visible"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button android:id="@+id/taskPicture"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="拍照"
android:drawableLeft="@drawable/camera0"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
只要特別的就是,對camera轉向
if (Build.VERSION.SDK_INT >= 8)
camera.setDisplayOrientation(90);
及拍完照,要儲存前還要再轉向
public Bitmap rotationBitmap(Bitmap picture) {
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(picture,picture.getWidth(),picture.getHeight(),true);
Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);
return rotatedBitmap;
}
將照片資訊傳到gallery
public void sendToGallery(Context ctx, String path) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(new File(path));
intent.setData(contentUri);
ctx.sendBroadcast(intent);
}
第一次學內建Camera拍照的功能。
主要重點元件就會是
SurfaceView
SurfaceHolder
Camera
及他們的Callback
SurfaceHolder.Callback,
Camera.AutoFocusCallback
方法重點在
camera.autoFocus(CameraActivity.this);
camera.takePicture(null, null, jpeg);
camera.startPreview();