Android?拍照功能實(shí)現(xiàn)(手機(jī)關(guān)閉依然拍照)詳解及實(shí)例代碼
Android 拍照功能/手機(jī)關(guān)閉能拍照
效果如下:
其實(shí)拍照與偷錄實(shí)現(xiàn)方式是一樣的,都是使用到的WindowManager來繪制桌面小控件的原理。那我就不多說了…
一、首先我們需要一個(gè)SurfaceView:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/small_window_layout" android:layout_width="1dip" android:layout_height="1dip" > <FrameLayout android:id="@+id/percent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" /> </LinearLayout>
二、然后進(jìn)行的操作就是生產(chǎn)這個(gè)小控件了:
public PhotoWindowSmallView(Context context) { super(context); windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); LayoutInflater.from(context).inflate(R.layout.float_window_small, this); View view = findViewById(R.id.small_window_layout); viewWidth = view.getLayoutParams().width; viewHeight = view.getLayoutParams().height; // SurfaceView percentView = (SurfaceView) findViewById(R.id.percent); // percentView.setText(MyWindowManager.getUsedPercentValue(context)); } /** * 將小懸浮窗的參數(shù)傳入,用于更新小懸浮窗的位置。 * * @param params 小懸浮窗的參數(shù) */ public void setParams(WindowManager.LayoutParams params) { mParams = params; }
三、那桌面控件有了,下面當(dāng)然就是使用WindowManager添加到桌面上了:
/** * 創(chuàng)建一個(gè)小懸浮窗。初始位置為屏幕的右部中間位置。 * * @param context 必須為應(yīng)用程序的Context. */ public void createSmallWindow(Context context) { mContext = context; WindowManager windowManager = getWindowManager(context); int screenWidth = windowManager.getDefaultDisplay().getWidth(); int screenHeight = windowManager.getDefaultDisplay().getHeight(); if (smallWindow == null) { smallWindow = new PhotoWindowSmallView(context); if (smallWindowParams == null) { smallWindowParams = new LayoutParams(); smallWindowParams.type = LayoutParams.TYPE_PHONE; smallWindowParams.format = PixelFormat.RGBA_8888; smallWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; smallWindowParams.gravity = Gravity.LEFT | Gravity.TOP; smallWindowParams.width = PhotoWindowSmallView.viewWidth; smallWindowParams.height = PhotoWindowSmallView.viewHeight; smallWindowParams.x = screenWidth; smallWindowParams.y = screenHeight / 2; } smallWindow.setParams(smallWindowParams); windowManager.addView(smallWindow, smallWindowParams); mSurfaceview = (FrameLayout) smallWindow.findViewById(R.id.percent); } } /** * 將小懸浮窗從屏幕上移除。 * * @param context 必須為應(yīng)用程序的Context. */ public void removeSmallWindow(Context context) { if (smallWindow != null) { WindowManager windowManager = getWindowManager(context); windowManager.removeView(smallWindow); smallWindow = null; } }
四、這個(gè)時(shí)候我們需要的SurfaceView就有了,那么,怎么在后臺(tái)進(jìn)行操作呢?自然而然就想到了Service了
在Service中執(zhí)行桌面控件的操作:
@Override public int onStartCommand(Intent intent, int flags, int startId) { myWindowManager = new MyPhotoWindowManager(); createWindow(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } private void createWindow() { // 當(dāng)前界面是桌面,且沒有懸浮窗顯示,則創(chuàng)建懸浮窗。 myWindowManager.removeSmallWindow(getApplicationContext()); myWindowManager.createSmallWindow(getApplicationContext()); }
五、在activity中對(duì)Service綁定,進(jìn)行拍照的操作
private class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub binder = (PhotoWindowService.myServiceBinder) service; if (isVedio) { binder.startCarema(); } else { binder.stopCarema(); } } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } }
六、在Service中控制myWindowManager中的拍照的開始和結(jié)束
public class myServiceBinder extends Binder { public void startCarema() { myWindowManager.startCarema(); } public void stopCarema() { myWindowManager.stopCarema(); } }
七、在MyPhotoWindowManager開啟或終止拍照操作
public void startCarema() { itt = InitTimetoTakePic.getInstance(mContext); itt.initView(mSurfaceview); itt.start(); } public void stopCarema() { if (itt != null) itt.releaseCarema(); }
八、在InitTimetoTakePic進(jìn)行拍照的相關(guān)處理
package com.ddv.www.candidphotodemo; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PictureCallback; import android.os.Build; import android.os.Handler; import android.os.Message; import android.widget.FrameLayout; import java.io.File; import java.io.FileOutputStream; /** * 設(shè)置定時(shí)拍照功能 * * @author <p> * 創(chuàng)建定時(shí)拍照任務(wù) * cameraType 攝像頭 * resolutionString 分辨率 * tvSaveLocation 保存地址 * etExtension 拓展名 * cameraStart, 開始拍攝時(shí)間 * cameraNumber, 拍攝次數(shù) * cameraStop 拍攝張數(shù) */ public class InitTimetoTakePic { private static InitTimetoTakePic mInstance; private static int cameraType = 1; Context mContext; static FrameLayout mSurfaceViewFrame; private static Camera mCamera; private static CameraPreview mPreview; private static String resolutionString = "1920x1080"; private static String saveLocation = AppUtils.getSDCardPath(); private static String extension = "JPG"; private static String cameraStart = "1"; private static String cameraNumber = "1"; private static String cameraStop = "10"; private static int number = 0; private static boolean clearVoice = false; private Intent intent; private InitTimetoTakePic(Context context) { this.mContext = context; } public synchronized static InitTimetoTakePic getInstance(Context context) { mInstance = null; mInstance = new InitTimetoTakePic(context); return mInstance; } public void initView(FrameLayout surfaceViewFrame) { mSurfaceViewFrame = surfaceViewFrame; } /** * 啟動(dòng)定時(shí)拍照并上傳功能 */ Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: LogUtils.v("開始拍照"); initCarema(); break; case 2: if (mCamera == null) { releaseCarema(); number = 0; mHandler.removeCallbacksAndMessages(null); } else { if (number < Integer.valueOf(cameraStop)) { mCamera.autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // 從Camera捕獲圖片 LogUtils.v("自動(dòng)聚焦111" + success); try { mCamera.takePicture(null, null, mPicture); mHandler.sendEmptyMessageDelayed(1, Integer.valueOf(cameraNumber) * 1000); } catch (Exception e) { releaseCarema(); mHandler.removeCallbacksAndMessages(null); } } }); } else { releaseCarema(); number = 0; mHandler.removeCallbacksAndMessages(null); } } break; } } }; public void start() { mHandler.sendEmptyMessageDelayed(1, 1 * 1000); //7s 后開始啟動(dòng)相機(jī) } private void initCarema() { LogUtils.v("initCarema"); if (mCamera == null) { LogUtils.v("camera=null"); mCamera = getCameraInstance(); mPreview = new CameraPreview(mContext, mCamera); mSurfaceViewFrame.removeAllViews(); mSurfaceViewFrame.addView(mPreview); } LogUtils.v(mCamera == null ? "mCamera is null" : "mCamera is not null"); mCamera.startPreview(); mHandler.sendEmptyMessageDelayed(2, Integer.valueOf(cameraStart) * 1000); //3s后拍照 } /** * 檢測(cè)設(shè)備是否存在Camera硬件 */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_CAMERA)) { // 存在 return true; } else { // 不存在 return false; } } /** * 打開一個(gè)Camera */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static Camera getCameraInstance() { Camera c = null; try { c = Camera.open(cameraType); c.setDisplayOrientation(90); Camera.Parameters mParameters = c.getParameters(); //快門聲音 c.enableShutterSound(clearVoice); //可以用得到當(dāng)前所支持的照片大小,然后 //List<Size> ms = mParameters.getSupportedPictureSizes(); //mParameters.setPictureSize(ms.get(0).width, ms.get(0).height); //默認(rèn)最大拍照取最大清晰度的照片 String[] xes = resolutionString.split("x"); // LogUtils.i("ms.get(0).width==>"+ms.get(0).width); // LogUtils.i("ms.get(0).height==>"+ms.get(0).height); // LogUtils.i("Integer.valueOf(xes[0])==>"+Integer.valueOf(xes[0])); // LogUtils.i("Integer.valueOf(xes[1])==>"+Integer.valueOf(xes[1])); mParameters.setPictureSize(Integer.valueOf(xes[0]), Integer.valueOf(xes[1])); //默認(rèn)最大拍照取最大清晰度的照片 c.setParameters(mParameters); } catch (Exception e) { LogUtils.v("打開Camera失敗失敗"); } return c; } private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 獲取Jpeg圖片,并保存在sd卡上 String path = saveLocation; File dirF = new File(path); if (!dirF.exists()) { dirF.mkdirs(); } File pictureFile = new File(path + "/" + System.currentTimeMillis() + "." + extension);//擴(kuò)展名 try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); LogUtils.v("保存圖成功"); number++; intent = new Intent(); intent.setAction("CameraFragment.start"); intent.putExtra("number", number); mContext.sendBroadcast(intent); } catch (Exception e) { LogUtils.v("保存圖片失敗"); e.printStackTrace(); } releaseCarema(); } }; public void releaseCarema() { if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } } }
demo下載地址://www.dbjr.com.cn/softs/519032.html
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Android自定義滑動(dòng)刪除效果的實(shí)現(xiàn)代碼
這篇文章將從現(xiàn)有 Android 滑動(dòng)刪除的痛點(diǎn),到搭建好一個(gè)基本的框架,到最終提供一份完整的 Demo為止,爭(zhēng)取為讀者提供最大的可定制化,需要的朋友可以參考下2018-03-03Android使用內(nèi)置WebView打開TextView超鏈接的實(shí)現(xiàn)方法
這篇文章主要介紹了Android使用內(nèi)置WebView打開TextView超鏈接的實(shí)現(xiàn)方法,文中給出了詳細(xì)的示例代碼,對(duì)各位Android開發(fā)者們具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。2017-03-03Android開發(fā)優(yōu)化之Apk瘦身優(yōu)化指南
隨著業(yè)務(wù)快速發(fā)展,各種業(yè)務(wù)功能上線,版本不斷迭代,apk體積也越來越大,下面這篇文章主要給大家介紹了關(guān)于Android開發(fā)優(yōu)化之Apk瘦身優(yōu)化的相關(guān)資料,需要的朋友可以參考下2022-05-05Android開發(fā)之ProgressDialog進(jìn)度對(duì)話框用法示例
這篇文章主要介紹了Android開發(fā)之ProgressDialog進(jìn)度對(duì)話框用法,簡(jiǎn)單介紹了ProgressDialog進(jìn)度對(duì)話框常見函數(shù)功能,并結(jié)合實(shí)例形式分析了ProgressDialog組件創(chuàng)建及使用進(jìn)度對(duì)話框相關(guān)操作技巧,需要的朋友可以參考下2019-03-03Android Socket通信的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Android Socket通信的簡(jiǎn)單實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09Kotlin自定義View系列教程之標(biāo)尺控件(選擇身高、體重等)的實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于Kotlin自定義View系列教程之標(biāo)尺控件(選擇身高、體重等)實(shí)現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07Android?Flutter實(shí)現(xiàn)創(chuàng)意時(shí)鐘的示例代碼
時(shí)鐘這個(gè)東西很奇妙,總能當(dāng)做創(chuàng)意實(shí)現(xiàn)的入口。這篇文章主要介紹了如何通過Android?Flutter實(shí)現(xiàn)一個(gè)創(chuàng)意時(shí)鐘,感興趣的小伙伴可以了解一下2023-03-03Android中Handler與Message的簡(jiǎn)單實(shí)例
這篇文章主要介紹了Android中Handler與Message的簡(jiǎn)單實(shí)例的相關(guān)資料,這里提供實(shí)例來說明線程Handler與message 的結(jié)合使用,需要的朋友可以參考下2017-08-08