Android * 功能实现(手机关闭依然拍照)详解及实例代码

作者:晓果博客 时间:2023-01-08 00:23:19 

 Android * 功能/手机关闭能拍照

效果如下:

Android  * 功能实现(手机关闭依然拍照)详解及实例代码

其实 * 与偷录实现方式是一样的,都是使用到的WindowManager来绘制桌面小控件的原理。那我就不多说了…

一、首先我们需要一个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>

二、然后进行的操作就是生产这个小控件了:


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));
 }

/**
  * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。
  *
  * @param params 小悬浮窗的参数
  */
 public void setParams(WindowManager.LayoutParams params) {
   mParams = params;
 }

三、那桌面控件有了,下面当然就是使用WindowManager添加到桌面上了:


/**
    * 创建一个小悬浮窗。初始位置为屏幕的右部中间位置。
    *
    * @param context 必须为应用程序的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 必须为应用程序的Context.
    */
   public void removeSmallWindow(Context context) {
     if (smallWindow != null) {
       WindowManager windowManager = getWindowManager(context);
       windowManager.removeView(smallWindow);
       smallWindow = null;
     }
   }

四、这个时候我们需要的SurfaceView就有了,那么,怎么在后台进行操作呢?自然而然就想到了Service了

在Service中执行桌面控件的操作:


@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() {
   // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。
   myWindowManager.removeSmallWindow(getApplicationContext());
   myWindowManager.createSmallWindow(getApplicationContext());

}

五、在activity中对Service绑定,进行拍照的操作


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中的拍照的开始和结束


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进行拍照的相关处理


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;

/**
* 设置定时拍照功能
*
* @author <p>
*     创建定时拍照任务
*     cameraType 摄像头
*     resolutionString 分辨率
*     tvSaveLocation 保存地址
*     etExtension 拓展名
*     cameraStart, 开始拍摄时间
*     cameraNumber, 拍摄次数
*     cameraStop 拍摄张数
*/
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;
 }

/**
  * 启动定时拍照并上传功能
  */
 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("自动聚焦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 后开始启动相机
 }

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后拍照
 }

/**
  * 检测设备是否存在Camera硬件
  */
 private boolean checkCameraHardware(Context context) {
   if (context.getPackageManager().hasSystemFeature(
       PackageManager.FEATURE_CAMERA)) {
     // 存在
     return true;
   } else {
     // 不存在
     return false;
   }
 }

/**
  * 打开一个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);
     //可以用得到当前所支持的照片大小,然后
     //List<Size> ms = mParameters.getSupportedPictureSizes();
     //mParameters.setPictureSize(ms.get(0).width, ms.get(0).height); //默认最大拍照取最大清晰度的照片
     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])); //默认最大拍照取最大清晰度的照片
     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);//扩展名
     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下载地址:https://www.jb51.net/softs/519032.html

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

来源:http://blog.csdn.net/huangxiaoguo1/article/details/53666047

标签:Android, ,
0
投稿

猜你喜欢

  • C#多线程学习之(二)操纵一个线程的方法

    2022-02-27 08:53:27
  • C#操作目录与文件的方法步骤

    2023-11-23 20:45:52
  • Android中使用Bitmap类将矩形图片转为圆形的方法

    2022-01-04 18:47:40
  • java web上传文件和下载文件代码片段分享

    2023-10-04 19:50:50
  • 利用OPENCV为android开发畸变校正的JNI库方法

    2021-10-06 17:33:27
  • Android开发InputManagerService创建与启动流程

    2021-07-11 20:45:22
  • 使用SSM+Layui+Bootstrap实现汽车维保系统的示例代码

    2023-11-28 18:30:04
  • Android巧用ViewPager实现左右循环滑动图片

    2021-07-13 16:32:32
  • Java并发之串行线程池实例解析

    2023-01-07 18:35:54
  • java单点登录(SSO)的实现

    2023-09-03 05:24:23
  • c#简单工厂、工厂方法与抽象工厂的区别分析

    2021-11-30 04:39:47
  • Android AS为xutils添加依赖过程图解

    2023-11-16 03:51:05
  • c#通过xpath读取xml示例

    2023-07-16 01:31:05
  • Android超详细讲解组件ScrollView的使用

    2022-08-05 09:55:18
  • Java与SpringBoot对redis的使用方式

    2021-06-11 19:23:39
  • C#对WPF数据绑定的菜单插入Seperator分隔

    2022-04-29 17:09:28
  • 详解SpringBoot通用配置文件(不定时更新)

    2022-12-01 09:07:04
  • 如何获取Android设备挂载的所有存储器

    2023-08-16 12:44:41
  • 用Java设计模式中的观察者模式开发微信公众号的例子

    2023-01-17 05:30:58
  • Java深入浅出掌握SpringBoot之MVC自动配置原理篇

    2022-04-16 02:14:34
  • asp之家 软件编程 m.aspxhome.com