Graba video y audio con Android / Save video and audio with Android
Programación
por ipaelo | el mayo 19th, 2010 |
{lang: ‘es’}
Llevo varios dias liado intentando programar mi Htc Hero para poder grabar video y audio. Después de mucho rebuscar y probar un montón de ejemplos, al final logré hacerlo funcionar usando una mezcla de varios.
He hecho dos pequeñas aplicaciones una para audio y video y otra para solo imagen.
Camcorder es el mas completo, usamos 4 archivos: Camcorder_preview.xml, camcorderpreview.java, camcorderactivity.java y androidmanifest.xml.
AndroidManifest.xml
<?xml version ="1.0" encoding ="utf-8" ?>
<manifest xmlns:android ="http://schemas.android.com/apk/res/android"
package ="video.camcorder"
android:versionCode ="1"
android:versionName ="1.0" >
<uses-permission android:name ="android.permission.CAMERA" />
<uses-permission android:name ="android.permission.RECORD_AUDIO" />
<uses-permission android:name ="android.permission.WRITE_EXTERNAL_STORAGE" >
</uses-permission>
<application android:icon ="@drawable/icon" android:label ="@string/app_name" android:debuggable ="true" >
<activity android:name =".CamcorderActivity"
android:label ="@string/app_name" >
<intent-filter>
<action android:name ="android.intent.action.MAIN" />
<category android:name ="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Camcorder_preview.xml
<?xml version ="1.0" encoding ="utf-8" ?>
<linearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
android:orientation ="vertical" android:layout_width ="fill_parent"
android:layout_height ="fill_parent" >
<video .camcorder.CamcorderPreview android:id ="@+id/camcorder_preview"
android:layout_width ="fill_parent" android:layout_height ="fill_parent"
android:enabled ="false" android:focusable ="true" android:clickable ="true" />
</linearLayout>
CamcorderActivity.java
package video.camcorder ;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnTouchListener;
public class CamcorderActivity extends Activity {
private CamcorderPreview camcorderPreview;
private boolean recording = false ;
/** Called when the activity is first created. */
@Override
public void onCreate( Bundle savedInstanceState) {
super .onCreate ( savedInstanceState) ;
requestWindowFeature
( Window .
FEATURE_NO_TITLE ) ;
setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ) ;
setContentView( R.layout .camcorder_preview ) ;
camcorderPreview = ( CamcorderPreview) findViewById( R.id .camcorder_preview ) ;
camcorderPreview.setOnTouchListener ( new OnTouchListener( ) {
@Override
public boolean onTouch
( View view, MotionEvent event
) {
if ( event.getAction ( ) == MotionEvent.ACTION_DOWN ) {
if ( recording) {
Log.i ( "YO" , "Saliendo." ) ;
camcorderPreview.getRecorder ( ) .stop ( ) ;
camcorderPreview.getRecorder ( ) .release ( ) ;
finish( ) ;
} else {
recording = true ;
Log.i ( "YO" , "Grabando." ) ;
camcorderPreview.getRecorder ( ) .start ( ) ;
}
return true ;
}
return false ;
}
} ) ;
}
}
Y la clase que realmente hace el trabajo duro.
Camcorderpreview.java:
package video.camcorder ;
import java.io.File;
import java.io.IOException;
import android.content.Context;
import android.media.MediaRecorder;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CamcorderPreview extends SurfaceView implements
SurfaceHolder.Callback {
MediaRecorder recorder;
SurfaceHolder holder;
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 .DEFAULT ) ;
recorder.setOutputFormat ( MediaRecorder.OutputFormat .MPEG_4 ) ;
recorder.setAudioEncoder ( MediaRecorder.AudioEncoder .AMR_NB ) ;
recorder.setVideoEncoder ( MediaRecorder.VideoEncoder .MPEG_4_SP ) ;
}
@Override
public void surfaceChanged( SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated( SurfaceHolder holder) {
String path =
Environment .
getExternalStorageDirectory ( ) .
getAbsolutePath ( ) +
"/data/ejemplo.mp4" ;
File directory =
new File ( path
) .
getParentFile ( ) ;
if ( !directory.exists ( ) && !directory.mkdirs ( ) ) {
try {
throw new IOException ( "Path to file could not be created." ) ;
// TODO Auto-generated catch block
e.printStackTrace ( ) ;
}
}
recorder.setOutputFile ( path) ;
recorder.setPreviewDisplay ( holder.getSurface ( ) ) ;
if ( recorder != null ) {
try {
recorder.prepare ( ) ;
Log.e ( "YO.1.Illegal" , e.toString ( ) ) ;
Log.e ( "YO.2.IOException" , e.toString ( ) ) ;
}
}
}
@Override
public void surfaceDestroyed( SurfaceHolder holder) {
}
public MediaRecorder getRecorder( ) {
return recorder;
}
}
Y VideoRecorder que solo graba video, que es interesante si no te sirve para nada el audio.
VideoRecorder Manifest.xml
<?xml version ="1.0" encoding ="utf-8" ?>
<manifest xmlns:android ="http://schemas.android.com/apk/res/android"
package ="video.recorder"
android:versionCode ="1"
android:versionName ="1.0" >
<application android:icon ="@drawable/icon" android:label ="@string/app_name" >
<activity android:name =".VideoRecorder"
android:label ="@string/app_name" >
<intent-filter>
<action android:name ="android.intent.action.MAIN" />
<category android:name ="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name ="android.permission.CAMERA" > </uses-permission>
<uses-permission android:name ="android.permission.WRITE_EXTERNAL_STORAGE" > </uses-permission>
<uses-permission android:name ="android.permission.RECORD_AUDIO" > </uses-permission>
</manifest>
Videorecorder.java
package video.recorder ;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
public class VideoRecorder extends Activity
{
private final static String TAG =
"Playing" ;
private MediaRecorder recorder;
private Preview mPreview;
/** Called when the activity is first created. */
@Override
public void onCreate( Bundle savedInstanceState)
{
super .onCreate ( savedInstanceState) ;
requestWindowFeature
( Window .
FEATURE_NO_TITLE ) ;
recorder = new MediaRecorder( ) ;
recorder.setVideoSource ( MediaRecorder.VideoSource .DEFAULT ) ;
recorder.setOutputFormat ( MediaRecorder.OutputFormat .MPEG_4 ) ;
recorder.setVideoEncoder ( MediaRecorder.VideoEncoder .MPEG_4_SP ) ;
mPreview = new Preview( this ,recorder) ;
setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ) ;
setContentView( mPreview) ;
}
@Override
public boolean onCreateOptionsMenu
( Menu menu
)
{
menu.add ( 0 , 0 , 0 , "StartRecording" ) ;
menu.add ( 0 , 1 , 0 , "StopRecording" ) ;
return super .onCreateOptionsMenu ( menu) ;
}
@Override
public boolean onOptionsItemSelected
( MenuItem item
)
{
switch ( item.getItemId ( ) )
{
case 0 :
try {
recorder.start ( ) ;
String message = e.
getMessage ( ) ;
Log.w ( TAG, e) ;
recorder.release ( ) ;
}
break ;
case 1 : //GoToAllNotes
recorder.stop ( ) ;
recorder.release ( ) ;
recorder = null ;
finish( ) ;
break ;
default :
break ;
}
return super .onOptionsItemSelected ( item) ;
}
}
class Preview extends SurfaceView implements SurfaceHolder.Callback
{
SurfaceHolder mHolder;
MediaRecorder tempRecorder;
Preview
( Context context, MediaRecorder recorder
)
{
super ( context) ;
tempRecorder = recorder;
mHolder = getHolder( ) ;
mHolder.addCallback ( this ) ;
mHolder.setType ( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS ) ;
}
public Surface getSurface( )
{
return mHolder.getSurface ( ) ;
}
public void surfaceCreated( SurfaceHolder holder)
{
tempRecorder.setOutputFile ( "/sdcard/myVideo.3gp" ) ;
tempRecorder.setPreviewDisplay ( mHolder.getSurface ( ) ) ;
try {
tempRecorder.prepare ( ) ;
String message = e.
getMessage ( ) ;
tempRecorder.release ( ) ;
tempRecorder = null ;
}
}
public void surfaceDestroyed( SurfaceHolder holder)
{
if ( tempRecorder!=null )
{
tempRecorder.release ( ) ;
tempRecorder = null ;
}
}
public void surfaceChanged( SurfaceHolder holder, int format, int w, int h)
{
}
}
En el foro de and.roid.es esta el hilo donde discutimos sobre este tema.
Comentarios (4)