Home > Enterprise >  How Can I take pictures in a new Thread which is created in a service?
How Can I take pictures in a new Thread which is created in a service?

Time:03-04

I am taking pictures in a background service, by creating a new thread. The issue is camera.takePicture is not executed. service starts, stops and iterates correctly just takePicture is not executed. It shows W/Camera-JNI: callback on dead camera object in the logcat in each iteration.

Here is My CameraService class

package com.flynn.pictureseverysecond;


import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;


public class CameraService extends Service implements Info {
    public static final int MEDIA_TYPE_IMAGE = 1;

    volatile boolean running = true;

    private Camera mCamera;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand: service started");
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "run: Thread still alive");
                while (running) {
                    mCamera = Util.getCameraInstance();
                    Log.i(TAG, "run: created camera instance");
                    if (mCamera != null) {
                        try {
                            mCamera.setPreviewTexture(new SurfaceTexture(0));
                            mCamera.startPreview();
                            Log.i(TAG, "run: preview set");
                            mCamera.takePicture(null, null, new Camera.PictureCallback() {

                                @Override
                                public void onPictureTaken(byte[] data, Camera camera) {
                                    Log.i(TAG, "onPictureTaken: here");
                                    File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
                                    if (pictureFile == null) {
                                        Log.e(TAG, "onPictureTaken: cannot create media files check Permissions");
                                        return;
                                    }
                                    try {
                                        Log.i(TAG, "onPictureTaken: arrived");
                                        FileOutputStream fos = new FileOutputStream(pictureFile);
                                        fos.write(data);
                                        fos.close();
                                    } catch (FileNotFoundException e) {
                                        Log.e(TAG, "onPictureTaken: File not found"   e.getMessage());
                                    } catch (IOException e) {
                                        Log.e(TAG, "onPictureTaken: Error Accessing File "   e.getMessage());
                                    }
                                }
                            });
                            releaseCamera();
                            Thread.sleep(3000);
                        } catch (IOException | InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy: cam service ending....");
        running = false;
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private static Uri getOutputMediaFileUri(int type) {
        return Uri.fromFile(getOutputMediaFile(type));
    }

    private static File getOutputMediaFile(int type) {
        Log.i(TAG, "getOutputMediaFile: inside");
        File storageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "fuckrey");
        Log.i(TAG, "getOutputMediaFile: dir created");
        if (!storageDir.exists()) {
            if (!storageDir.mkdirs()) {
                Log.e(TAG, "getOutputMediaFile: Failed to create directory");
                return null;
            }
        }

        @SuppressLint("SimpleDateFormat")
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
        if (type == MEDIA_TYPE_IMAGE) {
            mediaFile = new File(storageDir.getPath()   File.separator   "IMG_"   timeStamp   ".jpg");
        } else {
            Log.i(TAG, "getOutputMediaFile: returning null");
            return null;
        }

        Log.i(TAG, "getOutputMediaFile: properly returning");
        return mediaFile;
    }


        private void releaseCamera () {
            if (mCamera != null) {
                mCamera.release();        // release the camera for other applications
                mCamera = null;
            }
        }

}

Please Help me, what is wrong with my code?

CodePudding user response:

Background services cannot access the camera. Forground services can only if you specify the camera service type. And yours is definitely a background service. This was added back in Android 11.

  • Related