Reputation: 110
I want to make an app that record video, it seems like vine, hold to record, release it stop, hold to record and keep that to the end.
I have used MediaRecorder, but it just record once a time, if I start record again, app is crashed.
Please tell me there is any way to do this? I edited my code:
public class VideoRecordingActivity extends AppCompatActivity implements View.OnTouchListener, View.OnLongClickListener {
private Context myContext;
private boolean hasCamera;
private boolean onRecording;
private Camera mCamera;
private CameraPreview mPreview;
private MediaRecorder mediaRecorder;
private boolean cameraFront = false;
private int cameraId;
private int videoNumer;
private boolean isActionDown = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_introduction_recording);
initUI();
initialize();
}
private LinearLayout lnCameraPreview;
private ImageButton btn_recording;
private void initUI() {
lnCameraPreview = (LinearLayout) findViewById(R.id.ln_body_recording);
btn_recording = (ImageButton) findViewById(R.id.btn_recording);
}
public void initialize() {
myContext = this;
mPreview = new CameraPreview(this, cameraId, mCamera);
lnCameraPreview.addView(mPreview);
btn_recording.setOnLongClickListener(this);
btn_recording.setOnTouchListener(this);
videoNumer = 0;
}
public boolean onLongClick(View v) {
isActionDown = true;
try {
boolean isPrepared = false;
if (isActionDown)
isPrepared = prepareMediaRecorder();
if (isPrepared && isActionDown) {
// work on UiThread for better performance
runOnUiThread(new Runnable() {
public void run() {
mediaRecorder.start();
onRecording = true;
}
});
}
} catch (Exception e) {
e.printStackTrace();
Log.e("onLongPress Error ", e.toString());
}
return true;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
isActionDown = false;
try {
if (onRecording) {
if (mediaRecorder != null) {
mediaRecorder.stop();
}
onRecording = false;
videoNumer++;
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
break;
}
return false;
}
public void onResume() {
super.onResume();
if (!hasCamera(myContext)) {
Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG).show();
return;
}
initCamera();
}
@Override
protected void onPause() {
super.onPause();
// when on Pause, release camera in order to be used from other
// applications
releaseCamera();
}
private final int cMaxRecordDurationInMs = 30000;
private final long cMaxFileSizeInBytes = 5000000;
private final int cFrameRate = 20;
private File prRecordedFile;
@SuppressLint("SdCardPath")
private boolean prepareMediaRecorder() {
mediaRecorder = new MediaRecorder();
try {
mCamera.unlock();
} catch (Exception ex) {
return false;
}
// adjust the camera the way you need
mediaRecorder.setCamera(mCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
//
CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
mediaRecorder.setProfile(cpHigh);
mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
mediaRecorder.setOutputFile("/sdcard/" + videoNumer + "videocapture_example.mp4");
//set max size
mediaRecorder.setMaxDuration(600000); // Set max duration 60 sec.
mediaRecorder.setMaxFileSize(50000000); // Set max file size 50M
try {
mediaRecorder.prepare();
} catch (Exception e) {
releaseMediaRecorder();
e.printStackTrace();
}
return true;
}
private void releaseMediaRecorder() {
if (mediaRecorder != null) {
mediaRecorder.reset(); // clear recorder configuration
mediaRecorder.release(); // release the recorder object
mediaRecorder = null;
if (mCamera != null) {
mCamera.lock(); // lock camera for later use
}
}
}
/**
* Camera
*/
private void initCamera() {
if (mCamera == null) {
// if the front facing camera does not exist
if (findFrontFacingCamera() < 0) {
Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
}
mCamera = Camera.open(findBackFacingCamera());
mPreview.refreshCamera(mCamera);
}
onRecording = false;
}
private boolean hasCamera(Context context) {
// check if the device has camera
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
hasCamera = true;
} else {
hasCamera = false;
}
return hasCamera;
}
private int findFrontFacingCamera() {
int cameraId = -1;
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
cameraFront = true;
break;
}
}
this.cameraId = cameraId;
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1;
// Search for the back facing camera
// get the number of cameras
int numberOfCameras = Camera.getNumberOfCameras();
// for every camera check
for (int i = 0; i < numberOfCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
cameraFront = false;
break;
}
}
this.cameraId = cameraId;
return cameraId;
}
public void switchCamera() {
// if the camera preview is the front
if (cameraFront) {
int cameraId = findBackFacingCamera();
if (cameraId >= 0) {
// open the backFacingCamera
mCamera = Camera.open(cameraId);
// refresh the preview
mPreview.refreshCamera(mCamera);
}
} else {
int cameraId = findFrontFacingCamera();
if (cameraId >= 0) {
// open the backFacingCamera
mCamera = Camera.open(cameraId);
// refresh the preview
mPreview.refreshCamera(mCamera);
}
}
}
private void releaseCamera() {
// stop and release camera
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
}
Upvotes: 4
Views: 5686
Reputation: 110
This is my code.
public class VideoRecordingActivity extends AppCompatActivity implements View.OnClickListener, SurfaceHolder.Callback {
MediaRecorder recorder;
SurfaceHolder holder;
boolean recording = false;
private boolean isPrepared = false;
int videoNumber = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
super.onCreate(savedInstanceState);
recorder = new MediaRecorder();
initRecorder();
setContentView(R.layout.activity_video_introduction_recording);
SurfaceView cameraView = (SurfaceView) findViewById(R.id.ln_body_recording);
holder = cameraView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
cameraView.setClickable(true);
cameraView.setOnClickListener(this);
}
private void initRecorder() {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "CameraSample");
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile cpHigh = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
//CGlobal.VIDEO_RECORD_PATH = CGlobal.VIDEO_HOME_PATH + "VID_" + timeStamp;
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
recorder.setOutputFile(mediaFile+".mp4");
recorder.setMaxDuration(50000); // 50 seconds
recorder.setMaxFileSize(5000000); // Approximately 5 megabytes
}
private void prepareRecorder() {
recorder.setPreviewDisplay(holder.getSurface());
try {
recorder.prepare();
isPrepared = true;
} catch (IllegalStateException e) {
e.printStackTrace();
finish();
} catch (IOException e) {
e.printStackTrace();
finish();
}
}
public void onClick(View v) {
if (recording) {
recorder.stop();
recording = false;
isPrepared = false;
videoNumber++;
// Let's initRecorder so we can record again
} else {
if (!isPrepared){
initRecorder();
prepareRecorder();
}
recording = true;
recorder.start();
}
}
public void surfaceCreated(SurfaceHolder holder) {
prepareRecorder();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (recording) {
recorder.stop();
recording = false;
}
recorder.release();
finish();
}
}
Upvotes: 1
Reputation: 696
You can do achieve this functionality by setting OnLongClickListener() and OnTouchListener() on your record button. Like this:
recordBtn.setOnLongClickListener(recordBtnLCListener);
recordBtn.setOnTouchListener(recordBtnTouchListener);
then :
@Override
public boolean onLongClick(View v) {
ivCancel.setVisibility(View.GONE);
ivDone.setVisibility(View.GONE);
isActionDown = true;
try {
if (isActionDown) {
initRecorder();
if (isActionDown)
prepareRecorder();
}
if (isPrepared && isActionDown) {
mMediaRecorder.start();
isRecording = true;
}
} catch (Exception e) {
e.printStackTrace();
Log.e("onLongPress Error ", e.toString());
}
return true;
}
and :
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
isActionDown = false;
try {
if (isRecording) {
if (mMediaRecorder != null) {
mMediaRecorder.stop();
}
isRecording = false;
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
break;
}
return false;
}
So, in this way you can record the parts of video.Means each time you LongPress your record button, the recording starts. And time you release the button, the recording stops and here you have to save this part of video in any temporary folder. Once you done taking all parts of videos as many as you want, then you have to combine all that parts of videos to make a single video.
Here, is the code to merge all that video parts saved in temperory folder:
public void mergeVideos() {
try {
List<Movie> inMovies = new ArrayList<>();
for (int i = 0; i < videosPathList.size(); i++) {
String filePath = videosPathList.get(i);
try {
Movie movie = MovieCreator.build(filePath);
if (movie != null)
inMovies.add(movie);
} catch (Exception e) {
e.printStackTrace();
}
}
List<Track> videoTracks = new LinkedList<Track>();
List<Track> audioTracks = new LinkedList<Track>();
for (Movie m : inMovies) {
for (Track t : m.getTracks()) {
try {
if (t.getHandler().equals("soun")) {
audioTracks.add(t);
}
if (t.getHandler().equals("vide")) {
videoTracks.add(t);
}
} catch (Exception e) {
}
}
}
Movie result = new Movie();
if (audioTracks.size() > 0) {
result.addTrack(new AppendTrack(audioTracks
.toArray(new Track[audioTracks.size()])));
}
if (videoTracks.size() > 0) {
result.addTrack(new AppendTrack(videoTracks
.toArray(new Track[videoTracks.size()])));
}
BasicContainer out = (BasicContainer) new DefaultMp4Builder().build(result);
File f = null;
String finalVideoPath;
try {
f = setUpVideoFile(Environment
.getExternalStorageDirectory()+"/MyApp/videos/");
finalVideoPath = f.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
f = null;
finalVideoPath = null;
}
WritableByteChannel fc = new RandomAccessFile(finalVideoPath, "rw").getChannel();
out.writeContainer(fc);
fc.close();
deleteFilesDir(); //In this method you have to delete all parts of video stored in temporary folder.
} catch (Exception e) {
e.printStackTrace();
progressDialog.dismiss();
finish();
}
}
File setUpVideoFile(String directory) throws IOException {
File videoFile = null;
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
File storageDir = new File(directory);
if (storageDir != null) {
if (!storageDir.mkdirs()) {
if (!storageDir.exists()) {
Log.d("CameraSample", "failed to create directory");
return null;
}
}
}
videoFile = File.createTempFile("video_"
+ System.currentTimeMillis() + "_",
.mp4, storageDir);
}
return videoFile;
}
You can call mergeVideos() method after stopping mediaRecorder.
Hope this code helps you. :)
For merging the videos you have to use the isoparser library. So you have to add following dependendy in your gradle file :
compile 'com.googlecode.mp4parser:isoparser:1.0.5.4'
Upvotes: 5