1. Concepts and extensions
Videoview is a media playback display and Control control provided by the Android system. Its structure is as follows:
Prototype: videoview extendsSurfaceview ImplementsMediacontroller.Mediaplayercontrol
Class Structure:
Java. Lang. Object
Using Android. View. View
Using Android. View. surfaceview
Using Android. widget. videoview
Based on the videoview prototype, we can see that if you build a more complex and distinctive Video View,Surfaceview must be inherited and mediaplayercontrol interfaces must be implemented..WhereSurfaceviewSupports display, while mediaplayercontrol supports media control.
2. Case studies
1) videoview case
(We have not managedMediapalyerAll of these statuses makeVideoviewAnd whenVideoviewAt the time of creation,MediapalyerThe object will be created whenVideoviewWhen the object is destroyed, the mediaplayer object is released.)
Layout File
<? 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" >
< Videoview Android: ID = "@ + ID/video_view" Android: layout_width = "Match_parent" Android: layout_height = "Match_parent"
Android: layout_centerinparent = "True" />
</ Linearlayout >
MasterProgram:
Public Class Videoplayer Extends Activity Implements Mediaplayer. onerrorlistener, mediaplayer. oncompletionlistener {
Public Static Final String tag = "videoplayer ";
Private Videoview mvideoview;
Private Uri muri;
Private Int Mpositionwhenpaused =-1;
Private Mediacontroller mmediacontroller;
@ Override
Public Void Oncreate (bundle savedinstancestate ){
Super . Oncreate (savedinstancestate );
Setcontentview (R. layout. Main );
// Set the screen to landscape.
This . Setrequestedorientation (activityinfo. screen_orientation_landscape );
Mvideoview = (videoview) findviewbyid (R. Id. video_view );
// Video file
Muri = URI. parse (environment. getexternalstoragedirectory () + "/1.3gp ");
// Create media controller,The widget can control video playback, pause, reply, seek, and other operations.
Mmediacontroller = New Mediacontroller ( This );
Mvideoview. setmediacontroller (mmediacontroller );
}
Public Void Onstart (){
// Play video
Mvideoview. setvideouri (muri );
Mvideoview. Start ();
Super . Onstart ();
}
Public Void Onpause (){
// Stop video when the activity is pause.
Mpositionwhenpaused = mvideoview. getcurrentposition ();
Mvideoview. stopplayback ();
Super . Onpause ();
}
Public Void Onresume (){
// Resume Video Player
If (Mpositionwhenpaused> = 0 ){
Mvideoview. seekto (mpositionwhenpaused );
Mpositionwhenpaused =-1;
}
Super . Onresume ();
}
Public Boolean Onerror (mediaplayer player, Int Arg1, Int Arg2 ){
Return False ;
}
Public Void Oncompletion (mediaplayer MP ){
This . Finish ();
}
}
2)Custom videoview
Similar to videoview implementation, surfaceview is inherited and mediaplayercontrol is implemented.
Public Class Customervideoview Extends SurfaceviewImplements
Mediaplayercontrol {
Private Static String tag = "customer. videoplayer ";
Private Boolean Pause;
Private Boolean Seekbackward;
Private Boolean Seekforward;
Private Uri videouri;
Private Mediaplayer;
Private Context context;
Private Onpreparedlistener;
Private Int Videowidth;
Private Int Videoheight;
Private Mediacontroller;
Protected Surfaceholder;
Private Callback surfaceholdercallback =New Surfaceholder. Callback (){
Public Void Surfacechanged (surfaceholder holder, Int Format, Int W,
Int H ){
}
Public Void Surfacecreated (surfaceholder holder ){
Surfaceholder = holder;
If (Mediaplayer! = Null ){
Mediaplayer. setdisplay (surfaceholder );
Resume ();
} Else {
Openvideo ();
}
}
Public Void Surfacedestroyed (surfaceholder holder ){
Surfaceholder = Null ;
If (Mediacontroller! = Null ){
Mediacontroller. Hide ();
}
Release ( True );
}
};
Private Void Release ( Boolean Cleartargetstate ){
If (Mediaplayer! = Null ){
Mediaplayer. Reset ();
Mediaplayer. Release ();
Mediaplayer = Null ;
}
}
Public Void Resume (){
If (Surfaceholder = Null ){
Return ;
}
If (Mediaplayer! = Null ){
Return ;
}
Openvideo ();
}
Public Customervideoview (context, attributeset attrs, Int Defstyle ){
Super (Context, attrs, defstyle );
This . Context = context;
This . Initvideoview ();
}
Public Customervideoview (context, attributeset attrs ){
Super (Context, attrs );
This . Context = context;
This . Initvideoview ();
}
Public Customervideoview (context ){
Super (Context );
This . Context = context;
This . Initvideoview ();
}
@ Override
Public Boolean Canpause (){
Return This . Pause;
}
@ Override
Public Boolean Canseekbackward (){
Return This . Seekbackward;
}
@ Override
Public Boolean Canseekforward (){
Return This . Seekforward;
}
@ Override
Public Int Getbufferpercentage (){
Return 0;
}
@ Override
Public Int Getcurrentposition (){
Return Mediaplayer! = Null ? Mediaplayer. getcurrentposition (): 0;
}
@ Override
Public Int Getduration (){
Return Mediaplayer! = Null ? Mediaplayer. getduration (): 0;
}
@ Override
Public Boolean Isplaying (){
Return False ;
}
@ Override
Public Void Pause (){
}
@ Override
Public Void Seekto ( Int MSEC ){
}
@ Override
Public Void Start (){
}
Public Void Setvideouri (URI ){
This . Videouri = URI;
Openvideo ();
Requestlayout ();
Invalidate ();
}
Private Void Openvideo (){
This . Mediaplayer = New Mediaplayer ();
Try {
This . Mediaplayer. setdatasource ( This . Context, This . Videouri );
} Catch (Exception e ){
Log. E (TAG, E. getmessage ());
Throw New Runtimeexception (E );
}
This . Mediaplayer. prepareasync ();
This . Mediaplayer. setaudiostreamtype (audiomanager. stream_music );
This . Mediaplayer. setonpreparedlistener (onpreparedlistener );
Attachmediacontroller ();
}
Private Void Attachmediacontroller (){
If (Mediaplayer! = Null & Mediacontroller! = Null ){
Mediacontroller. setmediaplayer ( This );
View anchorview = This . Getparent () Instanceof View? (View) This
. Getparent (): This ;
Mediacontroller. setanchorview (anchorview );
Mediacontroller. setenabled ( True );
}
}
Public Void Setmediacontroller (mediacontroller Controller ){
If (Mediacontroller! = Null ){
Mediacontroller. Hide ();
}
Mediacontroller = controller;
Attachmediacontroller ();
}
Public Void Setonpreparedlistener (onpreparedlistener ){
This . Onpreparedlistener = onpreparedlistener;
}
@ Override
Protected Void Onmeasure ( Int Widthmeasurespec, Int Heightmeasurespec ){
Int Width = getdefaultsize (videowidth, widthmeasurespec );
Int Height = getdefaultsize (videoheight, heightmeasurespec );
If (Videowidth> 0 & videoheight> 0 ){
If (Videowidth * Height> width * videoheight ){
Height = width * videoheight/videowidth;
} Else If (Videowidth * height <width * videoheight ){
Width = height * videowidth/videoheight;
}
}
Log. I (TAG, "setting size:" + width + 'X' + height );
Setmeasureddimension (width, height );
}
Private Void Initvideoview (){
Videowidth = 0;
Videoheight = 0;
Getholder (). addcallback (surfaceholdercallback );
Getholder (). settype (surfaceholder. surface_type_push_buffers );
Setfocusable ( True );
Setfocusableintouchmode ( True );
Requestfocus ();
}
}
Generally, the rendering and updating of the android interface must be performed by the main UI thread through the handler mechanism. However, to play a video, you must first change and draw the page in real time. Android provides a mechanism to draw the UI using a separate thread, that is, surfaceview.To use surfaceview, you must implement the surfaceholder. Callback interface:
- Surfacecreated: After the surface (surfaceview contains a surface instance) is created, this method is called immediately. You can initialize the interface in this method;
- Surfacechanged: when the surface status changes, such as the size, this method is called. This method is called at least once in the surfacecreated method;
- Surfacedestroyed, called when the surface is destroyed.
You cannot directly operate a surface instance. You must use surfacehandler to obtain the surfacehandler instance through the gethandler method in surfaceview.
Surfacehander has some types used to identify the data source on the surface instance interface. You can use settype to perform the following operations:
- Surface_type_normal: Native data cached by Ram
- Surface_type_hardware: the data obtained through DMA and direct memory access is the data obtained through direct Screen Writing Technology, or data accelerated by other hardware.
- Surface_type_gpu: GPU-Accelerated Data
- Surface_type_push_buffers: identifies data from other objects, such as cameras, such as video playback servers (servers with video playback in Android, all playing videos are equivalent to clients)
The constructor of customervideoview, which uses the constructor of the superclass. The initvideoview () method is executed to initialize the interface and parameters.Another major content is the openvideo () method:
- mediaplayer. prepareasync () is used to prepare for playing asynchronously. In addition, there is a prepare () method, which is synchronous, that is, it can only be played after all the downloads are completed. Obviously, use the former when playing online videos.
- the attachmediacontroller () method is used to append the control bar to the surfaceview of the video to be played. This method is not completely implemented and therefore cannot be used. You only need to set the mediaplayercontrol instance through the setmediaplayer method, onpreparedlistener is used to get the callback for successful loading, and Code is used to call the video to get the video length and current time length.