When i try to record video from camera which seems with an error prepare failed: -1.
I search lot and I cant get any acceptable answers from anywhere. here is my code below.
I don't know it by parameter? and by unlocking camera. Any one who can it will be grateful.
package com.camara.activity;
import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CamcorderView extends SurfaceView implements
SurfaceHolder.Callback {
MediaRecorder recorder;
SurfaceHolder holder;
String outputFile = "/sdcard/default.mp4";
public CamcorderView(Context context, AttributeSet attrs) {
super(context, attrs);
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
recorder.setVideoSize(480, 320);
recorder.setVideoFrameRate(10);
recorder.setMaxDuration(10000);
}
public void surfaceCreated(SurfaceHolder holder) {
recorder.setOutputFile(outputFile);
recorder.setPreviewDisplay(holder.getSurface());
if (recorder != null) {
try {
recorder.prepare();
} catch (IllegalStateException e) {
Log.e("IllegalStateException", e.toString());
} catch (IOException e) {
Log.e("IOException", e.toString());
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void setOutputFile(String filename) {
outputFile = filename;
recorder.setOutputFile(filename);
}
public void startRecording() {
recorder.start();
}
public void stopRecording() {
recorder.stop();
recorder.release();
}
}
following is the output from the logcat
01-10 17:33:00.450: I/MediaRecorderJNI(14046): prepare: surface=0x243398 (id=1)
01-10 17:33:00.500: E/MediaRecorder(14046): prepare failed: -1
01-10 17:33:00.500: E/IOException(14046): java.io.IOException: prepare failed.
thanks in advance.
Ok I actually found my mistake. Because of course there was a mistake. Actually I wanted to have a preview and recording at the same time, and thought I had to use the object Camera for that. But Actually the MediaRecorder does that by itself using SetDisplayPreview and .... MediaRecord.Prepare :)
I'm in a good mood, so here's all the class ;)
import java.io.File;
import java.io.IOException;
import android.content.Context;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.media.MediaRecorder.OnInfoListener;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.FrameLayout;
public class ModuleVideo implements SurfaceHolder.Callback, OnInfoListener
{
public static final int STATE_NONE = -1;
public static final int STATE_STOPPED = 0;
public static final int STATE_PREVIEW = 1;
public static final int STATE_CAPTURE = 2;
public static final int STATE_RECORDING = 3;
private SurfaceHolder mHolder;
private MediaRecorder mRecorder;
private SurfaceView mCameraView;
private Context mContext;
private FrameLayout mParent;
private int mState;
private boolean mRecording;
public ModuleVideo(Context context, FrameLayout parent)
{
//Initiate the Surface Holder properly
mParent = parent;
mContext = context;
mRecorder = null;
mState = STATE_NONE;
mRecording = false;
}
private void Init()
{
mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile camcorderProfile_HQ = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
mRecorder.setProfile(camcorderProfile_HQ);
mRecorder.setOutputFile("/sdcard/MY_VIDEO.mp4");
}
private void Prepare()
{
try
{
mRecorder.setPreviewDisplay(mHolder.getSurface());
mRecorder.prepare();
}
catch (IllegalStateException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void UI_StartPreview()
{
if(mState == STATE_STOPPED || mState == STATE_NONE)
{
mRecorder= new MediaRecorder();
Init();
mCameraView= new SurfaceView(mContext);
mParent.addView(mCameraView);
this.mHolder = mCameraView.getHolder();
this.mHolder.addCallback(this);
this.mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
}
public void UI_StopPreview()
{
if(mState == STATE_PREVIEW)
{
if(mRecording)
{
UI_StopRecord();
}
if(mRecorder != null)
{
mRecorder.release();
mRecorder= null;
}
mParent.removeView(mCameraView);
//mCameraView= null;
}
}
public boolean UI_StartRecord()
{
if(mState != STATE_PREVIEW )
{
return false;
}
String path= "/sdcard/PLUS_VIDEO.mp4";
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(Environment.MEDIA_MOUNTED))
{
return false;
}
File directory = new File(path).getParentFile();
if(!directory.exists() && !directory.mkdirs())
{
return false;
}
mRecorder.start();
mRecording= true;
mState= STATE_RECORDING;
return true;
}
public void UI_StopRecord()
{
if(mRecorder != null)
{
mRecorder.stop();
mRecorder.reset();
Init();
Prepare();
mRecording= false;
mState= STATE_PREVIEW;
}
}
public boolean UI_IsRecording()
{
return mRecording;
}
#Override
public void onInfo(MediaRecorder mr, int what, int extra)
{
// TODO Auto-generated method stub
Log.i(null, "onInfo");
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
Prepare();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
mState= STATE_PREVIEW;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
mState= STATE_STOPPED;
}
}
Related
I have a SurfaceView showing a CameraSource and I want the camera to focus automatically. Also, when the user taps the SurfaceView, I want the camera to focus on the tapped area. The autofocus is already enabled, but the manual focus is not and I dont know how to add that, any tips?
My code so far:
public class MyActivity extends AppCompatActivity {
SurfaceView cameraPreview;
BarcodeDetector barcodeDetector;
CameraSource cameraSource;
final Integer requestCameraPermissionID = 1001;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity_layout);
final int height = getSurfaceViewHeight();
final int width = getSurfaceViewWidth();
cameraPreview = findViewById(R.id.surfaceview_scanner);
barcodeDetector = new BarcodeDetector.Builder(AddScanningActivity.this)
.setBarcodeFormats(Barcode.ALL_FORMATS)
.build();
cameraSource = new CameraSource.Builder(AddScanningActivity.this, barcodeDetector)
.setAutoFocusEnabled(false)
.setRequestedPreviewSize(width, height)
.build();
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
// handle detections
}
});
cameraPreview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// handle manual focus here?
}
});
cameraPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(AddScanningActivity.this,
new String[]{Manifest.permission.CAMERA}, requestCameraPermissionID);
return;
}
try {
cameraSource.start(cameraPreview.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
}
}, 100);
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
cameraSource.stop();
}
});
}
}
If it is not possible to have autofocus and manual focus in the same SurfaceView, I would rather have manual focus than autofocus.
As you are making barcode app i will suggest you to use FOCUS_MODE_FIXED,
or
FOCUS_MODE_MACRO
package com.example.yaumanualcamera;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Camera;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
TextureView textureview;
CameraDevice cameraDevice;
String cameraId;
Size imageDimensions;
CaptureRequest.Builder captureRequestBuilder;
CameraCaptureSession cameraSession;
Handler backgroundHandler;
HandlerThread handleThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureview = (TextureView) findViewById(R.id.texture);
textureview.setSurfaceTextureListener(surfaceTextureListener);
}
TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
try {
openCamera();
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private void openCamera() throws CameraAccessException {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
cameraId = cameraManager.getCameraIdList()[0];
CameraCharacteristics cc = cameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = cc.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
imageDimensions = map.getOutputSizes(SurfaceTexture.class)[0];
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
cameraManager.openCamera(cameraId, stateCallback, null);
}
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
try {
startCameraPreview();
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onDisconnected(#NonNull CameraDevice camera) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
private void startCameraPreview() throws CameraAccessException {
SurfaceTexture texture = textureview.getSurfaceTexture();
texture.setDefaultBufferSize(imageDimensions.getWidth(), imageDimensions.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
System.out.println("Focus 1 ====== "+captureRequestBuilder.get(CaptureRequest.LENS_FOCUS_DISTANCE));
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession session) {
if (cameraDevice == null) {
return;
}
cameraSession = session;
try {
updatePreview();
} catch (CameraAccessException e) {
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession session) {
}
}, null);
}
private void initPreview() {
float valueAF;
valueAF = 10.0f;
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,CameraMetadata.CONTROL_MODE_AUTO);
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_OFF);
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, valueAF);
}
private void updatePreview() throws CameraAccessException {
if (cameraDevice == null) {
return;
}
initPreview();
System.out.println("Focus 2 ====== "+captureRequestBuilder.get(CaptureRequest.LENS_FOCUS_DISTANCE));
cameraSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if (textureview.isAvailable()) {
try {
openCamera();
} catch (CameraAccessException e) {
e.printStackTrace();
}
} else {
textureview.setSurfaceTextureListener(surfaceTextureListener);
}
}
private void startBackgroundThread() {
handleThread = new HandlerThread("CAMERA BACKGROUND");
handleThread.start();
backgroundHandler = new Handler(handleThread.getLooper());
}
#Override
protected void onPause() {
try {
stopBackgroundThread();
} catch (InterruptedException e) {
e.printStackTrace();
}
super.onPause();
}
private void stopBackgroundThread() throws InterruptedException {
handleThread.quitSafely();
handleThread.join();
backgroundHandler = null;
handleThread = null;
}
}
How can we apply filters like sepia, vintage, etc. to a video, and consequently post the same on our servers?
Likewise, we can bluff user by creating a filter layer on TextureView, and consequently applying the corresponding filter on the server.
CODE :
package com.example.mediaplayerdemo_video;
import java.io.IOException;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
public class MainActivity extends Activity implements TextureView.SurfaceTextureListener {
// Log tag.
private static final String TAG = MainActivity.class.getName();
// Asset video file name.
private static final String FILE_NAME = "test.mp4";
// MediaPlayer instance to control playback of video file.
private MediaPlayer mMediaPlayer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
TextureView textureView = (TextureView) findViewById(R.id.textureView);
textureView.setSurfaceTextureListener(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
Surface surface = new Surface(surfaceTexture);
try {
AssetFileDescriptor afd = getAssets().openFd(FILE_NAME);
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mMediaPlayer.setSurface(surface);
mMediaPlayer.setLooping(true);
mMediaPlayer.prepareAsync();
// Play video when the media source is ready for playback.
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
} catch (IllegalArgumentException e) {
Log.d(TAG, e.getMessage());
} catch (SecurityException e) {
Log.d(TAG, e.getMessage());
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
}
I am using this code to test things out: https://gist.github.com/ErikHellman/5840101
This works fine for videos stored on the device. However for streaming videos, I am not able to switch views at runtime.
The streaming url that I am using is this: rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov
The only way I can get it to work is by if I reset my player. However, since I am streaming the video, resetting or releasing the player is not an option for me.
Below is my code for the MainActivity:
package com.example.testvideo;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
#SuppressWarnings("ConstantConditions")
public class MainActivity extends Activity {
private static final int PICK_VIDEO_REQUEST = 1001;
private static final String TAG = "SurfaceSwitch";
private MediaPlayer mMediaPlayer;
private SurfaceHolder mFirstSurface;
private SurfaceHolder mSecondSurface;
private SurfaceHolder mActiveSurface;
private Uri mVideoUri;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SurfaceView first = (SurfaceView) findViewById(R.id.firstSurface);
first.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, "First surface created!");
mFirstSurface = surfaceHolder;
if (mVideoUri != null) {
mMediaPlayer = MediaPlayer.create(getApplicationContext(),
mVideoUri, mFirstSurface);
mActiveSurface = mFirstSurface;
mMediaPlayer.start();
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, "First surface destroyed!");
}
});
SurfaceView second = (SurfaceView) findViewById(R.id.secondSurface);
second.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, "Second surface created!");
mSecondSurface = surfaceHolder;
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, "Second surface destroyed!");
}
});
}
#Override
protected void onPause() {
super.onPause();
mVideoUri = null;
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_VIDEO_REQUEST && resultCode == RESULT_OK) {
Log.d(TAG, "Got video " + data.getData());
//mVideoUri = data.getData();
mVideoUri = Uri.parse("rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov");
}
}
public void doStartStop(View view) {
if (mMediaPlayer == null) {
Intent pickVideo = new Intent(Intent.ACTION_PICK);
pickVideo.setTypeAndNormalize("video/*");
startActivityForResult(pickVideo, PICK_VIDEO_REQUEST);
} else {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
public void doSwitchSurface(View view) {
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
mActiveSurface = mFirstSurface == mActiveSurface ? mSecondSurface : mFirstSurface;
mMediaPlayer.setDisplay(mActiveSurface);
}
}
}
I made a camera preview app for android and everything works fine even when I press the power button to make device asleep, and waking it up again. But when my activity goes to background (like pressing home button) and then it comes to foreground again the program stops.
This is my activity code:
package com.example.campreview;
import com.example.campreview.CameraPreview;
import com.example.campreview.R;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.view.Menu;
import android.view.View;
public class ScanActivity extends Activity {
private CameraPreview CamPrev = null;
private FrameLayout PreviewFrm;
private Camera cam = null;
private Handler atfcs;
private ImageScanner scnr;
private boolean hascam = false;
private boolean prvng = true;
private boolean paused = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
PreviewFrm = (FrameLayout)findViewById(R.id.PreviewFrm);
StartCamera();
if (cam != null) {
hascam = true;
atfcs = new Handler();
CamPrev = new CameraPreview(this, cam, PreviewCB, AutoFocusCB);
PreviewFrm.addView(CamPrev);
}
}
#Override
public void onPause() {
ReleaseCamera();
paused = true;
super.onPause();
}
#Override
public void onResume() {
super.onResume();
if (paused) StartPreview();
}
private boolean StartCamera() {
boolean r = true;
if (cam == null) {
try {
cam = Camera.open();
} catch (Exception e) {
cam = null;
r = false;
}
if (cam != null) {
try {
Camera.Parameters p = cam.getParameters();
if (p.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO))
p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
if (p.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_OFF))
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
if (p.getSupportedPreviewFormats().contains(ImageFormat.NV21))
p.setPreviewFormat(ImageFormat.NV21);
Camera.Size s = null;
int a = 0, b;
for (Camera.Size z : p.getSupportedPreviewSizes()) {
b = z.width * z.height;
if (Math.abs(b - 307200) < Math.abs(a - 307200)) { //640x480 is the best
s = z;
a = b;
}
}
if (a != 0) p.setPreviewSize(s.width, s.height);
cam.setParameters(p);
cam.setDisplayOrientation(90);
if (CamPrev != null) cam.setPreviewDisplay(CamPrev.getHolder());
} catch (Exception e) {
r = false;
cam.release();
cam = null;
}
}
}
return r;
}
private void ReleaseCamera() {
if (cam != null) {
StopPreview();
cam.release();
cam = null;
}
}
public void StartPreview() {
if ((!prvng) & hascam) {
if (StartCamera()) {
cam.setPreviewCallback(PreviewCB);
cam.startPreview();
cam.autoFocus(AutoFocusCB);
prvng = true;
}
}
}
public void StopPreview() {
if (prvng) {
cam.stopPreview();
cam.setPreviewCallback(null);
prvng = false;
}
}
private Runnable DoAutoFocus = new Runnable() {
public void run() {
if (prvng) cam.autoFocus(AutoFocusCB);
}
};
AutoFocusCallback AutoFocusCB = new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
atfcs.postDelayed(DoAutoFocus, 1000);
}
};
PreviewCallback PreviewCB = new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
//
}
};
}
And this is the preview code:
package com.example.campreview;
import java.io.IOException;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.AutoFocusCallback;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder hldr;
private Camera cam;
private PreviewCallback pcb;
private AutoFocusCallback afcb;
public CameraPreview(Context context, Camera camera, PreviewCallback previewCb, AutoFocusCallback autoFocusCb) {
super(context);
cam = camera;
pcb = previewCb;
afcb = autoFocusCb;
hldr = getHolder();
hldr.addCallback(this);
//hldr.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
cam.setPreviewDisplay(holder);
} catch (IOException e) {
// No Code
}
}
public void surfaceDestroyed(SurfaceHolder holder) {}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (hldr.getSurface() == null) return;
try {
cam.stopPreview();
} catch (Exception e){
// No Code
}
try {
cam.setPreviewDisplay(hldr);
cam.setPreviewCallback(pcb);
cam.startPreview();
cam.autoFocus(afcb);
} catch (Exception e) {
// No Code
}
}
}
Is there any idea how can I solve this problem?
I found the problem. It seems the SurfaceView that is made in program destroys on activity stop. So I replaced it with a SurfaceView in my layout.
package com.example.campreview;
import com.example.campreview.R;
import java.io.IOException;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
public class ScanActivity extends Activity implements OnClickListener {
private SurfaceView PreviewSfc;
private Camera cam = null;
private Handler atfcs;
private boolean hascam = false;
private boolean validdisplay = false;
private boolean prvng = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
PreviewSfc = (SurfaceView)findViewById(R.id.PreviewSfc);
PreviewSfc.getHolder().addCallback(SurfaceCB);
//PreviewSfc.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
StartCamera();
if (cam != null) {
hascam = true;
atfcs = new Handler();
}
}
#Override
public void onPause() {
ReleaseCamera();
super.onPause();
}
#Override
public void onResume() {
super.onResume();
StartPreview();
}
private boolean StartCamera() {
boolean r = true;
if (cam == null) {
try {
cam = Camera.open();
} catch (Exception e) {
cam = null;
r = false;
}
if (cam != null) {
try {
Camera.Parameters p = cam.getParameters();
if (p.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO))
p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
if (p.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_OFF))
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
if (p.getSupportedPreviewFormats().contains(ImageFormat.NV21))
p.setPreviewFormat(ImageFormat.NV21);
Camera.Size s = null;
int a = 0, b;
for (Camera.Size z : p.getSupportedPreviewSizes()) {
b = z.width * z.height;
if (Math.abs(b - 307200) < Math.abs(a - 307200)) { //640x480 is the best
s = z;
a = b;
}
}
if (a != 0) p.setPreviewSize(s.width, s.height);
cam.setParameters(p);
cam.setDisplayOrientation(90);
if (validdisplay) cam.setPreviewDisplay(PreviewSfc.getHolder());
} catch (Exception e) {
r = false;
cam.release();
cam = null;
}
}
}
//if (!r) Error message that failed to start camera
return r;
}
private void ReleaseCamera() {
if (cam != null) {
StopPreview();
cam.release();
cam = null;
}
}
public void StartPreview() {
if ((!prvng) & (hascam) & (validdisplay)) {
if (StartCamera()) {
cam.setPreviewCallback(PreviewCB);
cam.startPreview();
cam.autoFocus(AutoFocusCB);
prvng = true;
}
}
}
public void StopPreview() {
if (prvng) {
cam.stopPreview();
cam.setPreviewCallback(null);
prvng = false;
}
}
private Runnable DoAutoFocus = new Runnable() {
public void run() {
if (prvng) cam.autoFocus(AutoFocusCB);
}
};
AutoFocusCallback AutoFocusCB = new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
atfcs.postDelayed(DoAutoFocus, 1000);
}
};
PreviewCallback PreviewCB = new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
//
}
};
SurfaceHolder.Callback SurfaceCB = new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
if (cam != null) {
try {
cam.setPreviewDisplay(holder);
} catch (IOException e) {
// No Code
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
validdisplay = true;
StartPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
validdisplay = false;
}
};
}
I'm currently trying to create a very simple video recorder on Android without using intent, just a custom app. My code snippet is following
import java.io.IOException;
import android.app.Activity;
import android.media.MediaRecorder;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraActivity extends Activity implements SurfaceHolder.Callback {
public enum State {
UNKNOWN, CONNECTED, NOT_CONNECTED
}
SurfaceView cameraView;
SurfaceHolder holder;
public boolean mListening;
public Object mState;
public NetworkInfo mNetworkInfo;
public boolean mSending;
boolean recording = false;
public static final String TAG = "VIDEOCAPTURE";
private MediaRecorder recorder;
protected void captureVideo() {
if (recording) {
recorder.stop();
// recorder.release();
recording = false;
Log.v(TAG, "Recording Stopped");
// Let's initRecorder so we can record again
initRecorder();
prepareRecorder();
} else {
recording = true;
recorder.start();
Log.v(TAG, "Recording Started");
}
}
private void initRecorder() {
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
recorder.setOutputFile("/sdcard/videocapture_example.mp4");
recorder.setMaxDuration(50000); // 50 seconds
recorder.setMaxFileSize(5000000);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
recorder = new MediaRecorder();
initRecorder();
setContentView(R.layout.main);
cameraView = (SurfaceView) this.findViewById(R.id.CameraView);
holder = cameraView.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(this);
}
private void prepareRecorder() {
recorder.setPreviewDisplay(holder.getSurface());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
finish();
} catch (IOException e) {
e.printStackTrace();
finish();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v(TAG, "surfaceCreated");
prepareRecorder();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// camera.stopPreview();
// camera.release();
Log.v(TAG, "surfaceDestroyed");
if (recording) {
recorder.stop();
recording = false;
}
recorder.release();
finish();
}
}
But when i deployed this code within emulator, in the LogCat i got some errors like this.
java.lang.RuntimeException: Unable to start activity ComponentInfo...
java.lang.RuntimeException: setMaxDuration failed.
at android.media.MediaRecorder.setMaxDuration(Native Method)
What wrong with my code?
Quote from http://developer.android.com/reference/android/media/MediaRecorder.html:
"Note: Currently, MediaRecorder does not work on the emulator."