並加入自動對焦與列出照片並可刪除該照片檔案
1.AndroidManifest.xml加入權限
2.建立java檔與layout檔
TakeAPhotoActivity.java 拍照
package tw.android; import android.app.Activity; import android.content.Intent; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; public class TakeAPhotoActivity extends Activity { private static final String TAG = "TakeAPhotoActivity"; private SurfaceView sv; // private ImageView iv; private Button takePhotoBtn, hidePhotoBtn, autoFocus,picList; // 相機 callback private CameraCallback cc; // 快門 callback private ShCallback sc; // 處理 raw data callback private RawCallback rc; // 處理 jpg callback private JpgCallback jc; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.take_a_photo_activity); this.sv = (SurfaceView) this.findViewById(R.id.sv); this.takePhotoBtn = (Button) this.findViewById(R.id.takePhotoBtn); this.hidePhotoBtn = (Button) this.findViewById(R.id.hidePhotoBtn); this.autoFocus = (Button) this.findViewById(R.id.autoFocus); this.picList= (Button) this.findViewById(R.id.picList); this.cc = new CameraCallback(); this.sc = new ShCallback(); this.rc = new RawCallback(); this.jc = new JpgCallback(this); Log.d(TAG, "設定預覽視窗..."); SurfaceHolder sh = this.sv.getHolder(); sh.addCallback(this.cc); sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); Log.d(TAG, "設定拍照頁面..."); this.hidePhotoBtn.setVisibility(View.GONE); // 按鈕外按自動對焦 autoFocus.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { cc.getCarema().autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { } }); } }); //前往照片列表 picList.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { goToPicList(); } }); } public void takePhoto(View v) { Log.d(TAG, "拍照..."); // 需要三個 callback:快門、處理 raw data、處理 jpg // 拍照時自動對焦 this.cc.getCarema().autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (success) { camera.takePicture(sc, rc, jc); } } }); } public void hidePhoto(View v) { Log.d(TAG, "設定拍照頁面..."); this.takePhotoBtn.setVisibility(View.VISIBLE);// 顯示拍照按鈕 this.hidePhotoBtn.setVisibility(View.GONE); // 隱藏重拍按鈕 Log.d(TAG, "回到拍照功能,需重新啟動預覽..."); this.cc.getCarema().startPreview(); } public void showPhoto(String picPath) { Log.d(TAG, "取得照片路徑:" + picPath); Log.d(TAG, "設定照片頁面..."); this.takePhotoBtn.setVisibility(View.GONE); this.hidePhotoBtn.setVisibility(View.VISIBLE); } //前往照片列表 public void goToPicList(){ Intent intent=new Intent(this,PhotoList.class); startActivity(intent); } }CameraCallback.java
package tw.android; import java.io.IOException; import android.hardware.Camera; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; public class CameraCallback implements Callback { private static final String TAG = "CameraCallback"; private Camera carema; public Camera getCarema() { return this.carema; } public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG, "啟動相機..."); this.carema = Camera.open(); try { Log.d(TAG, "設定預覽視窗"); this.carema.setPreviewDisplay(holder); } catch (IOException e) { Log.e(TAG, e.getMessage(), e); } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(TAG, "開始預覽..."); this.carema.setDisplayOrientation(90); //相機旋轉90度 this.carema.startPreview(); } public void surfaceDestroyed(SurfaceHolder holder) { Log.d(TAG, "停止預覽..."); this.carema.stopPreview(); Log.d(TAG, "釋放相機資源..."); this.carema.release(); this.carema = null; } }JpgCallback.java
package tw.android; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.os.Environment; import android.util.Log; public class JpgCallback implements PictureCallback { private static final String TAG = "JpgCallback"; private String picPath; private TakeAPhotoActivity act; int number; public JpgCallback(TakeAPhotoActivity act) { super(); this.act = act; } @Override public void onPictureTaken(byte[] data, Camera camera) { Log.d(TAG, "處理 JPG 資料,輸出 jpg 檔..."); /*-- 2015-09-11 相機旋轉90度後,照片需要跟著旋轉90度 --*/ Bitmap srcBmp, dstBmp; srcBmp= BitmapFactory.decodeByteArray(data, 0, data.length); Matrix matrix=new Matrix(); matrix.reset(); matrix.postRotate(90f); dstBmp= Bitmap.createBitmap(srcBmp, 0, 0, srcBmp.getWidth(), srcBmp.getHeight(), matrix, true); /*-- 2015-09-11 --*/ FileOutputStream os = null; try { File pic = this.createPicFile(); os = new FileOutputStream(pic); dstBmp.compress(Bitmap.CompressFormat.JPEG, 100, os); //2015-09-11 Bitmap 轉回 byte[] os.write(data); } catch (IOException e) { Log.e(TAG, e.getMessage(), e); } finally { if (os != null) { try { os.close(); } catch (IOException e) { } } } Log.d(TAG, "輸出 JPG 完成"); // 顯示照片 this.act.showPhoto(this.picPath); } @SuppressLint("DefaultLocale") private File createPicFile() { File sdDir = Environment.getExternalStorageDirectory(); Log.d(TAG, "sdDir" + sdDir); File picDir = new File(sdDir, "takePic"); //建立放置照片資料夾 if (!picDir.exists()) { picDir.mkdir(); } long ctm =System.currentTimeMillis(); //照片名 /* SharedPreferences */ try { SharedPreferences preferencesGet = this.act .getSharedPreferences("takePic", android.content.Context.MODE_PRIVATE); number=preferencesGet.getInt("number", 0); //照片數量 } catch (Exception e) { } SharedPreferences preferencesSave = this.act .getSharedPreferences("takePic", android.content.Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferencesSave.edit(); Log.d(TAG,number+""); number++; //照片數量+1 editor.putInt("number", number); editor.putLong(Integer.toString(number), ctm); //儲存照片名 editor.commit(); String fileName = String.format("%d.jpg", ctm); File pic = new File(picDir, fileName); this.picPath = pic.getAbsolutePath(); Log.d(TAG, "照片路徑:" + this.picPath); return pic; } }RawCallback.java
package tw.android; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.util.Log; public class RawCallback implements PictureCallback { private static final String TAG = "RawCallback"; @Override public void onPictureTaken(byte[] data, Camera camera) { Log.d(TAG, "處理 Raw data..."); } }ShCallback.java
package tw.android; import android.hardware.Camera.ShutterCallback; import android.util.Log; public class ShCallback implements ShutterCallback { private static final String TAG = "ShCallback"; @Override public void onShutter() { Log.d(TAG, "啟動快門..."); } }PhotoList.java 列出照片
package tw.android; import java.io.File; import android.app.Activity; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TableRow.LayoutParams; public class PhotoList extends Activity { private Button[] detelPic; private String[] dataName; private int number; private int id; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.photo_list); setTable(); } // 排版 public void setTable() { try { SharedPreferences preferencesGet = getApplicationContext() .getSharedPreferences("takePic", android.content.Context.MODE_PRIVATE); number=preferencesGet.getInt("number", 0);//取出照片數量 dataName = new String[number]; Log.i("number", number+""); for(int i = 0; i < number; i++){ dataName[i]=String.valueOf(preferencesGet.getLong(Integer.toString(i+1), 0)); //放入照片名稱 Log.i("dataName[i]", dataName[i]+""); } } catch (Exception e) { } TableLayout t1 = (TableLayout) findViewById(R.id.tableSet); t1.removeAllViews(); TableRow.LayoutParams tP = new TableRow.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f); tP.setMargins(0, 0, 0, 20); detelPic = new Button[number]; for (int i = 0; i < number; i++) { // 列 TableRow row = new TableRow(this); ImageView iv = new ImageView(this); String picPath = "/storage/emulated/0/takePic/" + dataName[i] + ".jpg"; Uri uri = Uri.fromFile(new File(picPath)); iv.setLayoutParams(tP); iv.setImageURI(uri); row.addView(iv, 0); // 刪除button detelPic[i] = new Button(this); detelPic[i].setText("刪除"); detelPic[i].setId(i); detelPic[i].setOnClickListener(dp); // 動作 row.addView(detelPic[i], 1); t1.addView(row); } } private OnClickListener dp = new OnClickListener() { public void onClick(View v) { id = v.getId(); // 刪除照片 File file = new File("/storage/emulated/0/takePic/" + dataName[id] + ".jpg"); file.delete(); setTable();//重整 } }; }take_a_photo_activity.xml //拍照layout
photo_list.xml //照相列表 layout
檔案下載:
https://github.com/terryyamg/AndroidCamera
參考來源:
1.http://cw1057.blogspot.tw/2011/12/android-camera_09.html
2.http://stackoverflow.com/questions/8058122/where-to-put-autofocus-in-the-class-android-camera
3.http://stackoverflow.com/questions/5486529/delete-file-from-internal-storage
4.http://stackoverflow.com/questions/10660598/android-camera-preview-orientation-in-portrait-mode
(2015-09-11 update)
5. http://rincliu.com/blog/2013/11/18/camera/
6.http://bingtian.iteye.com/blog/642128