欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2024-02-27 17:16:09
 android 偷拍功能/手机关闭能拍照 效果如下: 其实偷拍与偷录实现方式是一样的,都是使用到的windowmanager来绘制桌面小控件的原理...

 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下载地址:

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