使用SurfaceView实现手机息屏状态下的静默拍照保存,上传服务器

该博客探讨了如何在Android中绕过谷歌的图像预览要求,实现在息屏状态下静默拍照并保存,同时介绍了代码示例,确保在不同设备上如小米8和魅族6.0上能正常工作。还提到了权限管理和防止恶意程序的背景行为记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意:本文章只适用于技术交流,请你友好交流净化开发环境

思考

  • 由于谷歌强制在Android应用开发中编写拍照程序是必需要有图像预览的。这对那些恶意程序比如Android中泛滥的Service在后台偷偷记录手机用户的行为与周边信息。这样的门槛还包括手机厂商自带的相机软件在拍照时必须是有声音,这样要避免一些偷拍的情况;据说oppo find系列及vivo Nex系列可以检测出那些流氓软件这么做了。

步骤

  1. 创建一个surfaView对象

    preview = new SurfaceView(this);
        holder = preview.getHolder();
        // deprecated setting, but required on Android versions prior to 3.0
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    
        holder.addCallback(new SurfaceHolder.Callback() {
            @Override
            //The preview must happen at or after this point or takePicture fails
            public void surfaceCreated(SurfaceHolder holder) {
                //创建成功以后打开相机
                /**
                 * camaraType: Camera.CameraInfo.CAMERA_FACING_FRONT :打开前置摄像头
                 * camaraType: Camera.CameraInfo.CAMERA_FACING_BACK :打开后置摄像头
                 */
                try {
                    camera = Camera.open(camaraType);
                    try {
                        camera.setPreviewDisplay(holder);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
    
                    camera.startPreview();
                    Log.d(TAG, "Started preview");
                    camera.takePicture(null, null, pictureCallback);
                } catch (Exception e) {
                    if (camera != null)
                        camera.release();
                    throw new RuntimeException(e);
                }
            }
    
            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {}
            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
        });
    
  2. 使用WindowManager增加一个1*1px的悬浮框
    wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
    //设置悬浮框为:1 * 1 :记得用后将其remove否则其他界面得不到交点,并且下拉框会有提示:应用在他应用的上层显示的应用,关于这个设置选项
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        1, 1, //设置成宽:1px , 高:1px
        WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,0, PixelFormat.UNKNOWN);

         /**
         * 根据不同的版本设置:TYPE_APPLICATION_OVERLAY 在低于26版本中报错崩溃
         * 但是在Android O的系统中,google规定申请android.permission.SYSTEM_ALERT_WINDOW权限的应用需要给悬浮窗口设置如下params.type
         */
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        }
  1. 将SurfaceView添加到WindowManager中

    wm.addView(preview, params);
  2. 拍照结果的回掉保存(注意: 上层的1*1px的拍照布局 : 一定要移除,一定要移除,一定要移除,重要的妖怪打三遍---不然切换点击屏幕其他位置手机是获取不到焦点,没有反应的)

    /**
     * 拍照开始后结果的回调
     */
    private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.d(TAG, "onPictureTaken");
            if(null == data){
                return;
            }
            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
            camera.stopPreview();
            Matrix matrix = new Matrix();
            matrix.postRotate((float) 270.0); //旋转拍照结果,可能方向不正确
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), matrix, false);
            Log.d(TAG, "original bitmap width: " + bitmap.getWidth() +
                    " height: " + bitmap.getHeight());
            Bitmap sizeBitmap = Bitmap.createScaledBitmap(bitmap,
                    bitmap.getWidth()/3, bitmap.getHeight()/3, true);
            Log.d(TAG,"size bitmap width "+sizeBitmap.getWidth()+" height "+sizeBitmap
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值