編輯:關於Android編程
Camera.Parameters中另一個特別有用設置是設置預覽大小。正如使用其他設置,我們首先要查詢的參數對象,取得其支持列表。取得預覽尺寸列表之後,我們遍歷它,以確保在設置之前,我們想要設置的大小是相機支持的。
在本示例中,我們不設定精確的預定尺寸,而選擇一個設備支持,最接近且不大於預定值的尺寸。圖 2-4 顯示了此示例的輸出。
... public static final int LARGEST_WIDTH = 200; public static final int LARGEST_HEIGHT= 200; ...
public void surfaceCreated(SurfaceHolder holder)
{
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);
Camera.Parameters parameters = camera.getParameters(); int bestWidth = 0;
int bestHeight = 0; ListpreviewSizes = parameters.getSupportedPreviewSizes(); if (previewSizes.size() > 1) { Iterator cei = previewSizes.iterator(); while (cei.hasNext()) { Camera.Size aSize = cei.next();
Log.v("SNAPSHOT","Checking " + aSize.width + " x " + aSize.height);
if (aSize.width > bestWidth && aSize.width <= LARGEST_WIDTH
&& aSize.height > bestHeight && aSize.height <= LARGEST_HEIGHT)
{
// 到目前為止它是最大的而且沒有超過屏幕尺寸
bestWidth = aSize.width;
bestHeight = aSize.height;
}
}此外,我們還要告訴我們的相機預覽 SurfaceView 對象 cameraView,以此大小顯示預覽。如果SurfaceView 不改變大小,相機的預覽圖像將被扭曲或以極低的質量顯示。
if (bestHeight != 0 && bestWidth != 0)
{
Log.v("SNAPSHOT", "Using " + bestWidth + " x " + bestHeight);
parameters.setPreviewSize(bestWidth, bestHeight);
cameraView.setLayoutParams(new LinearLayout.LayoutParams( bestWidth,bestHeight));
}
}
camera.setParameters(parameters); }
catch (IOException exception)
{
camera.release();
}
}
圖2-4. 相機以小尺寸預覽
使用Camera類捕獲圖像,我們得調用takePicture方法。此方法接收三個或四個參數,都為回調函數。使用takePicture方法的最簡單形式是所有參數都設為 null。但是在拍攝了圖像之後,沒法得到圖像的引用。至少要實現其中的一個回調函數。最安全的是 Camera.PictureCallback.onPictureTaken。當圖像采集壓縮就緒後,它一定會被調用。為此,我們讓我們的activity實現Camera.PictureCallback接口,添加onPictureTaken方法。
public class SnapShot extends Activity implements SurfaceHolder.Callback,
Camera.PictureCallback {
public void onPictureTaken(byte[] data, Camera camera) { } 因為給我們的是實際的 JPEG 數據,我們要保存它,只需要將它寫到磁盤的某個地方就行了。我們已經知道,利用 MediaStore 指定它的位置和元數據是個好主意。
當onPictureTaken方法被調用時,我們需要調用Camera對象的startPreview。因為當takePicture方法被調用時,預覽就自動暫停了。回調函數告訴我們,現在可以重新啟動預覽了。
public void onPictureTaken(byte[] data, Camera camera)
{
Uri imageFileUri = getContentResolver().
insert(Media.EXTERNAL_CONTENT_URI, new ContentValues()); try {
OutputStream imageFileOS = getContentResolver().openOutputStream(imageFileUri);
imageFileOS.write(data);
imageFileOS.flush();
imageFileOS.close(); }
catch (FileNotFoundException e)
{ }
catch (IOException e)
{ }
camera.startPreview();
}ContentValues contentValues = new ContentValues(3); contentValues.put(Media.DISPLAY_NAME, "This is a test title"); contentValues.put(Media.DESCRIPTION, "This is a test description"); getContentResolver().update(imageFileUri,contentValues,null,null);
我們讓我們的activity實現 OnClickListener 並設置surfaceView 的 onClickListener 為activity。然後,通過setClickable(true),我們讓SurfaceView成為可點擊的。此外,我們需要使 SurfaceView 可獲得焦點。SurfaceView 在默認情況下是不能獲得焦點的,所以我們必須通過 setFocusable(true) 顯式設置。此外,當我們在"觸摸模式"時,焦點一般是禁用的,因此我們必須通過顯性調用 setFocusInTouchMode(true)
使能焦點。
public class SnapShot extends Activity implements OnClickListener,
SurfaceHolder.Callback, Camera.PictureCallback
{
...
public void onCreate(Bundle savedInstanceState)
{
...
cameraView.setFocusable(true);
cameraView.setFocusableInTouchMode(true);
cameraView.setClickable(true);
cameraView.setOnClickListener(this);
}
public void onClick(View v)
{
camera.takePicture(null, null, null, this);
}除了Camera.PictureCallback,還有其他一些回調方法也值得提出來。
Camera.PreviewCallback: 定義了方法onPreviewFrame(byte[] data, Camera camera),當預覽幀就緒時被調用。函數傳入一字節數組,包含圖像當前的像素值。Camera有三種使用此回調的方法。
setPreviewCallback(Camera.PreviewCallback): 使用此方法注冊Camera.PreviewCallback,可以確保每當一個新的預覽幀就緒調用onPreviewFrame,並顯示在屏幕上 。傳遞給 onPreviewFrame 的數據字節數組,最可能是YUV格式。不幸的是,直到Android 2.2,才配備了 YUV 格式解碼器 (YuvImage) ;在以前版本中,解碼必須手工完成。
setOneShotPreviewCallback(Camera.PreviewCallback): 使用此方法注冊 Camera.PreviewCallback,當下一個預覽圖像就緒時,會調用onPreviewFrame一次。同樣, 傳遞給onPreviewFrame的預覽圖像數據最可能是YUV格式。可以通過定義在 ImageFormat 中的常量與 Camera.getParameters().getPreviewFormat() 返回值進行比較得出。
setPreviewCallbackWithBuffer(Camera.PreviewCallback): 在 Android 2.2 中引入,這種方法跟正常的setPreviewCallback 工作方式相同,但需要我們指定一個字節數組,作為預覽圖像數據緩沖區。這樣做是為了在處理預覽圖像時,我們能更好的管理內存。
Camera.AutoFocusCallback: 定義了方法onAutoFocus,自動對焦行為完成時被調用。調用Camera對象的autoFocus方法,以這個回調接口的實例作為參數,可能會觸發自動對焦。
Camera.ErrorCallback: 定義了方法onError,Camera發生錯誤時被調用。有兩個常量可以與傳入的錯誤代碼進行比較CAMERA_ERROR_UNKNOWN和MERA_ERROR_SERVER_DIED.
Camera.OnZoomChangeListener: 定義了方法onZoomChange方法,當正在進行或完成"平滑縮放" (緩慢放大或縮小)時被調用。在 Android 2.2(API 級別 8)中介紹了這個類及其方法。
Camera.ShutterCallback: 定義 onShutter 方法,在拍攝圖像時被調用。
讓我們完成整個示例。下面的代碼要運行在Android 2.2 及以上版本,但做細小修改,它可以在 1.6 及更高版本上運行。需要運行在1.6版本上的部分,在注釋中做了聲明。
Android多線程性能優化(一)
在程序開發中,為了讓程序表現的更快更流暢,我們會使用多線程來提升應用的並發性能。但多線程並發代碼是一個棘手的問題,線程的生命周期處理不好就會造成內存洩漏。 new
Android線上bug熱修復分析
針對app線上修復技術,目前有好幾種解決方案,開源界往往一個方案會有好幾種實現。重復的實現會有造輪子之嫌,但分析解決方案在技術上的探索和衍變,這輪子還是值得去推動的關於
android--動態加載、插件化
何為動態加載、插件化?需求驅動隨著業務發展需要和無線部門的拆分,各業務產品模塊歸屬到各業務BU,原有無線App開發團隊被分為基礎框架、業務A、業務B、業務C等多個開發團隊
Android實現分享微信好友及出現閃退的解決辦法
1.申請微信APPID要實現分享到微信的功能,首先要到微信開放平台申請一個APPID。但在申請APPID的時候需要填寫一個應用簽名和應用包名。需要注意的是包名