【问题标题】:Capture image in service without preview android在没有预览android的情况下在服务中捕获图像
【发布时间】:2018-08-16 11:10:11
【问题描述】:

问题陈述:

当有人尝试使用错误的图案/PIN 码打开设备时,我的应用程序应触发警报,向注册的手机号码发送警报短信。并且它应该捕获尝试解锁设备的人的图像,并将此图像发送到注册的电子邮件 ID。

我所取得的成就:

  • 我在DeviceAdmin 课程中收到错误模式/PIN 的通知。
  • 我启动后台任务服务。此服务成功播放警报。
  • 我向注册的手机号码发送了一条提醒短信。 我成功向注册的email ID 发送了一封警报电子邮件。 (但没有图像。)

我很困惑如何在设备锁定时在背景IntentService 中捕获图像,而且在没有预览的情况下也是如此。

我显然不能使用Camera intent。因为不能从Service 调用startActivityForResult。另外,我不希望用户在打开相机应用程序后捕捉图像。

我的研究已经引导我找到这些帖子。

Can I use Android Camera in service without preview?

How to Capture Image When Device is Locked

问题是:

Camera API 已弃用。 Camera2 API 需要最低 sdk 版本 21,

但我客户的要求是 minSdkVersion 15,我无法更改。我无法弄清楚我现在应该做什么。请问有什么参考或帮助吗?

【问题讨论】:

  • 使用Camera API。 Android 中的“已弃用”意味着“我们认为您应该考虑其他一些事情”——android.hardware.Camera 继续工作(和以往一样)。请注意,出于隐私原因,您需要在 Android 9.0+ 上使用前台服务。

标签: android camera


【解决方案1】:

我在this blog 的帮助下解决了我的问题

所以我使用以下代码在后台服务中捕获图像:

@Override
public void onStart(Intent intent, int startId) {
    mCamera = getAvailableFrontCamera();     // globally declared instance of camera
    if (mCamera == null){
        mCamera = Camera.open();    //Take rear facing camera only if no front camera available
    }
    SurfaceView sv = new SurfaceView(getApplicationContext());
    SurfaceTexture surfaceTexture = new SurfaceTexture(10);

    try {
        mCamera.setPreviewTexture(surfaceTexture);
        //mCamera.setPreviewDisplay(sv.getHolder());
        parameters = mCamera.getParameters();

        //set camera parameters
        mCamera.setParameters(parameters);


        //This boolean is used as app crashes while writing images to file if simultaneous calls are made to takePicture
        if(safeToCapture) {
            mCamera.startPreview();
            mCamera.takePicture(null, null, mCall);
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    //Get a surface
    sHolder = sv.getHolder();
    //tells Android that this surface will have its data constantly replaced
    sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

Camera.PictureCallback mCall = new Camera.PictureCallback()
{

    public void onPictureTaken(byte[] data, Camera camera)
    {
        safeToCapture = false;
        //decode the data obtained by the camera into a Bitmap

        FileOutputStream outStream = null;
        try{

            // create a File object for the parent directory
            File myDirectory = new File(Environment.getExternalStorageDirectory()+"/Test");
            // have the object build the directory structure, if needed.
            myDirectory.mkdirs();

            //SDF for getting current time for unique image name
            SimpleDateFormat curTimeFormat = new SimpleDateFormat("ddMMyyyyhhmmss");
            String curTime = curTimeFormat.format(new java.util.Date());

            // create a File object for the output file
            outStream = new FileOutputStream(myDirectory+"/user"+curTime+".jpg");
            outStream.write(data);
            outStream.close();
            mCamera.release();
            mCamera = null;

            String strImagePath = Environment.getExternalStorageDirectory()+"/"+myDirectory.getName()+"/user"+curTime+".jpg";
            sendEmailWithImage(strImagePath);
            Log.d("CAMERA", "picture clicked - "+strImagePath);
        } catch (FileNotFoundException e){
            Log.d("CAMERA", e.getMessage());
        } catch (IOException e){
            Log.d("CAMERA", e.getMessage());
        }

        safeToCapture = true;    //Set a boolean to true again after saving file.

    }
};

private Camera getAvailableFrontCamera (){

    int cameraCount = 0;
    Camera cam = null;
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    cameraCount = Camera.getNumberOfCameras();
    for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
        Camera.getCameraInfo(camIdx, cameraInfo);
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            try {
                cam = Camera.open(camIdx);
            } catch (RuntimeException e) {
                Log.e("CAMERA", "Camera failed to open: " + e.getLocalizedMessage());
            }
        }
    }

    return cam;
}


//Send Email using javamail API as user will not be allowed to choose available
// application using a Chooser dialog for intent.
public void sendEmailWithImage(String imageFile){
    .
    .
    .
}

在清单文件中将需要以下使用功能和权限:

<uses-feature
    android:name="android.hardware.camera"
    android:required="false" />
<uses-feature
    android:name="android.hardware.camera.front"
    android:required="false" />

<uses-permission android:name="android.permission.SEND_MAIL" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

我已将属性 required 设置为 false,因此即使没有任何可用的相机,用户也可以安装我的应用程序。可能这可以帮助将来的人。

【讨论】:

  • 删除样板代码。像 SurfaceView 一样,它没有被使用。如果您使用的是 SurfaceTexture,则无需使用 SurfaceView。此外,存储方法不适用于 android 11+(已测试)。由于实现了作用域存储。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
相关资源
最近更新 更多