編輯:關於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版本上的部分,在注釋中做了聲明。
在程序開發中,為了讓程序表現的更快更流暢,我們會使用多線程來提升應用的並發性能。但多線程並發代碼是一個棘手的問題,線程的生命周期處理不好就會造成內存洩漏。 new
針對app線上修復技術,目前有好幾種解決方案,開源界往往一個方案會有好幾種實現。重復的實現會有造輪子之嫌,但分析解決方案在技術上的探索和衍變,這輪子還是值得去推動的關於
何為動態加載、插件化?需求驅動隨著業務發展需要和無線部門的拆分,各業務產品模塊歸屬到各業務BU,原有無線App開發團隊被分為基礎框架、業務A、業務B、業務C等多個開發團隊
1.申請微信APPID要實現分享到微信的功能,首先要到微信開放平台申請一個APPID。但在申請APPID的時候需要填寫一個應用簽名和應用包名。需要注意的是包名