Android 相机在后台

标签 android android-camera android-service surfaceview android-windowmanager

我正在尝试创建一个 android 应用程序,该应用程序可以在服务启动后在后台捕获图像。我能够捕获它并保存在 SD 卡上,但捕获的图像有点暗,我无法追踪问题所在。 有哪些可能?

捕获的图像:http://imgur.com/8onjW60

public class MyService extends Service {

Camera mCamera;
public String imageEncodeString,imageName;
public Bitmap bitmap;
public File file;

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

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        if (data != null) {
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

            if (bitmap != null) {
                imageName = String.valueOf(System.currentTimeMillis() + ".jpg");
                File basedir =  new File(Environment.getExternalStorageDirectory() + "/dirr");
                file = new File(Environment.getExternalStorageDirectory() + "/dirr" + File.separator + imageName);
                if (!basedir.isDirectory()) {
                    basedir.mkdirs();
                }
                try {
                    file.createNewFile();
                    FileOutputStream otstream = new FileOutputStream(file);
                    bitmap.compress(Bitmap.CompressFormat.JPEG,100,otstream);
                    byte[] img =new byte[0];
                    otstream.write(img);
                    otstream.flush();
                    otstream.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            mCamera.startPreview();
        }

    }

};

public MyService() {

}

public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(MyService.this, "Starting Service...", Toast.LENGTH_SHORT).show();
    Log.d("TAG", "======= service in onStartCommand");

    if (checkCameraHardware(this)) {
        mCamera = getCameraInstance();
        if (mCamera != null) {
            SurfaceView sv = new SurfaceView(this);

           WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
            WindowManager.LayoutParams params = new WindowManager.LayoutParams(1, 1,
                    WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                    PixelFormat.TRANSPARENT);
                    params.alpha = 0;

            SurfaceHolder sh = sv.getHolder();
            sv.setZOrderOnTop(true);
            sh.setFormat(PixelFormat.TRANSPARENT);

            sh.addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    Camera.Parameters parameters = mCamera.getParameters();
                    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                    parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
                    parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
                    mCamera.setParameters(parameters);

                    Camera.Parameters p = mCamera.getParameters();

                    List<Camera.Size> listSize;

                    listSize = p.getSupportedPreviewSizes();
                    Camera.Size mPreviewSize = listSize.get(2);
                    Log.v("TAG", "preview width = " + mPreviewSize.width
                            + " preview height = " + mPreviewSize.height);
                    p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

                    listSize = p.getSupportedPictureSizes();
                    Camera.Size mPictureSize = listSize.get(2);
                    Log.v("TAG", "capture width = " + mPictureSize.width
                            + " capture height = " + mPictureSize.height);
                    p.setPictureSize(mPictureSize.width, mPictureSize.height);
                    mCamera.setParameters(p);

                    try {
                        mCamera.setPreviewDisplay(holder);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    // mCamera.startPreview();
                    //  mCamera.takePicture(null, null, mPictureCallback); // used to takePicture.

                    // Log.d("TAG", "========= Capturing Started");

                    //  mCamera.stopPreview();
                    //  mCamera.release();
                    //  Log.d("TAG", "========== Capturing finished.");

                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

                }

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    mCamera.stopPreview();
                    mCamera.release();
                }

            });
            wm.addView(sv, params);
        } else {
            Log.d("TAG", "==== get Camera from service failed");
        }
}else {
        Log.d("TAG", "==== There is no camera hardware on device.");
    }

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.d("TAG", "========= Capturing Started");
            mCamera.startPreview();
            mCamera.takePicture(null, null, mPictureCallback);
            Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
            vibrator.vibrate(1000);

            Log.d("TAG", "========== Capturing finished.");
        }
    }, 5000);

    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onCreate() {

    super.onCreate();
}

@Override
public void onDestroy() {
    Toast.makeText(MyService.this, "Service Stopped...", Toast.LENGTH_SHORT).show();
}

public static boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        return true;
    } else {
        return false;
    }
}

public static Camera getCameraInstance() {
    Camera c = null;
    try {
        c = Camera.open();
    } catch (Exception e) {
        Log.d("TAG", "Open camera failed: " + e);
    }

    return c;
}

}

最佳答案

我认为 takePicture() 应该延迟一点,让相机在预览开始后适应光照条件。

您必须等待多少数百毫秒取决于设备和照明条件。不幸的是,与焦点不同,没有回调指示曝光/增益调整已完成。

转念一想,成功的onAutoFocus()可能是相机稳定的一个很好的指示。另一个无效的选择是注册到 onPreviewFrame() 回调并检查到达帧的亮度是否稳定。

从服务开始不应该改变这种情况。

关于Android 相机在后台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36246207/

相关文章:

android - 从Android应用程序中的网站获取最新内容

java - 如何理解导致ArrayIndexOutOfBoundsException异常的mod计算的数学公式?

javascript - setTimeout 未在 android webkit 中调用

android - 打开新 fragment 时取消绑定(bind)/关闭所有cameraX组件

android - 如何从 Activity 中停止 START_STICKY android 服务

android - 通过服务类将项目添加到 RecyclerView

android - Linux 到 Android 蓝牙网络共享 (PAN)

android - 如果 SurfaceView 尺寸不是支持的尺寸之一,camera2 将崩溃

java - 如何纵向打开相机?

java - 让 Android 服务监听硬件键按下事件