• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.media;
18 
19 import android.annotation.NonNull;
20 import android.annotation.SystemApi;
21 import android.app.ActivityThread;
22 import android.hardware.Camera;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import android.os.Looper;
26 import android.os.Message;
27 import android.os.PersistableBundle;
28 import android.util.Log;
29 import android.view.Surface;
30 
31 import java.io.File;
32 import java.io.FileDescriptor;
33 import java.io.IOException;
34 import java.io.RandomAccessFile;
35 import java.lang.ref.WeakReference;
36 
37 /**
38  * Used to record audio and video. The recording control is based on a
39  * simple state machine (see below).
40  *
41  * <p><img src="{@docRoot}images/mediarecorder_state_diagram.gif" border="0" />
42  * </p>
43  *
44  * <p>A common case of using MediaRecorder to record audio works as follows:
45  *
46  * <pre>MediaRecorder recorder = new MediaRecorder();
47  * recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
48  * recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
49  * recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
50  * recorder.setOutputFile(PATH_NAME);
51  * recorder.prepare();
52  * recorder.start();   // Recording is now started
53  * ...
54  * recorder.stop();
55  * recorder.reset();   // You can reuse the object by going back to setAudioSource() step
56  * recorder.release(); // Now the object cannot be reused
57  * </pre>
58  *
59  * <p>Applications may want to register for informational and error
60  * events in order to be informed of some internal update and possible
61  * runtime errors during recording. Registration for such events is
62  * done by setting the appropriate listeners (via calls
63  * (to {@link #setOnInfoListener(OnInfoListener)}setOnInfoListener and/or
64  * {@link #setOnErrorListener(OnErrorListener)}setOnErrorListener).
65  * In order to receive the respective callback associated with these listeners,
66  * applications are required to create MediaRecorder objects on threads with a
67  * Looper running (the main UI thread by default already has a Looper running).
68  *
69  * <p><strong>Note:</strong> Currently, MediaRecorder does not work on the emulator.
70  *
71  * <div class="special reference">
72  * <h3>Developer Guides</h3>
73  * <p>For more information about how to use MediaRecorder for recording video, read the
74  * <a href="{@docRoot}guide/topics/media/camera.html#capture-video">Camera</a> developer guide.
75  * For more information about how to use MediaRecorder for recording sound, read the
76  * <a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a> developer guide.</p>
77  * </div>
78  */
79 public class MediaRecorder
80 {
81     static {
82         System.loadLibrary("media_jni");
native_init()83         native_init();
84     }
85     private final static String TAG = "MediaRecorder";
86 
87     // The two fields below are accessed by native methods
88     @SuppressWarnings("unused")
89     private long mNativeContext;
90 
91     @SuppressWarnings("unused")
92     private Surface mSurface;
93 
94     private String mPath;
95     private FileDescriptor mFd;
96     private File mFile;
97     private EventHandler mEventHandler;
98     private OnErrorListener mOnErrorListener;
99     private OnInfoListener mOnInfoListener;
100 
101     /**
102      * Default constructor.
103      */
MediaRecorder()104     public MediaRecorder() {
105 
106         Looper looper;
107         if ((looper = Looper.myLooper()) != null) {
108             mEventHandler = new EventHandler(this, looper);
109         } else if ((looper = Looper.getMainLooper()) != null) {
110             mEventHandler = new EventHandler(this, looper);
111         } else {
112             mEventHandler = null;
113         }
114 
115         String packageName = ActivityThread.currentPackageName();
116         /* Native setup requires a weak reference to our object.
117          * It's easier to create it here than in C++.
118          */
119         native_setup(new WeakReference<MediaRecorder>(this), packageName,
120                 ActivityThread.currentOpPackageName());
121     }
122 
123     /**
124      * Sets a {@link android.hardware.Camera} to use for recording.
125      *
126      * <p>Use this function to switch quickly between preview and capture mode without a teardown of
127      * the camera object. {@link android.hardware.Camera#unlock()} should be called before
128      * this. Must call before {@link #prepare}.</p>
129      *
130      * @param c the Camera to use for recording
131      * @deprecated Use {@link #getSurface} and the {@link android.hardware.camera2} API instead.
132      */
133     @Deprecated
setCamera(Camera c)134     public native void setCamera(Camera c);
135 
136     /**
137      * Gets the surface to record from when using SURFACE video source.
138      *
139      * <p> May only be called after {@link #prepare}. Frames rendered to the Surface before
140      * {@link #start} will be discarded.</p>
141      *
142      * @throws IllegalStateException if it is called before {@link #prepare}, after
143      * {@link #stop}, or is called when VideoSource is not set to SURFACE.
144      * @see android.media.MediaRecorder.VideoSource
145      */
getSurface()146     public native Surface getSurface();
147 
148     /**
149      * Configures the recorder to use a persistent surface when using SURFACE video source.
150      * <p> May only be called before {@link #prepare}. If called, {@link #getSurface} should
151      * not be used and will throw IllegalStateException. Frames rendered to the Surface
152      * before {@link #start} will be discarded.</p>
153 
154      * @param surface a persistent input surface created by
155      *           {@link MediaCodec#createPersistentInputSurface}
156      * @throws IllegalStateException if it is called after {@link #prepare} and before
157      * {@link #stop}.
158      * @throws IllegalArgumentException if the surface was not created by
159      *           {@link MediaCodec#createPersistentInputSurface}.
160      * @see MediaCodec#createPersistentInputSurface
161      * @see MediaRecorder.VideoSource
162      */
setInputSurface(@onNull Surface surface)163     public void setInputSurface(@NonNull Surface surface) {
164         if (!(surface instanceof MediaCodec.PersistentSurface)) {
165             throw new IllegalArgumentException("not a PersistentSurface");
166         }
167         native_setInputSurface(surface);
168     }
169 
native_setInputSurface(@onNull Surface surface)170     private native final void native_setInputSurface(@NonNull Surface surface);
171 
172     /**
173      * Sets a Surface to show a preview of recorded media (video). Calls this
174      * before prepare() to make sure that the desirable preview display is
175      * set. If {@link #setCamera(Camera)} is used and the surface has been
176      * already set to the camera, application do not need to call this. If
177      * this is called with non-null surface, the preview surface of the camera
178      * will be replaced by the new surface. If this method is called with null
179      * surface or not called at all, media recorder will not change the preview
180      * surface of the camera.
181      *
182      * @param sv the Surface to use for the preview
183      * @see android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)
184      */
setPreviewDisplay(Surface sv)185     public void setPreviewDisplay(Surface sv) {
186         mSurface = sv;
187     }
188 
189     /**
190      * Defines the audio source.
191      * An audio source defines both a default physical source of audio signal, and a recording
192      * configuration. These constants are for instance used
193      * in {@link MediaRecorder#setAudioSource(int)} or
194      * {@link AudioRecord.Builder#setAudioSource(int)}.
195      */
196     public final class AudioSource {
197 
AudioSource()198         private AudioSource() {}
199 
200         /** @hide */
201         public final static int AUDIO_SOURCE_INVALID = -1;
202 
203       /* Do not change these values without updating their counterparts
204        * in system/media/audio/include/system/audio.h!
205        */
206 
207         /** Default audio source **/
208         public static final int DEFAULT = 0;
209 
210         /** Microphone audio source */
211         public static final int MIC = 1;
212 
213         /** Voice call uplink (Tx) audio source.
214          * <p>
215          * Capturing from <code>VOICE_UPLINK</code> source requires the
216          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
217          * This permission is reserved for use by system components and is not available to
218          * third-party applications.
219          * </p>
220          */
221         public static final int VOICE_UPLINK = 2;
222 
223         /** Voice call downlink (Rx) audio source.
224          * <p>
225          * Capturing from <code>VOICE_DOWNLINK</code> source requires the
226          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
227          * This permission is reserved for use by system components and is not available to
228          * third-party applications.
229          * </p>
230          */
231         public static final int VOICE_DOWNLINK = 3;
232 
233         /** Voice call uplink + downlink audio source
234          * <p>
235          * Capturing from <code>VOICE_CALL</code> source requires the
236          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
237          * This permission is reserved for use by system components and is not available to
238          * third-party applications.
239          * </p>
240          */
241         public static final int VOICE_CALL = 4;
242 
243         /** Microphone audio source tuned for video recording, with the same orientation
244          *  as the camera if available. */
245         public static final int CAMCORDER = 5;
246 
247         /** Microphone audio source tuned for voice recognition. */
248         public static final int VOICE_RECOGNITION = 6;
249 
250         /** Microphone audio source tuned for voice communications such as VoIP. It
251          *  will for instance take advantage of echo cancellation or automatic gain control
252          *  if available.
253          */
254         public static final int VOICE_COMMUNICATION = 7;
255 
256         /**
257          * Audio source for a submix of audio streams to be presented remotely.
258          * <p>
259          * An application can use this audio source to capture a mix of audio streams
260          * that should be transmitted to a remote receiver such as a Wifi display.
261          * While recording is active, these audio streams are redirected to the remote
262          * submix instead of being played on the device speaker or headset.
263          * </p><p>
264          * Certain streams are excluded from the remote submix, including
265          * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_ALARM},
266          * and {@link AudioManager#STREAM_NOTIFICATION}.  These streams will continue
267          * to be presented locally as usual.
268          * </p><p>
269          * Capturing the remote submix audio requires the
270          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
271          * This permission is reserved for use by system components and is not available to
272          * third-party applications.
273          * </p>
274          */
275         public static final int REMOTE_SUBMIX = 8;
276 
277         /** Microphone audio source tuned for unprocessed (raw) sound if available, behaves like
278          *  {@link #DEFAULT} otherwise. */
279         public static final int UNPROCESSED = 9;
280 
281         /**
282          * Audio source for capturing broadcast radio tuner output.
283          * @hide
284          */
285         @SystemApi
286         public static final int RADIO_TUNER = 1998;
287 
288         /**
289          * Audio source for preemptible, low-priority software hotword detection
290          * It presents the same gain and pre processing tuning as {@link #VOICE_RECOGNITION}.
291          * <p>
292          * An application should use this audio source when it wishes to do
293          * always-on software hotword detection, while gracefully giving in to any other application
294          * that might want to read from the microphone.
295          * </p>
296          * This is a hidden audio source.
297          * @hide
298          */
299         @SystemApi
300         public static final int HOTWORD = 1999;
301     }
302 
303     // TODO make AudioSource static (API change) and move this method inside the AudioSource class
304     /**
305      * @hide
306      * @param source An audio source to test
307      * @return true if the source is only visible to system components
308      */
isSystemOnlyAudioSource(int source)309     public static boolean isSystemOnlyAudioSource(int source) {
310         switch(source) {
311         case AudioSource.DEFAULT:
312         case AudioSource.MIC:
313         case AudioSource.VOICE_UPLINK:
314         case AudioSource.VOICE_DOWNLINK:
315         case AudioSource.VOICE_CALL:
316         case AudioSource.CAMCORDER:
317         case AudioSource.VOICE_RECOGNITION:
318         case AudioSource.VOICE_COMMUNICATION:
319         //case REMOTE_SUBMIX:  considered "system" as it requires system permissions
320         case AudioSource.UNPROCESSED:
321             return false;
322         default:
323             return true;
324         }
325     }
326 
327     /** @hide */
toLogFriendlyAudioSource(int source)328     public static final String toLogFriendlyAudioSource(int source) {
329         switch(source) {
330         case AudioSource.DEFAULT:
331             return "DEFAULT";
332         case AudioSource.MIC:
333             return "MIC";
334         case AudioSource.VOICE_UPLINK:
335             return "VOICE_UPLINK";
336         case AudioSource.VOICE_DOWNLINK:
337             return "VOICE_DOWNLINK";
338         case AudioSource.VOICE_CALL:
339             return "VOICE_CALL";
340         case AudioSource.CAMCORDER:
341             return "CAMCORDER";
342         case AudioSource.VOICE_RECOGNITION:
343             return "VOICE_RECOGNITION";
344         case AudioSource.VOICE_COMMUNICATION:
345             return "VOICE_COMMUNICATION";
346         case AudioSource.REMOTE_SUBMIX:
347             return "REMOTE_SUBMIX";
348         case AudioSource.UNPROCESSED:
349             return "UNPROCESSED";
350         case AudioSource.RADIO_TUNER:
351             return "RADIO_TUNER";
352         case AudioSource.HOTWORD:
353             return "HOTWORD";
354         case AudioSource.AUDIO_SOURCE_INVALID:
355             return "AUDIO_SOURCE_INVALID";
356         default:
357             return "unknown source " + source;
358         }
359     }
360 
361     /**
362      * Defines the video source. These constants are used with
363      * {@link MediaRecorder#setVideoSource(int)}.
364      */
365     public final class VideoSource {
366       /* Do not change these values without updating their counterparts
367        * in include/media/mediarecorder.h!
368        */
VideoSource()369         private VideoSource() {}
370         public static final int DEFAULT = 0;
371         /** Camera video source
372          * <p>
373          * Using the {@link android.hardware.Camera} API as video source.
374          * </p>
375          */
376         public static final int CAMERA = 1;
377         /** Surface video source
378          * <p>
379          * Using a Surface as video source.
380          * </p><p>
381          * This flag must be used when recording from an
382          * {@link android.hardware.camera2} API source.
383          * </p><p>
384          * When using this video source type, use {@link MediaRecorder#getSurface()}
385          * to retrieve the surface created by MediaRecorder.
386          */
387         public static final int SURFACE = 2;
388     }
389 
390     /**
391      * Defines the output format. These constants are used with
392      * {@link MediaRecorder#setOutputFormat(int)}.
393      */
394     public final class OutputFormat {
395       /* Do not change these values without updating their counterparts
396        * in include/media/mediarecorder.h!
397        */
OutputFormat()398         private OutputFormat() {}
399         public static final int DEFAULT = 0;
400         /** 3GPP media file format*/
401         public static final int THREE_GPP = 1;
402         /** MPEG4 media file format*/
403         public static final int MPEG_4 = 2;
404 
405         /** The following formats are audio only .aac or .amr formats */
406 
407         /**
408          * AMR NB file format
409          * @deprecated  Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB
410          */
411         public static final int RAW_AMR = 3;
412 
413         /** AMR NB file format */
414         public static final int AMR_NB = 3;
415 
416         /** AMR WB file format */
417         public static final int AMR_WB = 4;
418 
419         /** @hide AAC ADIF file format */
420         public static final int AAC_ADIF = 5;
421 
422         /** AAC ADTS file format */
423         public static final int AAC_ADTS = 6;
424 
425         /** @hide Stream over a socket, limited to a single stream */
426         public static final int OUTPUT_FORMAT_RTP_AVP = 7;
427 
428         /** H.264/AAC data encapsulated in MPEG2/TS */
429         public static final int MPEG_2_TS = 8;
430 
431         /** VP8/VORBIS data in a WEBM container */
432         public static final int WEBM = 9;
433     };
434 
435     /**
436      * Defines the audio encoding. These constants are used with
437      * {@link MediaRecorder#setAudioEncoder(int)}.
438      */
439     public final class AudioEncoder {
440       /* Do not change these values without updating their counterparts
441        * in include/media/mediarecorder.h!
442        */
AudioEncoder()443         private AudioEncoder() {}
444         public static final int DEFAULT = 0;
445         /** AMR (Narrowband) audio codec */
446         public static final int AMR_NB = 1;
447         /** AMR (Wideband) audio codec */
448         public static final int AMR_WB = 2;
449         /** AAC Low Complexity (AAC-LC) audio codec */
450         public static final int AAC = 3;
451         /** High Efficiency AAC (HE-AAC) audio codec */
452         public static final int HE_AAC = 4;
453         /** Enhanced Low Delay AAC (AAC-ELD) audio codec */
454         public static final int AAC_ELD = 5;
455         /** Ogg Vorbis audio codec */
456         public static final int VORBIS = 6;
457     }
458 
459     /**
460      * Defines the video encoding. These constants are used with
461      * {@link MediaRecorder#setVideoEncoder(int)}.
462      */
463     public final class VideoEncoder {
464       /* Do not change these values without updating their counterparts
465        * in include/media/mediarecorder.h!
466        */
VideoEncoder()467         private VideoEncoder() {}
468         public static final int DEFAULT = 0;
469         public static final int H263 = 1;
470         public static final int H264 = 2;
471         public static final int MPEG_4_SP = 3;
472         public static final int VP8 = 4;
473         public static final int HEVC = 5;
474     }
475 
476     /**
477      * Sets the audio source to be used for recording. If this method is not
478      * called, the output file will not contain an audio track. The source needs
479      * to be specified before setting recording-parameters or encoders. Call
480      * this only before setOutputFormat().
481      *
482      * @param audio_source the audio source to use
483      * @throws IllegalStateException if it is called after setOutputFormat()
484      * @see android.media.MediaRecorder.AudioSource
485      */
setAudioSource(int audio_source)486     public native void setAudioSource(int audio_source)
487             throws IllegalStateException;
488 
489     /**
490      * Gets the maximum value for audio sources.
491      * @see android.media.MediaRecorder.AudioSource
492      */
getAudioSourceMax()493     public static final int getAudioSourceMax() {
494         return AudioSource.UNPROCESSED;
495     }
496 
497     /**
498      * Sets the video source to be used for recording. If this method is not
499      * called, the output file will not contain an video track. The source needs
500      * to be specified before setting recording-parameters or encoders. Call
501      * this only before setOutputFormat().
502      *
503      * @param video_source the video source to use
504      * @throws IllegalStateException if it is called after setOutputFormat()
505      * @see android.media.MediaRecorder.VideoSource
506      */
setVideoSource(int video_source)507     public native void setVideoSource(int video_source)
508             throws IllegalStateException;
509 
510     /**
511      * Uses the settings from a CamcorderProfile object for recording. This method should
512      * be called after the video AND audio sources are set, and before setOutputFile().
513      * If a time lapse CamcorderProfile is used, audio related source or recording
514      * parameters are ignored.
515      *
516      * @param profile the CamcorderProfile to use
517      * @see android.media.CamcorderProfile
518      */
setProfile(CamcorderProfile profile)519     public void setProfile(CamcorderProfile profile) {
520         setOutputFormat(profile.fileFormat);
521         setVideoFrameRate(profile.videoFrameRate);
522         setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
523         setVideoEncodingBitRate(profile.videoBitRate);
524         setVideoEncoder(profile.videoCodec);
525         if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
526              profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) {
527             // Nothing needs to be done. Call to setCaptureRate() enables
528             // time lapse video recording.
529         } else {
530             setAudioEncodingBitRate(profile.audioBitRate);
531             setAudioChannels(profile.audioChannels);
532             setAudioSamplingRate(profile.audioSampleRate);
533             setAudioEncoder(profile.audioCodec);
534         }
535     }
536 
537     /**
538      * Set video frame capture rate. This can be used to set a different video frame capture
539      * rate than the recorded video's playback rate. This method also sets the recording mode
540      * to time lapse. In time lapse video recording, only video is recorded. Audio related
541      * parameters are ignored when a time lapse recording session starts, if an application
542      * sets them.
543      *
544      * @param fps Rate at which frames should be captured in frames per second.
545      * The fps can go as low as desired. However the fastest fps will be limited by the hardware.
546      * For resolutions that can be captured by the video camera, the fastest fps can be computed using
547      * {@link android.hardware.Camera.Parameters#getPreviewFpsRange(int[])}. For higher
548      * resolutions the fastest fps may be more restrictive.
549      * Note that the recorder cannot guarantee that frames will be captured at the
550      * given rate due to camera/encoder limitations. However it tries to be as close as
551      * possible.
552      */
setCaptureRate(double fps)553     public void setCaptureRate(double fps) {
554         // Make sure that time lapse is enabled when this method is called.
555         setParameter("time-lapse-enable=1");
556         setParameter("time-lapse-fps=" + fps);
557     }
558 
559     /**
560      * Sets the orientation hint for output video playback.
561      * This method should be called before prepare(). This method will not
562      * trigger the source video frame to rotate during video recording, but to
563      * add a composition matrix containing the rotation angle in the output
564      * video if the output format is OutputFormat.THREE_GPP or
565      * OutputFormat.MPEG_4 so that a video player can choose the proper
566      * orientation for playback. Note that some video players may choose
567      * to ignore the compostion matrix in a video during playback.
568      *
569      * @param degrees the angle to be rotated clockwise in degrees.
570      * The supported angles are 0, 90, 180, and 270 degrees.
571      * @throws IllegalArgumentException if the angle is not supported.
572      *
573      */
setOrientationHint(int degrees)574     public void setOrientationHint(int degrees) {
575         if (degrees != 0   &&
576             degrees != 90  &&
577             degrees != 180 &&
578             degrees != 270) {
579             throw new IllegalArgumentException("Unsupported angle: " + degrees);
580         }
581         setParameter("video-param-rotation-angle-degrees=" + degrees);
582     }
583 
584     /**
585      * Set and store the geodata (latitude and longitude) in the output file.
586      * This method should be called before prepare(). The geodata is
587      * stored in udta box if the output format is OutputFormat.THREE_GPP
588      * or OutputFormat.MPEG_4, and is ignored for other output formats.
589      * The geodata is stored according to ISO-6709 standard.
590      *
591      * @param latitude latitude in degrees. Its value must be in the
592      * range [-90, 90].
593      * @param longitude longitude in degrees. Its value must be in the
594      * range [-180, 180].
595      *
596      * @throws IllegalArgumentException if the given latitude or
597      * longitude is out of range.
598      *
599      */
setLocation(float latitude, float longitude)600     public void setLocation(float latitude, float longitude) {
601         int latitudex10000  = (int) (latitude * 10000 + 0.5);
602         int longitudex10000 = (int) (longitude * 10000 + 0.5);
603 
604         if (latitudex10000 > 900000 || latitudex10000 < -900000) {
605             String msg = "Latitude: " + latitude + " out of range.";
606             throw new IllegalArgumentException(msg);
607         }
608         if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
609             String msg = "Longitude: " + longitude + " out of range";
610             throw new IllegalArgumentException(msg);
611         }
612 
613         setParameter("param-geotag-latitude=" + latitudex10000);
614         setParameter("param-geotag-longitude=" + longitudex10000);
615     }
616 
617     /**
618      * Sets the format of the output file produced during recording. Call this
619      * after setAudioSource()/setVideoSource() but before prepare().
620      *
621      * <p>It is recommended to always use 3GP format when using the H.263
622      * video encoder and AMR audio encoder. Using an MPEG-4 container format
623      * may confuse some desktop players.</p>
624      *
625      * @param output_format the output format to use. The output format
626      * needs to be specified before setting recording-parameters or encoders.
627      * @throws IllegalStateException if it is called after prepare() or before
628      * setAudioSource()/setVideoSource().
629      * @see android.media.MediaRecorder.OutputFormat
630      */
setOutputFormat(int output_format)631     public native void setOutputFormat(int output_format)
632             throws IllegalStateException;
633 
634     /**
635      * Sets the width and height of the video to be captured.  Must be called
636      * after setVideoSource(). Call this after setOutFormat() but before
637      * prepare().
638      *
639      * @param width the width of the video to be captured
640      * @param height the height of the video to be captured
641      * @throws IllegalStateException if it is called after
642      * prepare() or before setOutputFormat()
643      */
setVideoSize(int width, int height)644     public native void setVideoSize(int width, int height)
645             throws IllegalStateException;
646 
647     /**
648      * Sets the frame rate of the video to be captured.  Must be called
649      * after setVideoSource(). Call this after setOutFormat() but before
650      * prepare().
651      *
652      * @param rate the number of frames per second of video to capture
653      * @throws IllegalStateException if it is called after
654      * prepare() or before setOutputFormat().
655      *
656      * NOTE: On some devices that have auto-frame rate, this sets the
657      * maximum frame rate, not a constant frame rate. Actual frame rate
658      * will vary according to lighting conditions.
659      */
setVideoFrameRate(int rate)660     public native void setVideoFrameRate(int rate) throws IllegalStateException;
661 
662     /**
663      * Sets the maximum duration (in ms) of the recording session.
664      * Call this after setOutFormat() but before prepare().
665      * After recording reaches the specified duration, a notification
666      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
667      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
668      * and recording will be stopped. Stopping happens asynchronously, there
669      * is no guarantee that the recorder will have stopped by the time the
670      * listener is notified.
671      *
672      * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit)
673      *
674      */
setMaxDuration(int max_duration_ms)675     public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException;
676 
677     /**
678      * Sets the maximum filesize (in bytes) of the recording session.
679      * Call this after setOutFormat() but before prepare().
680      * After recording reaches the specified filesize, a notification
681      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
682      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
683      * and recording will be stopped. Stopping happens asynchronously, there
684      * is no guarantee that the recorder will have stopped by the time the
685      * listener is notified.
686      *
687      * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit)
688      *
689      */
setMaxFileSize(long max_filesize_bytes)690     public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException;
691 
692     /**
693      * Sets the audio encoder to be used for recording. If this method is not
694      * called, the output file will not contain an audio track. Call this after
695      * setOutputFormat() but before prepare().
696      *
697      * @param audio_encoder the audio encoder to use.
698      * @throws IllegalStateException if it is called before
699      * setOutputFormat() or after prepare().
700      * @see android.media.MediaRecorder.AudioEncoder
701      */
setAudioEncoder(int audio_encoder)702     public native void setAudioEncoder(int audio_encoder)
703             throws IllegalStateException;
704 
705     /**
706      * Sets the video encoder to be used for recording. If this method is not
707      * called, the output file will not contain an video track. Call this after
708      * setOutputFormat() and before prepare().
709      *
710      * @param video_encoder the video encoder to use.
711      * @throws IllegalStateException if it is called before
712      * setOutputFormat() or after prepare()
713      * @see android.media.MediaRecorder.VideoEncoder
714      */
setVideoEncoder(int video_encoder)715     public native void setVideoEncoder(int video_encoder)
716             throws IllegalStateException;
717 
718     /**
719      * Sets the audio sampling rate for recording. Call this method before prepare().
720      * Prepare() may perform additional checks on the parameter to make sure whether
721      * the specified audio sampling rate is applicable. The sampling rate really depends
722      * on the format for the audio recording, as well as the capabilities of the platform.
723      * For instance, the sampling rate supported by AAC audio coding standard ranges
724      * from 8 to 96 kHz, the sampling rate supported by AMRNB is 8kHz, and the sampling
725      * rate supported by AMRWB is 16kHz. Please consult with the related audio coding
726      * standard for the supported audio sampling rate.
727      *
728      * @param samplingRate the sampling rate for audio in samples per second.
729      */
setAudioSamplingRate(int samplingRate)730     public void setAudioSamplingRate(int samplingRate) {
731         if (samplingRate <= 0) {
732             throw new IllegalArgumentException("Audio sampling rate is not positive");
733         }
734         setParameter("audio-param-sampling-rate=" + samplingRate);
735     }
736 
737     /**
738      * Sets the number of audio channels for recording. Call this method before prepare().
739      * Prepare() may perform additional checks on the parameter to make sure whether the
740      * specified number of audio channels are applicable.
741      *
742      * @param numChannels the number of audio channels. Usually it is either 1 (mono) or 2
743      * (stereo).
744      */
setAudioChannels(int numChannels)745     public void setAudioChannels(int numChannels) {
746         if (numChannels <= 0) {
747             throw new IllegalArgumentException("Number of channels is not positive");
748         }
749         setParameter("audio-param-number-of-channels=" + numChannels);
750     }
751 
752     /**
753      * Sets the audio encoding bit rate for recording. Call this method before prepare().
754      * Prepare() may perform additional checks on the parameter to make sure whether the
755      * specified bit rate is applicable, and sometimes the passed bitRate will be clipped
756      * internally to ensure the audio recording can proceed smoothly based on the
757      * capabilities of the platform.
758      *
759      * @param bitRate the audio encoding bit rate in bits per second.
760      */
setAudioEncodingBitRate(int bitRate)761     public void setAudioEncodingBitRate(int bitRate) {
762         if (bitRate <= 0) {
763             throw new IllegalArgumentException("Audio encoding bit rate is not positive");
764         }
765         setParameter("audio-param-encoding-bitrate=" + bitRate);
766     }
767 
768     /**
769      * Sets the video encoding bit rate for recording. Call this method before prepare().
770      * Prepare() may perform additional checks on the parameter to make sure whether the
771      * specified bit rate is applicable, and sometimes the passed bitRate will be
772      * clipped internally to ensure the video recording can proceed smoothly based on
773      * the capabilities of the platform.
774      *
775      * @param bitRate the video encoding bit rate in bits per second.
776      */
setVideoEncodingBitRate(int bitRate)777     public void setVideoEncodingBitRate(int bitRate) {
778         if (bitRate <= 0) {
779             throw new IllegalArgumentException("Video encoding bit rate is not positive");
780         }
781         setParameter("video-param-encoding-bitrate=" + bitRate);
782     }
783 
784     /**
785      * Sets the desired video encoding profile and level for recording. The profile and level
786      * must be valid for the video encoder set by {@link #setVideoEncoder}. This method can
787      * called before or after {@link #setVideoEncoder} but it must be called before {@link #prepare}.
788      * {@code prepare()} may perform additional checks on the parameter to make sure that the specified
789      * profile and level are applicable, and sometimes the passed profile or level will be
790      * discarded due to codec capablity or to ensure the video recording can proceed smoothly
791      * based on the capabilities of the platform. <br>Application can also use the
792      * {@link MediaCodecInfo.CodecCapabilities#profileLevels} to query applicable combination of profile
793      * and level for the corresponding format. Note that the requested profile/level may not be supported by
794      * the codec that is actually being used by this MediaRecorder instance.
795      * @param profile declared in {@link MediaCodecInfo.CodecProfileLevel}.
796      * @param level declared in {@link MediaCodecInfo.CodecProfileLevel}.
797      * @throws IllegalArgumentException when an invalid profile or level value is used.
798      */
setVideoEncodingProfileLevel(int profile, int level)799     public void setVideoEncodingProfileLevel(int profile, int level) {
800         if (profile <= 0)  {
801             throw new IllegalArgumentException("Video encoding profile is not positive");
802         }
803         if (level <= 0)  {
804             throw new IllegalArgumentException("Video encoding level is not positive");
805         }
806         setParameter("video-param-encoder-profile=" + profile);
807         setParameter("video-param-encoder-level=" + level);
808     }
809 
810     /**
811      * Currently not implemented. It does nothing.
812      * @deprecated Time lapse mode video recording using camera still image capture
813      * is not desirable, and will not be supported.
814      * @hide
815      */
setAuxiliaryOutputFile(FileDescriptor fd)816     public void setAuxiliaryOutputFile(FileDescriptor fd)
817     {
818         Log.w(TAG, "setAuxiliaryOutputFile(FileDescriptor) is no longer supported.");
819     }
820 
821     /**
822      * Currently not implemented. It does nothing.
823      * @deprecated Time lapse mode video recording using camera still image capture
824      * is not desirable, and will not be supported.
825      * @hide
826      */
setAuxiliaryOutputFile(String path)827     public void setAuxiliaryOutputFile(String path)
828     {
829         Log.w(TAG, "setAuxiliaryOutputFile(String) is no longer supported.");
830     }
831 
832     /**
833      * Pass in the file descriptor of the file to be written. Call this after
834      * setOutputFormat() but before prepare().
835      *
836      * @param fd an open file descriptor to be written into.
837      * @throws IllegalStateException if it is called before
838      * setOutputFormat() or after prepare()
839      */
setOutputFile(FileDescriptor fd)840     public void setOutputFile(FileDescriptor fd) throws IllegalStateException
841     {
842         mPath = null;
843         mFile = null;
844         mFd = fd;
845     }
846 
847     /**
848      * Pass in the file object to be written. Call this after setOutputFormat() but before prepare().
849      * File should be seekable. After setting the next output file, application should not use the
850      * file until {@link #stop}. Application is responsible for cleaning up unused files after
851      * {@link #stop} is called.
852      *
853      * @param file the file object to be written into.
854      */
setOutputFile(File file)855     public void setOutputFile(File file)
856     {
857         mPath = null;
858         mFd = null;
859         mFile = file;
860     }
861 
862     /**
863      * Sets the next output file descriptor to be used when the maximum filesize is reached
864      * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File descriptor
865      * must be seekable and writable. After setting the next output file, application should not
866      * use the file referenced by this file descriptor until {@link #stop}. It is the application's
867      * responsibility to close the file descriptor. It is safe to do so as soon as this call returns.
868      * Application must call this after receiving on the
869      * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
870      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
871      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
872      * that output. Application will receive{@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
873      * when the next output file is used. Application will not be able to set a new output file if
874      * the previous one has not been used. Application is responsible for cleaning up unused files
875      * after {@link #stop} is called.
876      *
877      * @param fd an open file descriptor to be written into.
878      * @throws IllegalStateException if it is called before prepare().
879      * @throws IOException if setNextOutputFile fails otherwise.
880      */
setNextOutputFile(FileDescriptor fd)881     public void setNextOutputFile(FileDescriptor fd) throws IOException
882     {
883         _setNextOutputFile(fd);
884     }
885 
886     /**
887      * Sets the path of the output file to be produced. Call this after
888      * setOutputFormat() but before prepare().
889      *
890      * @param path The pathname to use.
891      * @throws IllegalStateException if it is called before
892      * setOutputFormat() or after prepare()
893      */
setOutputFile(String path)894     public void setOutputFile(String path) throws IllegalStateException
895     {
896         mFd = null;
897         mFile = null;
898         mPath = path;
899     }
900 
901     /**
902      * Sets the next output file to be used when the maximum filesize is reached on the prior
903      * output {@link #setOutputFile} or {@link #setNextOutputFile}). File should be seekable.
904      * After setting the next output file, application should not use the file until {@link #stop}.
905      * Application must call this after receiving on the
906      * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
907      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
908      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
909      * that output. Application will receive {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
910      * when the next output file is used. Application will not be able to set a new output file if
911      * the previous one has not been used. Application is responsible for cleaning up unused files
912      * after {@link #stop} is called.
913      *
914      * @param  file The file to use.
915      * @throws IllegalStateException if it is called before prepare().
916      * @throws IOException if setNextOutputFile fails otherwise.
917      */
setNextOutputFile(File file)918     public void setNextOutputFile(File file) throws IOException
919     {
920         RandomAccessFile f = new RandomAccessFile(file, "rws");
921         try {
922             _setNextOutputFile(f.getFD());
923         } finally {
924             f.close();
925         }
926     }
927 
928     // native implementation
_setOutputFile(FileDescriptor fd)929     private native void _setOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
_setNextOutputFile(FileDescriptor fd)930     private native void _setNextOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
_prepare()931     private native void _prepare() throws IllegalStateException, IOException;
932 
933     /**
934      * Prepares the recorder to begin capturing and encoding data. This method
935      * must be called after setting up the desired audio and video sources,
936      * encoders, file format, etc., but before start().
937      *
938      * @throws IllegalStateException if it is called after
939      * start() or before setOutputFormat().
940      * @throws IOException if prepare fails otherwise.
941      */
prepare()942     public void prepare() throws IllegalStateException, IOException
943     {
944         if (mPath != null) {
945             RandomAccessFile file = new RandomAccessFile(mPath, "rws");
946             try {
947                 _setOutputFile(file.getFD());
948             } finally {
949                 file.close();
950             }
951         } else if (mFd != null) {
952             _setOutputFile(mFd);
953         } else if (mFile != null) {
954             RandomAccessFile file = new RandomAccessFile(mFile, "rws");
955             try {
956                 _setOutputFile(file.getFD());
957             } finally {
958                 file.close();
959             }
960         } else {
961             throw new IOException("No valid output file");
962         }
963 
964         _prepare();
965     }
966 
967     /**
968      * Begins capturing and encoding data to the file specified with
969      * setOutputFile(). Call this after prepare().
970      *
971      * <p>Since API level 13, if applications set a camera via
972      * {@link #setCamera(Camera)}, the apps can use the camera after this method
973      * call. The apps do not need to lock the camera again. However, if this
974      * method fails, the apps should still lock the camera back. The apps should
975      * not start another recording session during recording.
976      *
977      * @throws IllegalStateException if it is called before
978      * prepare() or when the camera is already in use by another app.
979      */
start()980     public native void start() throws IllegalStateException;
981 
982     /**
983      * Stops recording. Call this after start(). Once recording is stopped,
984      * you will have to configure it again as if it has just been constructed.
985      * Note that a RuntimeException is intentionally thrown to the
986      * application, if no valid audio/video data has been received when stop()
987      * is called. This happens if stop() is called immediately after
988      * start(). The failure lets the application take action accordingly to
989      * clean up the output file (delete the output file, for instance), since
990      * the output file is not properly constructed when this happens.
991      *
992      * @throws IllegalStateException if it is called before start()
993      */
stop()994     public native void stop() throws IllegalStateException;
995 
996     /**
997      * Pauses recording. Call this after start(). You may resume recording
998      * with resume() without reconfiguration, as opposed to stop(). It does
999      * nothing if the recording is already paused.
1000      *
1001      * When the recording is paused and resumed, the resulting output would
1002      * be as if nothing happend during paused period, immediately switching
1003      * to the resumed scene.
1004      *
1005      * @throws IllegalStateException if it is called before start() or after
1006      * stop()
1007      */
pause()1008     public native void pause() throws IllegalStateException;
1009 
1010     /**
1011      * Resumes recording. Call this after start(). It does nothing if the
1012      * recording is not paused.
1013      *
1014      * @throws IllegalStateException if it is called before start() or after
1015      * stop()
1016      * @see android.media.MediaRecorder#pause
1017      */
resume()1018     public native void resume() throws IllegalStateException;
1019 
1020     /**
1021      * Restarts the MediaRecorder to its idle state. After calling
1022      * this method, you will have to configure it again as if it had just been
1023      * constructed.
1024      */
reset()1025     public void reset() {
1026         native_reset();
1027 
1028         // make sure none of the listeners get called anymore
1029         mEventHandler.removeCallbacksAndMessages(null);
1030     }
1031 
native_reset()1032     private native void native_reset();
1033 
1034     /**
1035      * Returns the maximum absolute amplitude that was sampled since the last
1036      * call to this method. Call this only after the setAudioSource().
1037      *
1038      * @return the maximum absolute amplitude measured since the last call, or
1039      * 0 when called for the first time
1040      * @throws IllegalStateException if it is called before
1041      * the audio source has been set.
1042      */
getMaxAmplitude()1043     public native int getMaxAmplitude() throws IllegalStateException;
1044 
1045     /* Do not change this value without updating its counterpart
1046      * in include/media/mediarecorder.h or mediaplayer.h!
1047      */
1048     /** Unspecified media recorder error.
1049      * @see android.media.MediaRecorder.OnErrorListener
1050      */
1051     public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1;
1052     /** Media server died. In this case, the application must release the
1053      * MediaRecorder object and instantiate a new one.
1054      * @see android.media.MediaRecorder.OnErrorListener
1055      */
1056     public static final int MEDIA_ERROR_SERVER_DIED = 100;
1057 
1058     /**
1059      * Interface definition for a callback to be invoked when an error
1060      * occurs while recording.
1061      */
1062     public interface OnErrorListener
1063     {
1064         /**
1065          * Called when an error occurs while recording.
1066          *
1067          * @param mr the MediaRecorder that encountered the error
1068          * @param what    the type of error that has occurred:
1069          * <ul>
1070          * <li>{@link #MEDIA_RECORDER_ERROR_UNKNOWN}
1071          * <li>{@link #MEDIA_ERROR_SERVER_DIED}
1072          * </ul>
1073          * @param extra   an extra code, specific to the error type
1074          */
onError(MediaRecorder mr, int what, int extra)1075         void onError(MediaRecorder mr, int what, int extra);
1076     }
1077 
1078     /**
1079      * Register a callback to be invoked when an error occurs while
1080      * recording.
1081      *
1082      * @param l the callback that will be run
1083      */
setOnErrorListener(OnErrorListener l)1084     public void setOnErrorListener(OnErrorListener l)
1085     {
1086         mOnErrorListener = l;
1087     }
1088 
1089     /* Do not change these values without updating their counterparts
1090      * in include/media/mediarecorder.h!
1091      */
1092     /** Unspecified media recorder info.
1093      * @see android.media.MediaRecorder.OnInfoListener
1094      */
1095     public static final int MEDIA_RECORDER_INFO_UNKNOWN              = 1;
1096     /** A maximum duration had been setup and has now been reached.
1097      * @see android.media.MediaRecorder.OnInfoListener
1098      */
1099     public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
1100     /** A maximum filesize had been setup and has now been reached.
1101      * Note: This event will not be sent if application already set
1102      * next output file through {@link #setNextOutputFile}.
1103      * @see android.media.MediaRecorder.OnInfoListener
1104      */
1105     public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801;
1106     /** A maximum filesize had been setup and current recorded file size
1107      * has reached 90% of the limit. This is sent once per file upon
1108      * reaching/passing the 90% limit. To continue the recording, applicaiton
1109      * should use {@link #setNextOutputFile} to set the next output file.
1110      * Otherwise, recording will stop when reaching maximum file size.
1111      * @see android.media.MediaRecorder.OnInfoListener
1112      */
1113     public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING = 802;
1114     /** A maximum filesize had been reached and MediaRecorder has switched
1115      * output to a new file set by application {@link #setNextOutputFile}.
1116      * For best practice, application should use this event to keep track
1117      * of whether the file previously set has been used or not.
1118      * @see android.media.MediaRecorder.OnInfoListener
1119      */
1120     public static final int MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED = 803;
1121 
1122     /** informational events for individual tracks, for testing purpose.
1123      * The track informational event usually contains two parts in the ext1
1124      * arg of the onInfo() callback: bit 31-28 contains the track id; and
1125      * the rest of the 28 bits contains the informational event defined here.
1126      * For example, ext1 = (1 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the
1127      * track id is 1 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE;
1128      * while ext1 = (0 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the track
1129      * id is 0 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE. The
1130      * application should extract the track id and the type of informational
1131      * event from ext1, accordingly.
1132      *
1133      * FIXME:
1134      * Please update the comment for onInfo also when these
1135      * events are unhidden so that application knows how to extract the track
1136      * id and the informational event type from onInfo callback.
1137      *
1138      * {@hide}
1139      */
1140     public static final int MEDIA_RECORDER_TRACK_INFO_LIST_START        = 1000;
1141     /** Signal the completion of the track for the recording session.
1142      * {@hide}
1143      */
1144     public static final int MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000;
1145     /** Indicate the recording progress in time (ms) during recording.
1146      * {@hide}
1147      */
1148     public static final int MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME  = 1001;
1149     /** Indicate the track type: 0 for Audio and 1 for Video.
1150      * {@hide}
1151      */
1152     public static final int MEDIA_RECORDER_TRACK_INFO_TYPE              = 1002;
1153     /** Provide the track duration information.
1154      * {@hide}
1155      */
1156     public static final int MEDIA_RECORDER_TRACK_INFO_DURATION_MS       = 1003;
1157     /** Provide the max chunk duration in time (ms) for the given track.
1158      * {@hide}
1159      */
1160     public static final int MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS  = 1004;
1161     /** Provide the total number of recordd frames.
1162      * {@hide}
1163      */
1164     public static final int MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES    = 1005;
1165     /** Provide the max spacing between neighboring chunks for the given track.
1166      * {@hide}
1167      */
1168     public static final int MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS    = 1006;
1169     /** Provide the elapsed time measuring from the start of the recording
1170      * till the first output frame of the given track is received, excluding
1171      * any intentional start time offset of a recording session for the
1172      * purpose of eliminating the recording sound in the recorded file.
1173      * {@hide}
1174      */
1175     public static final int MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS  = 1007;
1176     /** Provide the start time difference (delay) betweeen this track and
1177      * the start of the movie.
1178      * {@hide}
1179      */
1180     public static final int MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS   = 1008;
1181     /** Provide the total number of data (in kilo-bytes) encoded.
1182      * {@hide}
1183      */
1184     public static final int MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES       = 1009;
1185     /**
1186      * {@hide}
1187      */
1188     public static final int MEDIA_RECORDER_TRACK_INFO_LIST_END          = 2000;
1189 
1190 
1191     /**
1192      * Interface definition of a callback to be invoked to communicate some
1193      * info and/or warning about the recording.
1194      */
1195     public interface OnInfoListener
1196     {
1197         /**
1198          * Called to indicate an info or a warning during recording.
1199          *
1200          * @param mr   the MediaRecorder the info pertains to
1201          * @param what the type of info or warning that has occurred
1202          * <ul>
1203          * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN}
1204          * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
1205          * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
1206          * </ul>
1207          * @param extra   an extra code, specific to the info type
1208          */
onInfo(MediaRecorder mr, int what, int extra)1209         void onInfo(MediaRecorder mr, int what, int extra);
1210     }
1211 
1212     /**
1213      * Register a callback to be invoked when an informational event occurs while
1214      * recording.
1215      *
1216      * @param listener the callback that will be run
1217      */
setOnInfoListener(OnInfoListener listener)1218     public void setOnInfoListener(OnInfoListener listener)
1219     {
1220         mOnInfoListener = listener;
1221     }
1222 
1223     private class EventHandler extends Handler
1224     {
1225         private MediaRecorder mMediaRecorder;
1226 
EventHandler(MediaRecorder mr, Looper looper)1227         public EventHandler(MediaRecorder mr, Looper looper) {
1228             super(looper);
1229             mMediaRecorder = mr;
1230         }
1231 
1232         /* Do not change these values without updating their counterparts
1233          * in include/media/mediarecorder.h!
1234          */
1235         private static final int MEDIA_RECORDER_EVENT_LIST_START = 1;
1236         private static final int MEDIA_RECORDER_EVENT_ERROR      = 1;
1237         private static final int MEDIA_RECORDER_EVENT_INFO       = 2;
1238         private static final int MEDIA_RECORDER_EVENT_LIST_END   = 99;
1239 
1240         /* Events related to individual tracks */
1241         private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100;
1242         private static final int MEDIA_RECORDER_TRACK_EVENT_ERROR      = 100;
1243         private static final int MEDIA_RECORDER_TRACK_EVENT_INFO       = 101;
1244         private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_END   = 1000;
1245 
1246 
1247         @Override
handleMessage(Message msg)1248         public void handleMessage(Message msg) {
1249             if (mMediaRecorder.mNativeContext == 0) {
1250                 Log.w(TAG, "mediarecorder went away with unhandled events");
1251                 return;
1252             }
1253             switch(msg.what) {
1254             case MEDIA_RECORDER_EVENT_ERROR:
1255             case MEDIA_RECORDER_TRACK_EVENT_ERROR:
1256                 if (mOnErrorListener != null)
1257                     mOnErrorListener.onError(mMediaRecorder, msg.arg1, msg.arg2);
1258 
1259                 return;
1260 
1261             case MEDIA_RECORDER_EVENT_INFO:
1262             case MEDIA_RECORDER_TRACK_EVENT_INFO:
1263                 if (mOnInfoListener != null)
1264                     mOnInfoListener.onInfo(mMediaRecorder, msg.arg1, msg.arg2);
1265 
1266                 return;
1267 
1268             default:
1269                 Log.e(TAG, "Unknown message type " + msg.what);
1270                 return;
1271             }
1272         }
1273     }
1274 
1275     /**
1276      * Called from native code when an interesting event happens.  This method
1277      * just uses the EventHandler system to post the event back to the main app thread.
1278      * We use a weak reference to the original MediaRecorder object so that the native
1279      * code is safe from the object disappearing from underneath it.  (This is
1280      * the cookie passed to native_setup().)
1281      */
postEventFromNative(Object mediarecorder_ref, int what, int arg1, int arg2, Object obj)1282     private static void postEventFromNative(Object mediarecorder_ref,
1283                                             int what, int arg1, int arg2, Object obj)
1284     {
1285         MediaRecorder mr = (MediaRecorder)((WeakReference)mediarecorder_ref).get();
1286         if (mr == null) {
1287             return;
1288         }
1289 
1290         if (mr.mEventHandler != null) {
1291             Message m = mr.mEventHandler.obtainMessage(what, arg1, arg2, obj);
1292             mr.mEventHandler.sendMessage(m);
1293         }
1294     }
1295 
1296     /**
1297      * Releases resources associated with this MediaRecorder object.
1298      * It is good practice to call this method when you're done
1299      * using the MediaRecorder. In particular, whenever an Activity
1300      * of an application is paused (its onPause() method is called),
1301      * or stopped (its onStop() method is called), this method should be
1302      * invoked to release the MediaRecorder object, unless the application
1303      * has a special need to keep the object around. In addition to
1304      * unnecessary resources (such as memory and instances of codecs)
1305      * being held, failure to call this method immediately if a
1306      * MediaRecorder object is no longer needed may also lead to
1307      * continuous battery consumption for mobile devices, and recording
1308      * failure for other applications if no multiple instances of the
1309      * same codec are supported on a device. Even if multiple instances
1310      * of the same codec are supported, some performance degradation
1311      * may be expected when unnecessary multiple instances are used
1312      * at the same time.
1313      */
release()1314     public native void release();
1315 
native_init()1316     private static native final void native_init();
1317 
native_setup(Object mediarecorder_this, String clientName, String opPackageName)1318     private native final void native_setup(Object mediarecorder_this,
1319             String clientName, String opPackageName) throws IllegalStateException;
1320 
native_finalize()1321     private native final void native_finalize();
1322 
setParameter(String nameValuePair)1323     private native void setParameter(String nameValuePair);
1324 
1325     /**
1326      *  Return Metrics data about the current Mediarecorder instance.
1327      *
1328      * @return a {@link PersistableBundle} containing the set of attributes and values
1329      * available for the media being generated by this instance of
1330      * MediaRecorder.
1331      * The attributes are descibed in {@link MetricsConstants}.
1332      *
1333      *  Additional vendor-specific fields may also be present in
1334      *  the return value.
1335      */
getMetrics()1336     public PersistableBundle getMetrics() {
1337         PersistableBundle bundle = native_getMetrics();
1338         return bundle;
1339     }
1340 
native_getMetrics()1341     private native PersistableBundle native_getMetrics();
1342 
1343     @Override
finalize()1344     protected void finalize() { native_finalize(); }
1345 
1346     public final static class MetricsConstants
1347     {
MetricsConstants()1348         private MetricsConstants() {}
1349 
1350         /**
1351          * Key to extract the audio bitrate
1352          * from the {@link MediaRecorder#getMetrics} return.
1353          * The value is an integer.
1354          */
1355         public static final String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
1356 
1357         /**
1358          * Key to extract the number of audio channels
1359          * from the {@link MediaRecorder#getMetrics} return.
1360          * The value is an integer.
1361          */
1362         public static final String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
1363 
1364         /**
1365          * Key to extract the audio samplerate
1366          * from the {@link MediaRecorder#getMetrics} return.
1367          * The value is an integer.
1368          */
1369         public static final String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
1370 
1371         /**
1372          * Key to extract the audio timescale
1373          * from the {@link MediaRecorder#getMetrics} return.
1374          * The value is an integer.
1375          */
1376         public static final String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
1377 
1378         /**
1379          * Key to extract the video capture frame rate
1380          * from the {@link MediaRecorder#getMetrics} return.
1381          * The value is a double.
1382          */
1383         public static final String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
1384 
1385         /**
1386          * Key to extract the video capture framerate enable value
1387          * from the {@link MediaRecorder#getMetrics} return.
1388          * The value is an integer.
1389          */
1390         public static final String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
1391 
1392         /**
1393          * Key to extract the intended playback frame rate
1394          * from the {@link MediaRecorder#getMetrics} return.
1395          * The value is an integer.
1396          */
1397         public static final String FRAMERATE = "android.media.mediarecorder.frame-rate";
1398 
1399         /**
1400          * Key to extract the height (in pixels) of the captured video
1401          * from the {@link MediaRecorder#getMetrics} return.
1402          * The value is an integer.
1403          */
1404         public static final String HEIGHT = "android.media.mediarecorder.height";
1405 
1406         /**
1407          * Key to extract the recorded movies time units
1408          * from the {@link MediaRecorder#getMetrics} return.
1409          * The value is an integer.
1410          * A value of 1000 indicates that the movie's timing is in milliseconds.
1411          */
1412         public static final String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
1413 
1414         /**
1415          * Key to extract the rotation (in degrees) to properly orient the video
1416          * from the {@link MediaRecorder#getMetrics} return.
1417          * The value is an integer.
1418          */
1419         public static final String ROTATION = "android.media.mediarecorder.rotation";
1420 
1421         /**
1422          * Key to extract the video bitrate from being used
1423          * from the {@link MediaRecorder#getMetrics} return.
1424          * The value is an integer.
1425          */
1426         public static final String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
1427 
1428         /**
1429          * Key to extract the value for how often video iframes are generated
1430          * from the {@link MediaRecorder#getMetrics} return.
1431          * The value is an integer.
1432          */
1433         public static final String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
1434 
1435         /**
1436          * Key to extract the video encoding level
1437          * from the {@link MediaRecorder#getMetrics} return.
1438          * The value is an integer.
1439          */
1440         public static final String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
1441 
1442         /**
1443          * Key to extract the video encoding profile
1444          * from the {@link MediaRecorder#getMetrics} return.
1445          * The value is an integer.
1446          */
1447         public static final String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
1448 
1449         /**
1450          * Key to extract the recorded video time units
1451          * from the {@link MediaRecorder#getMetrics} return.
1452          * The value is an integer.
1453          * A value of 1000 indicates that the video's timing is in milliseconds.
1454          */
1455         public static final String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
1456 
1457         /**
1458          * Key to extract the width (in pixels) of the captured video
1459          * from the {@link MediaRecorder#getMetrics} return.
1460          * The value is an integer.
1461          */
1462         public static final String WIDTH = "android.media.mediarecorder.width";
1463 
1464     }
1465 }
1466 
1467