首页 > 代码库 > android不知不觉偷拍他人功能实现(手机关闭依然拍照)

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下载地址:http://download.csdn.net/download/huangxiaoguo1/9711899

有什么不足,望大家指教,谢谢….

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    android不知不觉偷拍他人功能实现(手机关闭依然拍照)