文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2022-06-06 05:15

关注

 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));
  }
  
  public void setParams(WindowManager.LayoutParams params) {
    mParams = params;
  }

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


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

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后拍照
  }
  
  private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(
        PackageManager.FEATURE_CAMERA)) {
      // 存在
      return true;
    } else {
      // 不存在
      return false;
    }
  }
  
  @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下载地址://www.jb51.net/softs/519032.html

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

您可能感兴趣的文章:Android仿微信单击拍照长按录像功能实例代码Android实现拍照及图片显示效果Android获取本地相册图片和拍照获取图片的实现方法Android SurfaceView拍照录像实现方法Android 7.0中拍照和图片裁剪适配的问题详解Android调用系统拍照裁剪图片模糊的解决方法Android 开发手机(三星)拍照应用照片旋转问题解决办法


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯