In my application I need to record a video from the device and simultaneously post it to server(for every 5 seconds). For this I am using Http service (I don't want use RTSP here). I am able to record and simultaneously post it.
But the file at server end is not able to play (even in VLC also). The size of the both files are same in bytes (server file and device file). For testing purpose to find out the problem is with server or my end, I have commented the server posting code and written data to another file in sdcard (simultaneously while recording for every 5 seconds) but that file also same size and not able to play in device or VLC.
package com.techgene.instantrecorder;
import java.io.File;
import java.io.IOException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.media.MediaRecorder.OnInfoListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
import android.widget.VideoView;
import com.techgene.instantrecorder.utility.Util;
public class SafeVideoRecorder extends Activity implements SurfaceHolder.Callback
{
public static final String EXTRA_USE_FRONT_FACING_CAMERA ="frontcamera";
private static final String ROOT_DIR = Environment.getExternalStorageDirectory().toString() + "/InstantRecorder";
private static final int DUAL_MODE = 1;
private static final int MONO_MODE = 2;
private int currentMode;
private static final String TAG = "VideoRecorder";
public static Boolean mRecording = false;
private Boolean mUseFrontFacingCamera = false, isFromCall = false;
private VideoView mVideoView = null;
private MediaRecorder mVideoRecorder = null;
private Camera mCamera;
private String uniqueOutFile;
private ProgressDialog progress;
private Button btnStop, btnStartRecord, btnDual, btnMono;
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_video_recorder);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mVideoView = (VideoView) this.findViewById(R.id.videoView);
btnStop = (Button) findViewById(R.id.btnStop);
btnStop.setVisibility(View.GONE);
btnStop.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
try
{
stopRecording();
if(progress != null && progress.isShowing())
progress.dismiss();
progress = ProgressDialog.show(SafeVideoRecorder.this, "", "Uploading...");
new Thread(new Runnable()
{
#Override
public void run()
{
// Util util = new Util();
// final int respCode = util.upLoad2Server(uniqueOutFile);
//
// if(currentMode == MONO_MODE)
// {
// File file = new File(uniqueOutFile);
// if(file.exists())
// file.delete();
// }
runOnUiThread(new Runnable()
{
#Override
public void run()
{
if(progress != null && progress.isShowing())
progress.dismiss();
// if(respCode == 200)
// {
// Toast.makeText(SafeVideoRecorder.this, "Successfully uploaded to server", Toast.LENGTH_SHORT).show();
// }
// else
// {
// Toast.makeText(SafeVideoRecorder.this, "Unable to upload server", Toast.LENGTH_SHORT).show();
// }
try {
configureCameraRecorder(mVideoView.getHolder());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
btnStop.setVisibility(View.GONE);
btnStartRecord.setVisibility(View.VISIBLE);
btnDual.setVisibility(View.GONE);
btnMono.setVisibility(View.GONE);
}
});
}
}).start();
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
});
btnStartRecord = (Button) findViewById(R.id.btnStartRecord);
btnStartRecord.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
btnDual.setVisibility(View.VISIBLE);
btnMono.setVisibility(View.VISIBLE);
btnStop.setVisibility(View.GONE);
btnStartRecord.setVisibility(View.GONE);
startRecord();
}
});
btnDual = (Button) findViewById(R.id.btnDual);
btnDual.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
currentMode = DUAL_MODE;
isFromCall = true;
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"+"9703033575"));
startActivityForResult(intent, 1010);
btnDual.setVisibility(View.GONE);
btnMono.setVisibility(View.GONE);
btnStartRecord.setVisibility(View.GONE);
btnStop.setVisibility(View.VISIBLE);
}
});
btnMono = (Button) findViewById(R.id.btnMono);
btnMono.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
currentMode = MONO_MODE;
btnDual.setVisibility(View.GONE);
btnMono.setVisibility(View.GONE);
btnStartRecord.setVisibility(View.GONE);
btnStop.setVisibility(View.VISIBLE);
}
});
//mUseFrontFacingCamera = getIntent().getExtras().getBoolean(EXTRA_USE_FRONT_FACING_CAMERA, false);
if(mUseFrontFacingCamera)
{
// If caller wants to use front facing camera, then make sure the device has one...
// Hard coded to only open front facing camera on Xoom (model MZ604)
// For more universal solution try:
// http://stackoverflow.com/questions/2779002/how-to-open-front-camera-on-android-platform
String deviceModel = android.os.Build.MODEL;
if (deviceModel.contains("MZ604"))
{
mUseFrontFacingCamera = true;
}
else
{
Toast.makeText(getApplicationContext(), "The App isn't designed to use this Android's front facing camera.\n " +
"The device model is : " + deviceModel, Toast.LENGTH_LONG).show();
mUseFrontFacingCamera = false;
}
}
final SurfaceHolder holder = mVideoView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#SuppressLint("NewApi") #Override
public void surfaceCreated(SurfaceHolder holder)
{
Log.e(TAG, "surfaceCreated()");
try
{
if(!isFromCall)
{
Log.e(TAG, "configureCameraRecorder");
configureCameraRecorder(holder);
startRecord();
}
else
{
Log.e(TAG, "configureCamera ONLY");
if (mCamera != null)
{
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if (mUseFrontFacingCamera)
{
//hard coded assuming 1 is the front facing camera
mCamera = Camera.open(1);
}
else
{
mCamera = Camera.open();
}
// Camera setup is based on the API Camera Preview demo
mCamera.setPreviewDisplay(holder);
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(640, 480);
mCamera.setParameters(parameters);
mCamera.startPreview();
mCamera.unlock();
mVideoRecorder.setCamera(mCamera);
mVideoRecorder.setPreviewDisplay(holder.getSurface());
}
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
private void startRecord()
{
try
{
File file = new File(ROOT_DIR);
if(!file.exists())
file.mkdir();
uniqueOutFile = ROOT_DIR + "/IR_" + System.currentTimeMillis() + ".mp4";
File outFile = new File(uniqueOutFile);
if (outFile.exists())
{
outFile.delete();
}
if(mVideoRecorder != null)
{
Log.e(TAG, "Recording started");
mVideoRecorder.setOutputFile(uniqueOutFile);
mVideoRecorder.prepare();
mVideoRecorder.start();
mRecording = true;
new Thread(new Runnable()
{
#Override
public void run()
{
Util util = new Util();
final int respCode = util.upLoad2Server(uniqueOutFile);
}
}).start();
}
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Log.v(TAG, "Width x Height = " + width + "x" + height);
}
private void stopRecording() throws Exception
{
Log.e(TAG, "stopRecording()");
mRecording = false;
if (mVideoRecorder != null)
{
mVideoRecorder.stop();
mVideoRecorder.release();
mVideoRecorder = null;
}
if (mCamera != null)
{
mCamera.reconnect();
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
#Override
protected void onDestroy()
{
try
{
stopRecording();
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
super.onDestroy();
}
#SuppressLint("NewApi")
private void configureCameraRecorder(SurfaceHolder holder) throws Exception
{
if (mVideoRecorder != null)
{
mVideoRecorder.stop();
mVideoRecorder.release();
mVideoRecorder = null;
}
if (mCamera != null)
{
mCamera.reconnect();
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
try
{
if (mUseFrontFacingCamera)
{
//hard coded assuming 1 is the front facing camera
mCamera = Camera.open(1);
}
else
{
mCamera = Camera.open();
}
// Camera setup is based on the API Camera Preview demo
mCamera.setPreviewDisplay(holder);
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(640, 480);
mCamera.setParameters(parameters);
mCamera.startPreview();
mCamera.unlock();
mVideoRecorder = new MediaRecorder();
mVideoRecorder.setCamera(mCamera);
mVideoRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mVideoRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mVideoRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// THREE_GPP
mVideoRecorder.setVideoSize(640, 480);// YouTube recommended size: 320x240, OpenGazer eye tracker: 640x480 YouTube HD: 1280x720
mVideoRecorder.setVideoFrameRate(20); //might be auto-determined due to lighting
mVideoRecorder.setVideoEncodingBitRate(3000000);// 3 megapixel, or the max of the camera
mVideoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP
int sdk = android.os.Build.VERSION.SDK_INT;
// Gingerbread and up can have wide band ie 16,000 hz recordings
// (Okay quality for human voice)
if (sdk >= 10)
{
mVideoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
mVideoRecorder.setAudioSamplingRate(16000);
}
else
{
// Other devices only have narrow band, ie 8,000 hz
// (Same quality as a phone call, not really good quality for any purpose.
// For human voice 8,000 hz means /f/ and /th/ are indistinguishable)
mVideoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
}
// mVideoRecorder.setMaxDuration(30000); // limit to 30 seconds
mVideoRecorder.setOnInfoListener(new OnInfoListener()
{
#Override
public void onInfo(MediaRecorder mr, int what, int extra)
{
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED)
{
try
{
Log.e(TAG, "MEDIA_RECORDER_INFO_MAX_DURATION_REACHED reached");
stopRecording();
if(progress != null && progress.isShowing())
progress.dismiss();
progress = ProgressDialog.show(SafeVideoRecorder.this, "", "Uploading...");
new Thread(new Runnable()
{
#Override
public void run()
{
Util util = new Util();
final int respCode = util.upLoad2Server(uniqueOutFile);
runOnUiThread(new Runnable()
{
#Override
public void run()
{
if(progress != null && progress.isShowing())
progress.dismiss();
if(respCode == 200)
{
Toast.makeText(SafeVideoRecorder.this, "Successfully uploaded to server", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(SafeVideoRecorder.this, "Unable to upload server", Toast.LENGTH_SHORT).show();
}
}
});
}
}).start();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
});
mVideoRecorder.setPreviewDisplay(holder.getSurface());
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
#Override
protected void onPause()
{
super.onPause();
if (mCamera != null)
{
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
Log.e(TAG, "onActivityResult()");
// if(requestCode == 1010 && resultCode == RESULT_OK)
// {
//
// }
isFromCall = true;
}
}
package com.techgene.instantrecorder.utility;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import android.util.Log;
import com.techgene.instantrecorder.Appconstants;
import com.techgene.instantrecorder.SafeVideoRecorder;
import com.techgene.instantrecorder.VideoRecorder;
public class Util
{
public int upLoad2Server(String sourceFileUri)
{
int serverResponseCode = 0;
// String upLoadServerUri = "http://113.193.181.52:90/test/videos/add-video1.php";
String upLoadServerUri = "http://113.193.181.52:90/test/videos/add-video1.php?name=sample&description=Sample video&lat="
+ Appconstants.DEVICE_LAT
+ "&lng="
+ Appconstants.DEVICE_LANG;
upLoadServerUri = upLoadServerUri.replace(" ", "%20");
Log.e("Util", "Url: "+upLoadServerUri);
HttpURLConnection conn = null;
DataOutputStream dos = null;
int bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
File sourceFile = new File(sourceFileUri);
if (!sourceFile.isFile())
{
Log.e("Util", "Source File Does not exist");
return 0;
}
try
{
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(upLoadServerUri);
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
// conn.setRequestProperty("Content-Type", "multipart/form-data;");
// conn.setRequestProperty("uploaded_file", fileName);
// FileOutputStream fos = new FileOutputStream("/mnt/sdcard/hi.mp4");
dos = new DataOutputStream(conn.getOutputStream());
// dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""+fileName);
bytesAvailable = fileInputStream.available();
buffer = new byte[maxBufferSize];
while (SafeVideoRecorder.mRecording || (!SafeVideoRecorder.mRecording && bytesAvailable > 0))
{
Log.e("Util", "available : " + bytesAvailable);
bufferSize = Math.min(bytesAvailable, maxBufferSize);
fileInputStream.read(buffer, 0, bufferSize);
dos.write(buffer, 0, bufferSize);
dos.flush();
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
while (bytesAvailable <= 0 && SafeVideoRecorder.mRecording)
{
Log.e("Util", "NOT available : " + bytesAvailable);
Thread.sleep(5000);
bytesAvailable = fileInputStream.available();
}
}
// Responses from the server (code and message)
serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn.getResponseMessage();
Log.i("Util", "Upload file to server, HTTP Response is : " + serverResponseMessage + ": " + serverResponseCode);
fileInputStream.close();
dos.flush();
dos.close();
}
catch (Exception e)
{
e.printStackTrace();
}
// this block will give the response of upload link
try
{
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null)
{
Log.i("Util", "RES Message: " + line);
}
rd.close();
}
catch (Exception ioex)
{
Log.e("Util", "error: " + ioex.getMessage(), ioex);
}
return serverResponseCode;
}
}
Related
I am trying to record from the microphone and I built a code by trying some code snippets else where but nothing happens:
Here is the code, can someone tell me how to get this working.I am new to android coding.
package com.example.helloworld;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import java.io.IOException;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.AudioFormat;
import android.media.AudioRecord;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import android.util.Log;
import java.io.*;
import android.os.Environment;
public class MainActivity extends Activity {
public static final int SAMPLING_RATE = 44100;
public static final int AUDIO_SOURCE = MediaRecorder.AudioSource.MIC;
public static final int CHANNEL_IN_CONFIG = AudioFormat.CHANNEL_IN_MONO;
public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
public static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLING_RATE, CHANNEL_IN_CONFIG, AUDIO_FORMAT);
public static final String AUDIO_RECORDING_FILE_NAME = "recording.raw";
private static final String LOGTAG = "MyActivity";
private volatile boolean mStop = true;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView text = new TextView(this);
text.setText("Hello World, Ranjan");
setContentView(text);
}
/*public void run()
{
TextView text = new TextView(this);
text.setText(" hello smart mute");
}*/
//#Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
Log.v(LOGTAG, "Starting recordingā¦");
byte audioData[] = new byte[BUFFER_SIZE];
AudioRecord recorder = new AudioRecord(AUDIO_SOURCE,
SAMPLING_RATE, CHANNEL_IN_CONFIG,
AUDIO_FORMAT, BUFFER_SIZE);
recorder.startRecording();
String filePath = Environment.getExternalStorageDirectory().getPath()
+ "/" + AUDIO_RECORDING_FILE_NAME;
BufferedOutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(filePath));
} catch (FileNotFoundException e) {
Log.e(LOGTAG, "File not found for recording ", e);
}
while (!mStop) {
int status = recorder.read(audioData, 0, audioData.length);
if (status == AudioRecord.ERROR_INVALID_OPERATION ||
status == AudioRecord.ERROR_BAD_VALUE) {
Log.e(LOGTAG, "Error reading audio data!");
return;
}
try {
os.write(audioData, 0, audioData.length);
} catch (IOException e) {
Log.e(LOGTAG, "Error saving recording ", e);
return;
}
}
try {
os.close();
recorder.stop();
recorder.release();
Log.v(LOGTAG, "Recording doneā¦");
mStop = false;
} catch (IOException e) {
Log.e(LOGTAG, "Error when releasing", e);
}
}
}
Add these to your manifest file
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Try the below code,it helps us to record,stop and play audio
public class MainActivity extends Activity {
Button play,stop,record;
private MediaRecorder myAudioRecorder;
private String outputFile = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play=(Button)findViewById(R.id.button3);
stop=(Button)findViewById(R.id.button2);
record=(Button)findViewById(R.id.button);
stop.setEnabled(false);
play.setEnabled(false);
outputFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/recording.3gp";;
myAudioRecorder=new MediaRecorder();
myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myAudioRecorder.setOutputFile(outputFile);
record.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
myAudioRecorder.prepare();
myAudioRecorder.start();
}
catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
record.setEnabled(false);
stop.setEnabled(true);
Toast.makeText(getApplicationContext(), "Recording started", Toast.LENGTH_LONG).show();
}
});
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myAudioRecorder.stop();
myAudioRecorder.release();
myAudioRecorder = null;
stop.setEnabled(false);
play.setEnabled(true);
Toast.makeText(getApplicationContext(), "Audio recorded successfully",Toast.LENGTH_LONG).show();
}
});
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) throws IllegalArgumentException,SecurityException,IllegalStateException {
MediaPlayer m = new MediaPlayer();
try {
m.setDataSource(outputFile);
}
catch (IOException e) {
e.printStackTrace();
}
try {
m.prepare();
}
catch (IOException e) {
e.printStackTrace();
}
m.start();
Toast.makeText(getApplicationContext(), "Playing audio", Toast.LENGTH_LONG).show();
}
});
}
I need to record video for 8 seconds in my app. I am using MediaStore.ACTION_VIDEO_CAPTURE intent for video recording and using these parameters (MediaStore.EXTRA_VIDEO_QUALITY,MediaStore.EXTRA_DURATION_LIMIT) to set quality and duration limit of video recording. but i encountered a very interesting bug i.e. when i set duration limit to 8 seconds and video quality to 1, its working fine and is recording video for 8 seconds but as soon i changes the video quality to 0 and keeping everything same, the video is now recorded for 21 seconds. I am using sony Xperia phone for testing, but when i shift to HTC, duration limit not working in any case neither on setting video quality to 1 nor on setting it to 0.
So i don't know what is happening right now. In severe need. please help. Thanks in advance.
Here is the code I am using..
private void recordVideo() {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
File f = null;
try {
f = setUpVideoFile();
filePath = f.getAbsolutePath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
} catch (IOException e) {
e.printStackTrace();
f = null;
filePath = null;
}
objectGlobal.setFilepath(filePath);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 8);
startActivityForResult(intent, CAMERA_CAPTURE_VIDEO);
}
I know its bit late to answer this question, but i think i have to, so that if others are facing this problem, they can easily deal with it.
Actually the problem is when you lower the video quality via this
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
the camera intent no longer works as a video recorder. It actually creates a mms when we try lowering the quality. As far as time is concerned, I don't know whether it is a bug in Android or may be some memory constraints. So the solution I adopted is to make custom video recording class using SurfaceView.
So I am pasting the code of Video Recording from one of my projects.Also the video recorded is almost playable in all android/iOS devices, i have tested so far. Here is my Video Recording Class
package com.mukesh.videorecordingsample;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class RecordVideoPostsActivity extends Activity implements
SurfaceHolder.Callback, OnClickListener {
protected static final int RESULT_ERROR = 0x00000001;
private static final int MAX_VIDEO_DURATION = 8 * 1000;
private static final int ID_TIME_COUNT = 0x1006;
private SurfaceView mSurfaceView;
private ImageView iv_cancel, iv_ok, iv_record;
private TextView tv_counter;
private SurfaceHolder mSurfaceHolder;
private MediaRecorder mMediaRecorder;
private Camera mCamera;
private List<Size> mSupportVideoSizes;
private String filePath;
private boolean mIsRecording = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_recordvideo);
initView();
}
private void initView() {
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
iv_record = (ImageView) findViewById(R.id.iv_record);
iv_cancel = (ImageView) findViewById(R.id.iv_cancel);
iv_ok = (ImageView) findViewById(R.id.iv_ok);
iv_record.setImageResource(R.drawable.btn_video_start);
tv_counter = (TextView) findViewById(R.id.timer);
tv_counter.setVisibility(View.GONE);
iv_cancel.setOnClickListener(this);
iv_ok.setOnClickListener(this);
iv_record.setOnClickListener(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
private void exit(final int resultCode, final Intent data) {
if (mIsRecording) {
new AlertDialog.Builder(RecordVideoPostsActivity.this)
.setTitle("Video Recorder")
.setMessage("Do you want to exit?")
.setPositiveButton("yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
stopRecord();
if (resultCode == RESULT_CANCELED) {
if (filePath != null)
deleteFile(new File(filePath));
}
setResult(resultCode, data);
finish();
}
})
.setNegativeButton("no",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
}
}).show();
return;
}
if (resultCode == RESULT_CANCELED) {
if (filePath != null)
deleteFile(new File(filePath));
}
setResult(resultCode, data);
finish();
}
private void deleteFile(File delFile) {
if (delFile == null) {
return;
}
final File file = new File(delFile.getAbsolutePath());
delFile = null;
new Thread() {
#Override
public void run() {
super.run();
if (file.exists()) {
file.delete();
}
}
}.start();
}
private Handler mHandler = new Handler() {
#Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ID_TIME_COUNT:
if (mIsRecording) {
if (msg.arg1 > msg.arg2) {
// mTvTimeCount.setVisibility(View.INVISIBLE);
tv_counter.setText("00:00");
stopRecord();
} else {
tv_counter.setText("00:0" + (msg.arg2 - msg.arg1));
Message msg2 = mHandler.obtainMessage(ID_TIME_COUNT,
msg.arg1 + 1, msg.arg2);
mHandler.sendMessageDelayed(msg2, 1000);
}
}
break;
default:
break;
}
}
;
};
private void openCamera() {
try {
this.mCamera = Camera.open();
Camera.Parameters parameters = mCamera.getParameters();
parameters.setRotation(90);
System.out.println(parameters.flatten());
parameters.set("orientation", "portrait");
mCamera.setParameters(parameters);
mCamera.lock();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
try {
mCamera.setDisplayOrientation(90);
} catch (NoSuchMethodError e) {
e.printStackTrace();
}
}
mSupportVideoSizes = parameters.getSupportedVideoSizes();
if (mSupportVideoSizes == null || mSupportVideoSizes.isEmpty()) {
String videoSize = parameters.get("video-size");
Log.i(EmBazaarConstants.APP_NAME, videoSize);
mSupportVideoSizes = new ArrayList<Camera.Size>();
if (!RecordVideoPostsActivity.isEmpty(videoSize)) {
String[] size = videoSize.split("x");
if (size.length > 1) {
try {
int width = Integer.parseInt(size[0]);
int height = Integer.parseInt(size[1]);
mSupportVideoSizes.add(mCamera.new Size(width,
height));
} catch (Exception e) {
Log.e(EmBazaarConstants.APP_NAME, e.toString());
}
}
}
}
for (Size size : mSupportVideoSizes) {
Log.i(EmBazaarConstants.APP_NAME, size.width + "<>" + size.height);
}
} catch (Exception e) {
Log.e(EmBazaarConstants.APP_NAME, "Open Camera error\n" + e.toString());
}
}
private boolean initVideoRecorder() {
if (mCamera == null) {
mCamera = Camera.open();
mCamera.unlock();
} else {
mCamera.unlock();
}
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
try {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
} catch (Exception e) {
e.printStackTrace();
}
try {
CamcorderProfile lowProfile = CamcorderProfile
.get(CamcorderProfile.QUALITY_LOW);
CamcorderProfile hightProfile = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
if (lowProfile != null && hightProfile != null) {
lowProfile.audioCodec = MediaRecorder.AudioEncoder.AAC;
lowProfile.duration = hightProfile.duration;
lowProfile.videoCodec = MediaRecorder.VideoEncoder.H264;
lowProfile.videoFrameRate = hightProfile.videoFrameRate;
lowProfile.videoBitRate = 1500000 > hightProfile.videoBitRate ? hightProfile.videoBitRate
: 1500000;
if (mSupportVideoSizes != null && !mSupportVideoSizes.isEmpty()) {
int width = 640;
int height = 480;
Collections.sort(mSupportVideoSizes, new SizeComparator());
int lwd = mSupportVideoSizes.get(0).width;
for (Size size : mSupportVideoSizes) {
int wd = Math.abs(size.width - 640);
if (wd < lwd) {
width = size.width;
height = size.height;
lwd = wd;
} else {
break;
}
}
lowProfile.videoFrameWidth = width;
lowProfile.videoFrameHeight = height;
}
mMediaRecorder.setProfile(lowProfile);
}
} catch (Exception e) {
try {
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
} catch (Exception ex) {
ex.printStackTrace();
}
try {
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
} catch (Exception ex) {
ex.printStackTrace();
}
if (mSupportVideoSizes != null && !mSupportVideoSizes.isEmpty()) {
Collections.sort(mSupportVideoSizes, new SizeComparator());
Size size = mSupportVideoSizes.get(0);
try {
mMediaRecorder.setVideoSize(size.width, size.height);
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
try {
mMediaRecorder.setVideoSize(640, 480);
} catch (Exception ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
}
File f = null;
try {
f = setUpVideoFile();
filePath = f.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
f = null;
filePath = null;
}
mMediaRecorder.setOutputFile(filePath);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
try {
mMediaRecorder.setOrientationHint(90);
} catch (NoSuchMethodError e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d("VideoPreview",
"IllegalStateException preparing MediaRecorder: "
+ e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d("VideoPreview",
"IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (Exception e) {
releaseMediaRecorder();
e.printStackTrace();
}
return true;
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
mCamera.lock();
}
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
private void startRecord() {
try {
if (initVideoRecorder()) {
mMediaRecorder.start();
iv_record.setImageResource(R.drawable.btn_video_stop);
} else {
releaseMediaRecorder();
iv_record.setImageResource(R.drawable.btn_video_start);
}
tv_counter.setVisibility(View.VISIBLE);
tv_counter.setText("00:0" + (MAX_VIDEO_DURATION / 1000));
Message msg = mHandler.obtainMessage(ID_TIME_COUNT, 1,
MAX_VIDEO_DURATION / 1000);
mHandler.sendMessage(msg);
mIsRecording = true;
} catch (Exception e) {
showShortToast("problem while capturing video");
e.printStackTrace();
exit(RESULT_ERROR, null);
}
}
private void stopRecord() {
try {
mMediaRecorder.stop();
} catch (Exception e) {
if (new File(filePath) != null
&& new File(filePath).exists()) {
new File(filePath).delete();
}
}
releaseMediaRecorder();
mCamera.lock();
iv_record.setImageResource(R.drawable.btn_video_start);
mIsRecording = false;
iv_record.setVisibility(View.GONE);
iv_cancel.setVisibility(View.VISIBLE);
iv_ok.setVisibility(View.VISIBLE);
}
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo(); // Since API level 9
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
#Override
protected void onResume() {
super.onResume();
openCamera();
}
#Override
protected void onPause() {
super.onPause();
releaseCamera();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (Exception e) {
}
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
try {
mCamera.stopPreview();
} catch (Exception e) {
}
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exit(RESULT_CANCELED, null);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.iv_ok:
Intent data = new Intent();
if (filePath != null) {
data.putExtra("videopath", filePath);
}
exit(RESULT_OK, data);
break;
case R.id.iv_cancel:
exit(RESULT_CANCELED, null);
break;
case R.id.iv_record:
if (mIsRecording) {
stopRecord();
} else {
startRecord();
}
break;
default:
break;
}
}
protected void showShortToast(String text) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
private File setUpVideoFile() throws IOException {
File videoFile = null;
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
File storageDir = new File(
EmBazaarConstants.LOCAL_STORAGE_BASE_PATH_FOR_POSTED_VIDEOS)
.getParentFile();
if (storageDir != null) {
if (!storageDir.mkdirs()) {
if (!storageDir.exists()) {
Log.d("CameraSample", "failed to create directory");
return null;
}
}
}
videoFile = File.createTempFile(EmBazaarConstants.MP4_FILE_PREFIX
+ System.currentTimeMillis() + "_",
EmBazaarConstants.MP4_FILE_SUFIX, storageDir);
} else {
Log.v(getString(R.string.app_name),
"External storage is not mounted READ/WRITE.");
}
return videoFile;
}
private class SizeComparator implements Comparator<Size> {
#Override
public int compare(Size lhs, Size rhs) {
return rhs.width - lhs.width;
}
}
public static boolean isEmpty(String str) {
return str == null || "".equals(str.trim());
}
}
and you can simply call this class in your Activity like this
if (isDeviceSupportCamera()) {
startActivityForResult(new Intent(PostStatusActivity.this,
yourActivity.class),
EmBazaarConstants.CAMERA_CAPTURE_VIDEO);
} else {
Toast.makeText(this, "Your device doesn't support camera",
Toast.LENGTH_LONG).show();
}
and here is isDeviceSupportCamera() function
private boolean isDeviceSupportCamera() {
if (getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
In your onActivityResult, you have to write this code
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == EmBazaarConstants.CAMERA_CAPTURE_VIDEO
&& resultCode == RESULT_OK) {
if (data != null && data.getStringExtra("videopath") != null)
videoFilePath= data.getStringExtra("videopath");
}
}
Hope this helps.
** Although we have new Camera2 APIs in android lollipop, but this code still works in android lollipop as well.But still you can change to new Camera2 APIs,if you want.
I am trying to make a video player in android.
It plays the 3GP format videos.
But it does not support the mp4 video.Below is my code in android for the same.Why does it not support the mp4 format on the device and emulator?
package com.example.videoplayer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.URLUtil;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import android.widget.VideoView;
public class VideoViewDemo extends Activity {
private static final String TAG = "VideoViewDemo";
private VideoView mVideoView;
private EditText mPath;
private ImageButton mPlay;
private ImageButton mPause;
private ImageButton mReset;
private ImageButton mStop;
private String current;
#SuppressLint({ "NewApi", "NewApi", "NewApi" })
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
mVideoView = (VideoView) findViewById(R.id.surface_view);
mPath = (EditText) findViewById(R.id.path);
mPath.setText("ooklnet.com/files/368/368007/video.mp4");
mPlay = (ImageButton) findViewById(R.id.play);
mPause = (ImageButton) findViewById(R.id.pause);
mReset = (ImageButton) findViewById(R.id.reset);
mStop = (ImageButton) findViewById(R.id.stop);
mPlay.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
playVideo();
}
});
mPause.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
if (mVideoView != null) {
mVideoView.pause();
}
}
});
mReset.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
if (mVideoView != null) {
mVideoView.seekTo(0);
}
}
});
mStop.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
if (mVideoView != null) {
current = null;
mVideoView.stopPlayback();
}
}
});
/*runOnUiThread(new Runnable(){
public void run() {
sleep(2000);
playVideo();
}
});*/
Thread _trd1 = new Thread() {
public void run() {
try {
sleep(2000);
runOnUiThread(new Runnable() {
public void run() {
playVideo();
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
_trd1.start();
// new DoBackgroundTask().execute();
}
public class DoBackgroundTask extends AsyncTask
<String, Void, String> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
}
protected String doInBackground(String... locationNames) {
playVideo();
return null;
}
protected void onPostExecute(String addresses){
}
}
private void playVideo() {
try {
final String path = mPath.getText().toString();
Log.v(TAG, "path: " + path);
if (path == null || path.length() == 0) {
Toast.makeText(VideoViewDemo.this, "File URL/path is empty",
Toast.LENGTH_LONG).show();
} else {
// If the path has not changed, just start the media player
if (path.equals(current) && mVideoView != null) {
mVideoView.start();
mVideoView.requestFocus();
return;
}
current = path;
mVideoView.setVideoPath(getDataSource("ooklnet.com/files/368/368007/video.mp4"));
mVideoView.start();
mVideoView.requestFocus();
}
} catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e);
if (mVideoView != null) {
mVideoView.stopPlayback();
}
}
}
private String getDataSource(String path) throws IOException {
if (!URLUtil.isNetworkUrl(path)) {
return path;
} else {
URL url = new URL(path);
URLConnection cn = url.openConnection();
cn.connect();
InputStream stream = cn.getInputStream();
if (stream == null)
throw new RuntimeException("stream is null");
File temp = File.createTempFile("mediaplayertmp", "dat");
temp.deleteOnExit();
String tempPath = temp.getAbsolutePath();
FileOutputStream out = new FileOutputStream(temp);
byte buf[] = new byte[128];
do {
int numread = stream.read(buf);
if (numread <= 0)
break;
out.write(buf, 0, numread);
} while (true);
try {
stream.close();
} catch (IOException ex) {
Log.e(TAG, "error: " + ex.getMessage(), ex);
}
return tempPath;
}
}
}
Please advise as soon as possible.
Thanks.
The problem might be with the video encoding. Android Froyo and Gingerbread doesn't support H264 formats other than "Baseline" H264. So if your video is Mp4 & H264 encoded make sure its "AVC baseline" encoded. Use some tools like "Media info" in windows/Linux and check your video encoding. Convert the video to Baseline if possible.
An alternative workaround is to skip the Videoview and use a video play intent and redirect the playback to an app. User will be prompted to pick a player to handle the playback. Obviously if the video view cant play the file, the default player also wont be able to handle the file. you can choose some other installed player like Mx-Player which will stream the file perfectly.
Hope that solved your issue.
Try correct video url with protocol: http://www.ooklnet.com/files/368/368007/video.mp4
well, I am trying to develop an app that films with the front facing camera.
and i am having a wierd bug. the preview looks fine, but the output video comes out with a green line in low resolutions and broken with green lines in high resolutions
this is the code:
package feipeng.yacamcorder;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.media.MediaRecorder.AudioEncoder;
import android.media.MediaRecorder.VideoEncoder;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
/***
* TODO: 1. sound on/off 2. resolution change
*
* #author roman10
*
*/
public class Main extends Activity implements SurfaceHolder.Callback {
private SurfaceView prSurfaceView;
private Button prStartBtn;
private Button prSettingsBtn;
private boolean prRecordInProcess;
private SurfaceHolder prSurfaceHolder;
private Camera prCamera;
private final String cVideoFilePath = "/sdcard/r10videocam/";
private Context prContext;
private MediaRecorder prMediaRecorder;
private CamcorderProfile mProfile;
private final int cMaxRecordDurationInMs = 30000;
private final long cMaxFileSizeInBytes = 5000000;
private final int cFrameRate = 20;
private File prRecordedFile;
private static final int REQUEST_DECODING_OPTIONS = 0;
private static final String TAG = "aaa";
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
switch (requestCode) {
case REQUEST_DECODING_OPTIONS:
if (resultCode == RESULT_OK) {
updateEncodingOptions();
}
break;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
prContext = this.getApplicationContext();
setContentView(R.layout.main);
Utils.createDirIfNotExist(cVideoFilePath);
prSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
prStartBtn = (Button) findViewById(R.id.main_btn1);
prSettingsBtn = (Button) findViewById(R.id.main_btn2);
prRecordInProcess = false;
prStartBtn.setOnClickListener(new View.OnClickListener() {
// #Override
#Override
public void onClick(View v) {
if (prRecordInProcess == false) {
startRecording();
} else {
stopRecording();
}
}
});
prSettingsBtn.setOnClickListener(new View.OnClickListener() {
// #Override
#Override
public void onClick(View v) {
Intent lIntent = new Intent();
lIntent.setClass(prContext,
feipeng.yacamcorder.SettingsDialog.class);
startActivityForResult(lIntent, REQUEST_DECODING_OPTIONS);
}
});
prSurfaceHolder = prSurfaceView.getHolder();
prSurfaceHolder.addCallback(this);
prSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
prMediaRecorder = new MediaRecorder();
}
private Camera openFrontFacingCamera() {
Camera camera = null;
// Look for front-facing camera, using the Gingerbread API.
// Java reflection is used for backwards compatibility with
// pre-Gingerbread APIs.
try {
Class<?> cameraClass = Class.forName("android.hardware.Camera");
Object cameraInfo = null;
Field field = null;
int cameraCount = 0;
Method getNumberOfCamerasMethod = cameraClass
.getMethod("getNumberOfCameras");
if (getNumberOfCamerasMethod != null) {
cameraCount = (Integer) getNumberOfCamerasMethod.invoke(null,
(Object[]) null);
}
Class<?> cameraInfoClass = Class
.forName("android.hardware.Camera$CameraInfo");
if (cameraInfoClass != null) {
cameraInfo = cameraInfoClass.newInstance();
}
if (cameraInfo != null) {
field = cameraInfo.getClass().getField("facing");
}
Method getCameraInfoMethod = cameraClass.getMethod("getCameraInfo",
Integer.TYPE, cameraInfoClass);
if (getCameraInfoMethod != null && cameraInfoClass != null
&& field != null) {
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
getCameraInfoMethod.invoke(null, camIdx, cameraInfo);
int facing = field.getInt(cameraInfo);
if (facing == 1) { // Camera.CameraInfo.CAMERA_FACING_FRONT
try {
Method cameraOpenMethod = cameraClass.getMethod(
"open", Integer.TYPE);
if (cameraOpenMethod != null) {
camera = (Camera) cameraOpenMethod.invoke(null,
camIdx);
mProfile = CamcorderProfile
.get(CamcorderProfile.QUALITY_LOW);
}
} catch (RuntimeException e) {
Log.e(TAG,
"Camera failed to open: "
+ e.getLocalizedMessage());
}
}
}
}
}
// Ignore the bevy of checked exceptions the Java Reflection API throws
// - if it fails, who cares.
catch (ClassNotFoundException e) {
Log.e(TAG, "ClassNotFoundException" + e.getLocalizedMessage());
} catch (NoSuchMethodException e) {
Log.e(TAG, "NoSuchMethodException" + e.getLocalizedMessage());
} catch (NoSuchFieldException e) {
Log.e(TAG, "NoSuchFieldException" + e.getLocalizedMessage());
} catch (IllegalAccessException e) {
Log.e(TAG, "IllegalAccessException" + e.getLocalizedMessage());
} catch (InvocationTargetException e) {
Log.e(TAG, "InvocationTargetException" + e.getLocalizedMessage());
} catch (InstantiationException e) {
Log.e(TAG, "InstantiationException" + e.getLocalizedMessage());
} catch (SecurityException e) {
Log.e(TAG, "SecurityException" + e.getLocalizedMessage());
}
if (camera == null) {
// Try using the pre-Gingerbread APIs to open the camera.
try {
camera = Camera.open();
} catch (RuntimeException e) {
Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
}
}
return camera;
}
private boolean startRecording() {
prCamera.stopPreview();
try {
prCamera.unlock();
prMediaRecorder.setCamera(prCamera);
// set audio source as Microphone, video source as camera
// state: Initial=>Initialized
prMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
prMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// set the file output format: 3gp or mp4
// state: Initialized=>DataSourceConfigured
String lVideoFileFullPath;
String lDisplayMsg = "Current container format: ";
if (Utils.puContainerFormat == SettingsDialog.cpu3GP) {
lDisplayMsg += "3GP\n";
lVideoFileFullPath = ".3gp";
prMediaRecorder
.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
} else if (Utils.puContainerFormat == SettingsDialog.cpuMP4) {
lDisplayMsg += "MP4\n";
lVideoFileFullPath = ".mp4";
prMediaRecorder
.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
} else {
lDisplayMsg += "3GP\n";
lVideoFileFullPath = ".3gp";
prMediaRecorder
.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
}
// the encoders:
// audio: AMR-NB
prMediaRecorder.setAudioEncoder(AudioEncoder.AMR_NB);
// video: H.263, MP4-SP, or H.264
// prMediaRecorder.setVideoEncoder(VideoEncoder.H263);
// prMediaRecorder.setVideoEncoder(VideoEncoder.MPEG_4_SP);
lDisplayMsg += "Current encoding format: ";
if (Utils.puEncodingFormat == SettingsDialog.cpuH263) {
lDisplayMsg += "H263\n";
prMediaRecorder.setVideoEncoder(VideoEncoder.H263);
} else if (Utils.puEncodingFormat == SettingsDialog.cpuMP4_SP) {
lDisplayMsg += "MPEG4-SP\n";
prMediaRecorder.setVideoEncoder(VideoEncoder.MPEG_4_SP);
} else if (Utils.puEncodingFormat == SettingsDialog.cpuH264) {
lDisplayMsg += "H264\n";
prMediaRecorder.setVideoEncoder(VideoEncoder.H264);
} else {
lDisplayMsg += "H263\n";
prMediaRecorder.setVideoEncoder(VideoEncoder.H263);
}
lVideoFileFullPath = cVideoFilePath
+ String.valueOf(System.currentTimeMillis())
+ lVideoFileFullPath;
prRecordedFile = new File(lVideoFileFullPath);
prMediaRecorder.setOutputFile(prRecordedFile.getPath());
if (Utils.puResolutionChoice == SettingsDialog.cpuRes176) {
prMediaRecorder.setVideoSize(176, 144);
} else if (Utils.puResolutionChoice == SettingsDialog.cpuRes320) {
prMediaRecorder.setVideoSize(320, 240);
} else if (Utils.puResolutionChoice == SettingsDialog.cpuRes720) {
prMediaRecorder.setVideoSize(720, 480);
}
Toast.makeText(prContext, lDisplayMsg, Toast.LENGTH_LONG).show();
prMediaRecorder.setVideoFrameRate(cFrameRate);
prMediaRecorder.setPreviewDisplay(prSurfaceHolder.getSurface());
prMediaRecorder.setMaxDuration(cMaxRecordDurationInMs);
prMediaRecorder.setMaxFileSize(cMaxFileSizeInBytes);
// prepare for capturing
// state: DataSourceConfigured => prepared
prMediaRecorder.prepare();
// start recording
// state: prepared => recording
prMediaRecorder.start();
prStartBtn.setText("Stop");
prRecordInProcess = true;
return true;
} catch (IOException _le) {
_le.printStackTrace();
return false;
}
}
private void stopRecording() {
prMediaRecorder.stop();
prMediaRecorder.reset();
try {
prCamera.reconnect();
} catch (IOException e) {
e.printStackTrace();
}
prStartBtn.setText("Start");
prRecordInProcess = false;
prCamera.startPreview();
}
// #Override
#Override
public void surfaceChanged(SurfaceHolder _holder, int _format, int _width,
int _height) {
Camera.Parameters lParam = prCamera.getParameters();
// //lParam.setPreviewSize(_width, _height);
// //lParam.setPreviewSize(320, 240);
// lParam.setPreviewFormat(PixelFormat.JPEG);
prCamera.setParameters(lParam);
try {
prCamera.setPreviewDisplay(_holder);
prCamera.startPreview();
// prPreviewRunning = true;
} catch (IOException _le) {
_le.printStackTrace();
}
}
// #Override
#Override
public void surfaceCreated(SurfaceHolder arg0) {
prCamera = openFrontFacingCamera();
if (prCamera == null) {
Toast.makeText(this.getApplicationContext(),
"Camera is not available!", Toast.LENGTH_SHORT).show();
finish();
}
}
// #Override
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
if (prRecordInProcess) {
stopRecording();
} else {
prCamera.stopPreview();
}
prMediaRecorder.release();
prMediaRecorder = null;
prCamera.release();
prCamera = null;
}
private void updateEncodingOptions() {
if (prRecordInProcess) {
stopRecording();
startRecording();
Toast.makeText(prContext, "Recording restarted with new options!",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(prContext, "Recording options updated!",
Toast.LENGTH_SHORT).show();
}
}
}
p.s.
using galaxy s1.
any ideas?
I tried your code on Samsung Nexus S running on 4.0.4 and it works well.
The MediaRecorder was set as follows:
private boolean startRecording() {
...
prMediaRecorder.setCamera(prCamera);
prMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
prMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
prMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
prMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
prMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
prMediaRecorder.setOutputFile("/sdcard/video.mp4");
prMediaRecorder.setVideoSize(320, 240);//If higher produces error -19
prMediaRecorder.setVideoFrameRate(15);//If higher produces error -19
prMediaRecorder.setPreviewDisplay(prSurfaceHolder.getSurface());
prMediaRecorder.setMaxDuration(cMaxRecordDurationInMs);
prMediaRecorder.setMaxFileSize(cMaxFileSizeInBytes);
prMediaRecorder.prepare();
prMediaRecorder.start();
...
}//endOfStartRecording()
For a 10 sec recording it produces a .mp4 file of ~300 KB size. The quality is not really great but it is the highest I could get. Have in mind that the front facing camera is not as powerful as the back one.
if anyone has any idea that how to switch between front and back camera when using MediaRecorder . I defing a button for this function, but have no idea how to define the onclickListener.
the total activity is the following:
import java.io.File;
import java.io.IOException;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Test_cameraActivity extends Activity implements Callback {
// Camera variables to fiddle with video preview.
// private Camera cam;
// Viewholders etc
private SurfaceHolder recordViewHolder;
private SurfaceView recordSurface;
private int width, height;
// Button
private Button recordBut;
private Button switchBut;
private Button libraryBut;
private final static String DIRECTORY = "/hdrecorder"; // Directory where
// the film is
// stored
private final static String recordFileName = "/hdtestfile.mp4";
private final static String saveFileName = "/hdsavefile.mp4";
private MyMediaRecorder recorder = null;
private final static String LOG_TAG = "HD Recorder";
private String filePath;
// Activity overrides
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// *******************************************
// fullscreen mode
// *******************************************
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// *******************************************
setContentView(R.layout.main);
File dir = new File(Environment.getExternalStorageDirectory()
+ DIRECTORY);
if (!dir.exists()) {
if (dir.mkdir()) {
Log.v(LOG_TAG, "Created directory");
} else {
Log.v(LOG_TAG, "Failed to create Directory");
}
}
File videoFile = new File(Environment.getExternalStorageDirectory()
+ DIRECTORY + recordFileName);
if (!videoFile.exists()) {
videoFile.delete(); // Reset recording
}
filePath = videoFile.getAbsolutePath();
Log.v(LOG_TAG, "PATH:" + filePath);
Log.v(LOG_TAG, "PATH:" + filePath);
recordSurface = (SurfaceView) findViewById(R.id.videoSurface);
recordBut = (Button) findViewById(R.id.RecordBut);
recordBut.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (recorder.getState() != MyMediaRecorder.RECORDING) {
startRecord();
} else {
stopRecord();
recorder.release();
moveRecordFileToSave();
if (recorder == null) {
Log.v(LOG_TAG, "Recorder is null");
}
Log.v(LOG_TAG, "Value of recorder:" + recorder);
createRecorder();
initiateRecorder(recordViewHolder, width, height);
}
}
});
switchBut = (Button) findViewById(R.id.SwitchBut);
switchBut.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
libraryBut = (Button) findViewById(R.id.LibraryBut);
libraryBut.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Test_cameraActivity.this,
FileExplorer.class);
Test_cameraActivity.this.startActivity(intent);
}
});
recordViewHolder = recordSurface.getHolder();
recordViewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
recordViewHolder.addCallback(this);
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
createRecorder();
}
#Override
protected void onStart() {
super.onStart();
Log.v(LOG_TAG, "OnStart");
if (recorder != null) {
if (recorder.getState() == MyMediaRecorder.RELEASED) {
createRecorder();
}
}
Log.v(LOG_TAG, "SurfaceView create initiated. OnStart Done");
}
#Override
protected void onStop() {
super.onStop();
Log.v(LOG_TAG, "onStop received");
forceStopRecorder();
}
// General Helpers.
private void createRecorder() {
recorder = new MyMediaRecorder();
}
private void startRecord() {
if (recorder.getState() != MyMediaRecorder.PREPARED) {
Log.e(LOG_TAG, "Not recordable yet");
return;
}
recorder.start();
Log.v(LOG_TAG, "Recording started");
recordBut.setText("Stop Record");
}
private void stopRecord() {
Log.v(LOG_TAG, "Stop of recorder");
if (recorder.getState() == MyMediaRecorder.RECORDING) {
recorder.stop();
}
recorder.reset();
recordBut.setText("Record");
}
private void initiateRecorder(SurfaceHolder holder, int width, int height) {
Log.v(LOG_TAG, "H: " + height + " W:" + width);
if (recorder.getState() != MyMediaRecorder.INITIAL) {
Log.v(LOG_TAG, "Dude - not existing MediaRecorder - quitting");
return;
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setOutputFile(this.filePath);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
recorder.setVideoSize(width, height);
recorder.setVideoFrameRate(24);
recorder.setPreviewDisplay(holder.getSurface());
Log.d(LOG_TAG, "Preview restarted");
try {
recorder.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// isPrepared = true;
}
private void forceStopRecorder() {
Log.v(LOG_TAG, "Force release of recorder");
if (recorder.getState() != MyMediaRecorder.RELEASED) {
stopRecord();
recorder.release();
}
}
private void moveRecordFileToSave() {
File source = new File(filePath);
File dest = new File(Environment.getExternalStorageDirectory()
+ DIRECTORY + saveFileName);
if (dest.exists()) {
Log.v(LOG_TAG, "Delete old save file");
dest.delete();
}
source.renameTo(dest);
}
// ***** Implementing Callback ********/
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
recordViewHolder = holder;
this.width = width;
this.height = height;
if (recorder.getState() == MyMediaRecorder.RECORDING) {
stopRecord();
}
if (recorder.getState() == MyMediaRecorder.PREPARED) {
recorder.reset();
}
initiateRecorder(holder, width, height);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.v(LOG_TAG, "Surface is created: Path to use" + filePath);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.v(LOG_TAG, "Surface is Destroyed");
forceStopRecorder();
}
}
I have something that might also help, in order to jump to the other camera, follow this method:
public void flipit() {
//myCamera is the Camera object
if (Camera.getNumberOfCameras()>=2) {
myCamera.stopPreview();
myCamera.release();
//"which" is just an integer flag
switch (which) {
case 0:
myCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
which = 1;
break;
case 1:
myCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
which = 0;
break;
}
try {
myCamera.setPreviewDisplay(mHolder);
//"this" is a SurfaceView which implements SurfaceHolder.Callback,
//as found in the code examples
myCamera.setPreviewCallback(this);
myCamera.startPreview();
} catch (IOException exception) {
myCamera.release();
myCamera = null;
}
}
}
Now... for the magic trick, don't call this method from the main thread. Instead this method has to be kicked off from a separate thread, my code does this:
//btn is a Button that the user clicks on
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//onClick is invoked from main thread
//kick-off a different Thread to handle this call
Thread t = new Thread() {
public void run() {
//myViewer is the SurfaceView object which uses
//the camera
myViewer.flipit();
}
};
t.start();
}
});
I've tested this on Android 4.1.1 so I think it might work for you. (or until Google decides to break the way the camera opening/closing/releasing/unlocking/reconnecting/surfaceholder/onPause/onResume/etc..? works)
First, check if your device has more than one camera:
Camera.getNumberOfCameras();
Then, assign a camId value:
camId = Camera.CameraInfo.CAMERA_FACING_BACK;
or
camId = Camera.CameraInfo.CAMERA_FACING_FRONT;
and then creates a new Camera object to access a particular hardware camera (camId).
mCamera = Camera.open(camId);
Hope this help!