http://item.congci.com/item/android-camera-houtai-paizhao
有許多人希望在不讓用戶知道的情況下,使用Android后台Service調用攝像頭拍照,網上不少資料,都講到不預覽無法實現拍照,涉及到用戶隱私,屬於非法調用攝像頭...怎么辦!!!
曾經看到一篇博文,里面有一句經典的話:沒有什么是絕對的,沒有什么是繞不過去的。接下來就來分析一下怎么繞過去,實現不預覽拍照。
要求①:不讓用戶看到拍照界面
難點:預覽界面必須在一個Activity上,而彈出了Activity之后,用戶再傻,都知道你在干嘛,怎么辦!!
思路:彈出Activity就彈出吧,咱對Activity做手腳,讓他全透明,再來個全屏,和無標題欄,不就和沒東西彈出來一個效果。
要點②:不預覽
難點:非法調用攝像頭,怎么辦!!報錯 "take picture failed ! !"
思路:你要在Activity上有SurfaceView進行預覽,那就來一個SurfaceView,打不了咱再對SurfaceView做手腳就是 了...設這SurfaceView長和寬都為0.1 你不是要預覽嗎,也有,問題是預覽框這么小,要是你還能看到那就沒辦 法了...
好了,不多說,思路有了就開始工作:
首先,用來拍照的Activity布局:
- <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=".MyCamera" >
- <!-- 預覽框,長寬都為0.1 -->
- <SurfaceView
- android:id="@+id/camera_surfaceview"
- android:layout_width="0.1dp"
- android:layout_height="0.1dp" >
- </SurfaceView>
- </RelativeLayout>
接下來時全透明,在AndroidManifest.xml里,主題設置成全透明,記得添加調用攝像頭權限、自動對焦權限和讀寫SD卡權限:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.chenww.camera.ui"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk
- android:minSdkVersion="10"
- android:targetSdkVersion="16">
- </uses-sdk>
- <!-- 調用相機權限 -->
- <uses-permission android:name="android.permission.CAMERA" />
- <uses-feature android:name="android.hardware.camera" />
- <uses-feature android:name="android.hardware.camera.autofocus" />
- <!-- 讀寫SD卡權限 -->
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <!-- 拍照界面Activity -->
- <activity
- android:name="com.chenww.camera.ui.CameraActivity"
- android:theme="@android:style/Theme.Translucent" >
- <!-- theme設置成全透明 -->
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
然后是CameraActivity.java文件,這里就得在oncreate開頭添加如下代碼設置窗口全屏並且無標題。
- // 無title
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- // 全屏
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
綁定SurfaceView 初始化SurfaceHolder
- //初始化surfaceview
- mySurfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview);
- //初始化surfaceholder
- myHolder = mySurfaceView.getHolder();
- myHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
接下來,初始化Camera對象,並調用該對象的setPreviewDisplay函數設置SurfaceHolder對象(這里為myHolder)
- //這里的myCamera為已經初始化的Camera對象
- myCamera.setPreviewDisplay(myHolder);
接下來就是拍照,不過記得在takepicture之前startPreview
這里提醒一下,能把拍照代碼直接寫在oncreate函數里,那時Activity還未初始化完成,SurfaceView還沒出來,結果就是 "take ticture failed!!",最好在oncreate內新建一個線程執行拍照操作,一般不建議在UI線程內實現耗時操作。
並且攝像頭的開啟需要一定的事件,最好在調用open函數之后讓線程睡個兩秒。
- myCamera.startPreview();
- //自動對焦
- myCamera.autoFocus(myAutoFocus);
- //對焦后拍照
- myCamera.takePicture(null, null, myPicCallback);
上面的myAutoFocus及myPicCallback分別自動對焦回調函數和成功拍照回調函數
myAutoFocus我直接空實現,可以直接new一個接口對象,不過那樣代碼太亂,干脆空實現。
myPicCallback的話,就是實現onPictureTaken函數,在里面對攝像頭拍攝下來的照片字節數據進行處理(存儲)。
額....廢話多了點,上代碼:
myAutoFocus:
- //自動對焦回調函數(空實現)
- private AutoFocusCallback myAutoFocus = new AutoFocusCallback() {
- @Override
- public void onAutoFocus(boolean success, Camera camera) {
- }
- };
myPicCallback:
- //拍照成功回調函數
- private PictureCallback myPicCallback = new PictureCallback() {
- @Override
- public void onPictureTaken(byte[] data, Camera camera) {
- }
- }
騷年,在處理完Camera返回的數據之后,記得關閉Activity並各種釋放資源
- //完成拍照后關閉Activity
- MyCameraActivity.this.finish();
- myCamera.stopPreview();
- myCamera.release();
- myCamera = null;
PS:對照片的處理,我在上一篇博文中有講到,比如android攝像頭獲取的照片都是橫屏的...要讓他直起來怎么搞或者是豎直預覽:點擊打開鏈接
最后,我把我做的一個小小的后台拍照Demo發上來,供大家學習。
打開程序后自動調用前置攝像頭,如果無前置則調用后置攝像頭,並將獲取的照片調整為豎屏。
ps:導入工程后最好右鍵工程 android tools -->fix project properties 另外,我使用的是4.1.2版本編譯,如果需要改,右鍵工程properties-->android選擇其他版本