android:largeHeap="true"避免出現OutOfMemoryError
MyImageView Code
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.cyfang.test.MainActivity" > <SurfaceView android:id="@+id/surfaceView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" /> <com.cyfang.test.MyImageView android:id="@+id/myImageView" android:layout_width="320px" android:layout_height="480px" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:text="拍照" /> </RelativeLayout>
Manifes:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cyfang.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="landscape" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Activity:
package com.cyfang.test; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; import java.util.List; import android.util.DisplayMetrics; import android.app.Activity; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Point; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Parameters; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.Size; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements SurfaceHolder.Callback, PictureCallback { /** SurfaceView */ private SurfaceView surfaceView; /** Holder */ private SurfaceHolder holder; /** 相機 */ private Camera camera; /** 自訂ImageView */ private MyImageView imageview; /** 拍照按鈕 */ private Button buttonTake; /** 照片寬度 */ private int picWidth; /** 照片寬度 */ private int picHeight; /** 預覽寬度 */ private int pvWidth; /** 預覽高度 */ private int pvHeight; /** 螢幕寬 / 預覽寬 */ private double screenWithPreviewWidthRate; /** 螢幕高 / 預覽高 */ private double screenWithPreviewHeightRate; /** 預覽寬 / 照片高 */ private double previewWithOutputWidthRate; /** 預覽高 / 照片高 */ private double previewWithOutputHeightRate; /** 螢幕寬 */ private double screenWidth; /** 螢幕高 */ private double screenHeight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); screenWidth = displaymetrics.widthPixels; screenHeight = displaymetrics.heightPixels; imageview = (MyImageView) findViewById(R.id.myImageView); buttonTake = (Button) findViewById(R.id.button1); // 按鈕點擊事件 buttonTake.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { camera.takePicture(null, null, MainActivity.this); } }); surfaceView = (SurfaceView) findViewById(R.id.surfaceView); surfaceView.setZOrderOnTop(false); holder = surfaceView.getHolder(); holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } @Override protected void onStop() { if (camera != null) { camera.stopPreview(); camera.release(); camera = null; } super.onStop(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder holder) { try { if (camera == null) { camera = Camera.open(CameraInfo.CAMERA_FACING_BACK); // 取得相機參數 Parameters parameters = camera.getParameters(); // 關閉閃光燈 parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); // 預覽尺寸清單 List<Size> previewList = parameters.getSupportedPreviewSizes(); // 照片尺寸清單 List<Size> pictureList = parameters.getSupportedPictureSizes(); picWidth = pictureList.get(0).width; picHeight = pictureList.get(0).height; // 設定最佳照片尺寸 parameters.setPictureSize(picWidth, picHeight); pvWidth = previewList.get(0).width; pvHeight = previewList.get(0).height; // 設定最佳預覽尺寸 parameters.setPreviewSize(pvWidth, pvHeight); // 設定相機參數 camera.setParameters(parameters); // 設定顯示的Holder camera.setPreviewDisplay(holder); screenWithPreviewHeightRate = screenHeight >= previewHeight ? screenHeight / previewHeight : previewHeight / screenHeight; screenWithPreviewWidthRate = screenWidth >= previewWidth ? screenWidth / previewWidth : previewWidth / screenWidth; previewWithOutputHeightRate = previewHeight >= picHeight ? previewHeight / picHeight : picHeight / previewHeight; previewWithOutputWidthRate = previewWidth >= picWidth ? previewWidth / picWidth : picWidth / previewWidth; // 開始顯示 camera.startPreview(); } } catch (IOException e) { } catch (RuntimeException e) { } } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub } @Override public void onPictureTaken(byte[] data, Camera camera) { try { System.gc(); // 取得ImageView x,y int[] location = new int[2]; imageViewRect.getLocationOnScreen(location); Log.i("x", location[0] + "," + location[1]); int x = (int) (screenWithPreviewWidthRate * previewWithOutputWidthRate * (double) location[0]); int y = (int) (screenWithPreviewHeightRate * previewWithOutputHeightRate * (double) location[1]); int width = (int) (screenWithPreviewWidthRate * previewWithOutputWidthRate * (double) rectWidth); int height = (int) (screenWithPreviewHeightRate * previewWithOutputHeightRate * (double) rectHeight); Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); // 擷取範圍 Bitmap bitmapRect = Bitmap.createBitmap(bitmap, x, y, width, height); // 釋放bitmap資源 bitmap.recycle(); bitmap = null; FileOutputStream fileOutputStream = new FileOutputStream( new File("/sdcard/" + new Date().getTime() + ".jpg")); bitmapRect.compress(CompressFormat.JPEG, 90, fileOutputStream); bitmapRect.recycle(); bitmapRect = null; // 寫入檔案 fileOutputStream.flush(); fileOutputStream.close(); fileOutputStream = null; // 重啟相機預覽功能 camera.startPreview(); } catch (IOException e) { Log.i("Tack_IOException", e.getMessage()); } } }
擷取前:
擷取後: