Android自定義照相機(jī)實(shí)現(xiàn)
創(chuàng)新互聯(lián)客戶idc服務(wù)中心,提供資陽(yáng)移動(dòng)機(jī)房、成都服務(wù)器、成都主機(jī)托管、成都雙線服務(wù)器等業(yè)務(wù)的一站式服務(wù)。通過各地的服務(wù)中心,我們向成都用戶提供優(yōu)質(zhì)廉價(jià)的產(chǎn)品以及開放、透明、穩(wěn)定、高性價(jià)比的服務(wù),資深網(wǎng)絡(luò)工程師在機(jī)房提供7*24小時(shí)標(biāo)準(zhǔn)級(jí)技術(shù)保障。
近期小巫在學(xué)校有一個(gè)創(chuàng)新項(xiàng)目,也不是最近,是一個(gè)拖了很久的項(xiàng)目,之前一直沒有去搞,最近因?yàn)橐衅跈z查,搞得我跟小組成員一陣忙活,其實(shí)開發(fā)一款照相機(jī)軟件并不太難,下面就是通過自定義的方式來(lái)實(shí)現(xiàn)手機(jī)照相的功能。
創(chuàng)建一個(gè)項(xiàng)目:FingerTakePicture
首先來(lái)搞一下界面:
界面效果(無(wú)法把預(yù)覽給截屏下來(lái)滴):
權(quán)限設(shè)置少不了:
主Activity:
package com.wwj.finger; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import android.app.Activity; import android.content.Intent; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.os.Environment; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; /** * Android手指拍照 * * @author wwj * @date 2013/4/29 */ public class MainActivity extends Activity { private View layout; private Camera camera; private Camera.Parameters parameters = null; Bundle bundle = null; // 聲明一個(gè)Bundle對(duì)象,用來(lái)存儲(chǔ)數(shù)據(jù) @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 顯示界面 setContentView(R.layout.activity_main); layout = this.findViewById(R.id.buttonLayout); SurfaceView surfaceView = (SurfaceView) this .findViewById(R.id.surfaceView); surfaceView.getHolder() .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.getHolder().setFixedSize(176, 144); //設(shè)置Surface分辨率 surfaceView.getHolder().setKeepScreenOn(true);// 屏幕常亮 surfaceView.getHolder().addCallback(new SurfaceCallback());//為SurfaceView的句柄添加一個(gè)回調(diào)函數(shù) } /** * 按鈕被點(diǎn)擊觸發(fā)的事件 * * @param v */ public void btnOnclick(View v) { if (camera != null) { switch (v.getId()) { case R.id.takepicture: // 拍照 camera.takePicture(null, null, new MyPictureCallback()); break; } } } /** * 圖片被點(diǎn)擊觸發(fā)的時(shí)間 * * @param v */ public void imageClick(View v) { if (v.getId() == R.id.scalePic) { if (bundle == null) { Toast.makeText(getApplicationContext(), R.string.takephoto, Toast.LENGTH_SHORT).show(); } else { Intent intent = new Intent(this, ShowPicActivity.class); intent.putExtras(bundle); startActivity(intent); } } } private final class MyPictureCallback implements PictureCallback { @Override public void onPictureTaken(byte[] data, Camera camera) { try { bundle = new Bundle(); bundle.putByteArray("bytes", data); //將圖片字節(jié)數(shù)據(jù)保存在bundle當(dāng)中,實(shí)現(xiàn)數(shù)據(jù)交換 saveToSDCard(data); // 保存圖片到sd卡中 Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_SHORT).show(); camera.startPreview(); // 拍完照后,重新開始預(yù)覽 } catch (Exception e) { e.printStackTrace(); } } } /** * 將拍下來(lái)的照片存放在SD卡中 * @param data * @throws IOException */ public static void saveToSDCard(byte[] data) throws IOException { Date date = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化時(shí)間 String filename = format.format(date) + ".jpg"; File fileFolder = new File(Environment.getExternalStorageDirectory() + "/finger/"); if (!fileFolder.exists()) { // 如果目錄不存在,則創(chuàng)建一個(gè)名為"finger"的目錄 fileFolder.mkdir(); } File jpgFile = new File(fileFolder, filename); FileOutputStream outputStream = new FileOutputStream(jpgFile); // 文件輸出流 outputStream.write(data); // 寫入sd卡中 outputStream.close(); // 關(guān)閉輸出流 } private final class SurfaceCallback implements Callback { // 拍照狀態(tài)變化時(shí)調(diào)用該方法 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { parameters = camera.getParameters(); // 獲取各項(xiàng)參數(shù) parameters.setPictureFormat(PixelFormat.JPEG); // 設(shè)置圖片格式 parameters.setPreviewSize(width, height); // 設(shè)置預(yù)覽大小 parameters.setPreviewFrameRate(5); //設(shè)置每秒顯示4幀 parameters.setPictureSize(width, height); // 設(shè)置保存的圖片尺寸 parameters.setJpegQuality(80); // 設(shè)置照片質(zhì)量 } // 開始拍照時(shí)調(diào)用該方法 @Override public void surfaceCreated(SurfaceHolder holder) { try { camera = Camera.open(); // 打開攝像頭 camera.setPreviewDisplay(holder); // 設(shè)置用于顯示拍照影像的SurfaceHolder對(duì)象 camera.setDisplayOrientation(getPreviewDegree(MainActivity.this)); camera.startPreview(); // 開始預(yù)覽 } catch (Exception e) { e.printStackTrace(); } } // 停止拍照時(shí)調(diào)用該方法 @Override public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { camera.release(); // 釋放照相機(jī) camera = null; } } } /** * 點(diǎn)擊手機(jī)屏幕是,顯示兩個(gè)按鈕 */ @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: layout.setVisibility(ViewGroup.VISIBLE); // 設(shè)置視圖可見 break; } return true; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_CAMERA: // 按下拍照按鈕 if (camera != null && event.getRepeatCount() == 0) { // 拍照 //注:調(diào)用takePicture()方法進(jìn)行拍照是傳入了一個(gè)PictureCallback對(duì)象——當(dāng)程序獲取了拍照所得的圖片數(shù)據(jù)之后 //,PictureCallback對(duì)象將會(huì)被回調(diào),該對(duì)象可以負(fù)責(zé)對(duì)相片進(jìn)行保存或傳入網(wǎng)絡(luò) camera.takePicture(null, null, new MyPictureCallback()); } } return super.onKeyDown(keyCode, event); } // 提供一個(gè)靜態(tài)方法,用于根據(jù)手機(jī)方向獲得相機(jī)預(yù)覽畫面旋轉(zhuǎn)的角度 public static int getPreviewDegree(Activity activity) { // 獲得手機(jī)的方向 int rotation = activity.getWindowManager().getDefaultDisplay() .getRotation(); int degree = 0; // 根據(jù)手機(jī)的方向計(jì)算相機(jī)預(yù)覽畫面應(yīng)該選擇的角度 switch (rotation) { case Surface.ROTATION_0: degree = 90; break; case Surface.ROTATION_90: degree = 0; break; case Surface.ROTATION_180: degree = 270; break; case Surface.ROTATION_270: degree = 180; break; } return degree; } }
用來(lái)顯示圖片的Activity:
package com.wwj.finger; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.os.Bundle; import android.widget.ImageView; public class ShowPicActivity extends Activity { private ImageView ivPic = null; // 顯示圖片控件 /** * Activity在創(chuàng)建的時(shí)候回調(diào)的函數(shù) 主要用來(lái)初始化一些變量 */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.showpic); ivPic = (ImageView) findViewById(R.id.ivPic); setImageBitmap(getImageFormBundle()); } /** * 將MainActivity傳過來(lái)的圖片顯示在界面當(dāng)中 * * @param bytes */ public void setImageBitmap(byte[] bytes) { Bitmap cameraBitmap = byte2Bitmap(); // 根據(jù)拍攝的方向旋轉(zhuǎn)圖像(縱向拍攝時(shí)要需要將圖像選擇90度) Matrix matrix = new Matrix(); matrix.setRotate(MainActivity.getPreviewDegree(this)); cameraBitmap = Bitmap .createBitmap(cameraBitmap, 0, 0, cameraBitmap.getWidth(), cameraBitmap.getHeight(), matrix, true); ivPic.setImageBitmap(cameraBitmap); } /** * 從Bundle對(duì)象中獲取數(shù)據(jù) * * @return */ public byte[] getImageFormBundle() { Intent intent = getIntent(); Bundle data = intent.getExtras(); byte[] bytes = data.getByteArray("bytes"); return bytes; } /** * 將字節(jié)數(shù)組的圖形數(shù)據(jù)轉(zhuǎn)換為Bitmap * * @return */ private Bitmap byte2Bitmap() { byte[] data = getImageFormBundle(); // 將byte數(shù)組轉(zhuǎn)換成Bitmap對(duì)象 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); return bitmap; } }
這是小巫那個(gè)創(chuàng)新項(xiàng)目的一小部分,已經(jīng)完美實(shí)現(xiàn)簡(jiǎn)單的照相機(jī)功能了,保存圖片不會(huì)像有些網(wǎng)友提供的代碼給定一個(gè)特定的文件名,不能保存多張圖片,還特定把一些方法封裝了一下,有需要的朋友好好看看吧。