我可以在没有预览的情况下使用 Android 相机吗?
Can I use Android Camera in service without preview?
我在 Android 中创建了一个应用程序,使用相机我可以测量用户面部与 phone 屏幕之间的距离。
问题描述:
现在我想将其设置为 运行 背景,以便在我使用其他应用程序时可以使用该功能。 这意味着 我应该打开没有预览的相机在服务中,并在服务中对其进行处理。
我还做了什么:
我在这里提到了一些问题
How to record video from background of application : Android
How to use Android Camera in Background?
Taking picture from camera without preview
API 16级
我的服务文件
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.media.MediaRecorder;
import android.os.IBinder;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class RecorderService extends Service {
private static final String TAG = "RecorderService";
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private static Camera mServiceCamera;
private boolean mRecordingStatus;
private MediaRecorder mMediaRecorder;
File path = android.os.Environment.getExternalStorageDirectory();
@Override
public void onCreate() {
Log.i(TAG,"onCreate");
mRecordingStatus = false;
//mServiceCamera = CameraRecorder.mCamera;
mServiceCamera = Camera.open(1);
mSurfaceView = MainActivity.mSurfaceView;
mSurfaceHolder = MainActivity.mSurfaceHolder;
super.onCreate();
if (mRecordingStatus == false)
startRecording();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDestroy() {
Log.i(TAG,"onDestroy");
stopRecording();
mRecordingStatus = false;
super.onDestroy();
}
public boolean startRecording(){
Log.i(TAG,"startRecording");
try {
Toast.makeText(getBaseContext(), "Recording Started", Toast.LENGTH_SHORT).show();
//mServiceCamera = Camera.open();
Camera.Parameters params = mServiceCamera.getParameters();
mServiceCamera.setParameters(params);
Camera.Parameters p = mServiceCamera.getParameters();
final List<Size> listSize = p.getSupportedPreviewSizes();
Size mPreviewSize = listSize.get(2);
Log.v(TAG, "use: width = " + mPreviewSize.width
+ " height = " + mPreviewSize.height);
p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mServiceCamera.setParameters(p);
try {
mServiceCamera.setPreviewDisplay(mSurfaceHolder);
mServiceCamera.startPreview();
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
mServiceCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mServiceCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mMediaRecorder.setOutputFile(path+"/outputVideo.mp4");
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mPreviewSize.width, mPreviewSize.height);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
mRecordingStatus = true;
return true;
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
} catch (IOException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
}
}
public void stopRecording() {
Log.i(TAG,"stopRecording");
Toast.makeText(getBaseContext(), "Recording Stopped", Toast.LENGTH_SHORT).show();
try {
mServiceCamera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try{
mMediaRecorder.stop();
}catch (Exception ignored)
{
}
mMediaRecorder.reset();
mMediaRecorder.release();
mServiceCamera.stopPreview();
mServiceCamera.release();
mServiceCamera = null;
}
}
可以参考这个Question,里面讨论了如何在服务中进行录像。抓图步骤同上
为达到您的要求,您可能需要:
- 在您的服务中获取相机实例。检查这个 Official Guideline.
- 设置你的相机参数。使用
Camera.getParameters()
、Camera.setParameters()
、Camera.Parameters.setPictureSize(int with, int height)
和 Camera.Parameters.setPictureFormat(int format)
等 API。
- 准备一个用于存储图像的文件。为此,您需要实施
Camera.PictureCallback
。
- 拍照前请致电
Camera.startPreview()
。如果您在拍照前不调用此函数,您将得到异常。 (注意:您不需要先执行 Camera.setPreviewdisplay(SurfaceHolder display)
。)
- 在您的服务中调用
camera.takePicture()
。然后就可以将抓拍到的图片存储到你指定的文件中了。
它工作后,请不要忘记在生命周期内正确维护acquire/release相机的资源。
这是我的sample code on Github,评论里也提到了
我在 Android 中创建了一个应用程序,使用相机我可以测量用户面部与 phone 屏幕之间的距离。
问题描述:
现在我想将其设置为 运行 背景,以便在我使用其他应用程序时可以使用该功能。 这意味着 我应该打开没有预览的相机在服务中,并在服务中对其进行处理。
我还做了什么:
我在这里提到了一些问题
How to record video from background of application : Android
How to use Android Camera in Background?
Taking picture from camera without preview
API 16级
我的服务文件
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.media.MediaRecorder;
import android.os.IBinder;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class RecorderService extends Service {
private static final String TAG = "RecorderService";
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private static Camera mServiceCamera;
private boolean mRecordingStatus;
private MediaRecorder mMediaRecorder;
File path = android.os.Environment.getExternalStorageDirectory();
@Override
public void onCreate() {
Log.i(TAG,"onCreate");
mRecordingStatus = false;
//mServiceCamera = CameraRecorder.mCamera;
mServiceCamera = Camera.open(1);
mSurfaceView = MainActivity.mSurfaceView;
mSurfaceHolder = MainActivity.mSurfaceHolder;
super.onCreate();
if (mRecordingStatus == false)
startRecording();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDestroy() {
Log.i(TAG,"onDestroy");
stopRecording();
mRecordingStatus = false;
super.onDestroy();
}
public boolean startRecording(){
Log.i(TAG,"startRecording");
try {
Toast.makeText(getBaseContext(), "Recording Started", Toast.LENGTH_SHORT).show();
//mServiceCamera = Camera.open();
Camera.Parameters params = mServiceCamera.getParameters();
mServiceCamera.setParameters(params);
Camera.Parameters p = mServiceCamera.getParameters();
final List<Size> listSize = p.getSupportedPreviewSizes();
Size mPreviewSize = listSize.get(2);
Log.v(TAG, "use: width = " + mPreviewSize.width
+ " height = " + mPreviewSize.height);
p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mServiceCamera.setParameters(p);
try {
mServiceCamera.setPreviewDisplay(mSurfaceHolder);
mServiceCamera.startPreview();
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
mServiceCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mServiceCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mMediaRecorder.setOutputFile(path+"/outputVideo.mp4");
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mPreviewSize.width, mPreviewSize.height);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
mRecordingStatus = true;
return true;
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
} catch (IOException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
}
}
public void stopRecording() {
Log.i(TAG,"stopRecording");
Toast.makeText(getBaseContext(), "Recording Stopped", Toast.LENGTH_SHORT).show();
try {
mServiceCamera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try{
mMediaRecorder.stop();
}catch (Exception ignored)
{
}
mMediaRecorder.reset();
mMediaRecorder.release();
mServiceCamera.stopPreview();
mServiceCamera.release();
mServiceCamera = null;
}
}
可以参考这个Question,里面讨论了如何在服务中进行录像。抓图步骤同上
为达到您的要求,您可能需要:
- 在您的服务中获取相机实例。检查这个 Official Guideline.
- 设置你的相机参数。使用
Camera.getParameters()
、Camera.setParameters()
、Camera.Parameters.setPictureSize(int with, int height)
和Camera.Parameters.setPictureFormat(int format)
等 API。 - 准备一个用于存储图像的文件。为此,您需要实施
Camera.PictureCallback
。 - 拍照前请致电
Camera.startPreview()
。如果您在拍照前不调用此函数,您将得到异常。 (注意:您不需要先执行Camera.setPreviewdisplay(SurfaceHolder display)
。) - 在您的服务中调用
camera.takePicture()
。然后就可以将抓拍到的图片存储到你指定的文件中了。
它工作后,请不要忘记在生命周期内正确维护acquire/release相机的资源。
这是我的sample code on Github,评论里也提到了