Android 偷拍功能实现(手机关闭依然拍照)详解及实例代码
程序员文章站
2024-02-27 17:16:09
android 偷拍功能/手机关闭能拍照
效果如下:
其实偷拍与偷录实现方式是一样的,都是使用到的windowmanager来绘制桌面小控件的原理...
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下载地址:
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
上一篇: Java多线程中线程间的通信实例详解
下一篇: java构造函数示例(构造方法)