android 播放视频代码
Android开发—SeeJoPlayer视频播放器源码解析
2020.03.27 v1.2.0 beta版:更新说明:一、完美支持android1.五、android1.六、android2.0、android2.0一、android2.1平台;2、完美支持320×480、480×800、480×854等各类分辨率(自适应屏幕分辨率);3、支持在线音视频播放,支持URL input和从浏览器调用SeeJoPlayer播放器播放在线音视频;4、自动转为横屏播放,为用户提供更好的观看体验;5、修改了没有SD卡程序出错的Bug;6、美化了视频播放列表和操作说明的界面。
第一部份:功能介绍SeeJoPlayer的优势要紧在相对还算美观的界面和便利的交互操作上。
先说操作吧,它支持:一、全屏切换: 双击屏幕二、播放/暂停: 长按屏幕3、静音/恢复: 长按音量按钮4、播放列表: 操纵面板最右边的按钮(暂不支持编辑功能)五、音量调剂: 单击音量按钮,在弹出的音量显示区域触摸改变音量这些操作和PC上的播放器较为类似,希望大伙儿能用得适应。
至于界面的话,多说无益,直接上图吧:第二部份:源码解析一、VideoView与视频比例缩放:咱们能够很方便的取得VideoView的源代码,最简单的方式是直接在上找“.java”。
因此重写VideoView的进程其实只是在原先的基础上进行一些修改罢了,并非一个很麻烦的工作。
什么缘故Android自带的VideoView会维持视频的长宽比而不能让咱们很方便的自概念比例呢?我猜想可能Google 做Android也是一个很仓促的工程,许多代码并无考虑得太成熟。
VideoView的源码中有如此一段代码:1 @Override2 3 4 5 6 7 8 9101112131415161718192021222324252627protectedvoid onMeasure(int widthMeasureSpec, int heightMeasureSpec){//Log.i("@@@@", "onMeasure");int width = getDefaultSize(mVideoWidth, widthMeasureSpec);int height = getDefaultSize(mVideoHeight, heightMeasureSpec);if(mVideoWidth >0&& mVideoHeight >0){if( mVideoWidth * height > width * mVideoHeight ){//Log.i("@@@", "image too tall, correcting");height = width * mVideoHeight / mVideoWidth;}elseif( mVideoWidth * height < width * mVideoHeight ){//Log.i("@@@", "image too wide, correcting");width = height * mVideoWidth / mVideoHeight;}else{//Log.i("@@@", "aspect ratio is correct: " +//width+"/"+height+"="+//mVideoWidth+"/"+mVideoHeight);}}//Log.i("@@@@@@@@@@", "setting size: " + width + 'x' + height); setMeasuredDimension(width, height);}这确实是什么缘故长宽比不能改变的缘故了。
Android移动应用开发案例教程(模块五 实现视频播放)
}
思路: 在GestureDetector中监听onScroll(),判断手势按下点在屏幕的左侧还是右侧,如果 <screenWidth/2说明在左测按下;记录用户移动手指的距离;根据屏幕的总宽度、总音量 和滑动的距离计算声音应该改变的多少;音量改变后的值mvol+delta、音量最大值 maxVolume、音量最小值0做比较,最后取三者之一voice;将声音SeekBar调整到合适的 位置,将音量调整为voice。
核心代码:
public boolean onDoubleTap(MotionEvent e) { if(FULLSCREEN){ portrait(); FULLSCREEN=false; } else{ landscape(); FULLSCREEN=true; } return super.onDoubleTap(e);
this, new GestureDetector.OnGestureListener() {
public void onLongPress(MotionEvent e) { playAndPause();
} );
思路: 为VideoView控件注册手势监听onTouchListener; 再自定义手势监听GestureDetector类的对象,监听onLongPress(),调用视频播放/暂停的 方法; 在onTouchListener中编写手势事件监听转移detector.onTouchEvent(event)。
android编程调用mediaplayer播放器
mediaplayer的生命周期.1. 当mediaplayer被new出来的时候处于idle状态.(空闲状态)mediaPlayer.reset()之前:可以设置错误的监听器.2. setDataSource() 设置数据源. 初始化完毕.3. prepare() 准备开始播放视频或者音频.HDprepareAsync() 异步准备.4. start() 开始播放介绍:这款播放器是基于FMpeg音视频解码库的Vitamio框架和系统的MediaPlayer结合的方式开发的,支持flv、rmvb、mkv、mov、avi、mp4等多种视频格式,mp3、ogg、wma、mid、m4a等多种音频格式,实现了网络视频和本地视频播放,网络音频和本地音频的播放等功能。
技术:软解码和硬解码的使用,json解析服务端数据,采用Popuwindow显示播放控制器播放流程:视频播放器(网络视频,本地视频),音频播放器(网络音频,本地音频)Andoid默认支持视频格式是:mp4,3gp,wmvAndoid默认支持音频格式是:mp3,ogg播放原则:先用系统播放器去播放,当系统播放器播放出错的时候,切换到Vitamio播放器;我已经知道系统播放器播放不了的,直接用Vitamio播放器(支持在线视频,可以从Youku,或酷六客户端调用我们的播放器进来播放)用到了getIntent().getData(); 这个负责得到Url,当然还有单独的播放方法根据这URL地址去播放,但别忘了要功能清单文件里注明<data android:mimeType="video/*" android:scheme="http"/>网络视频<data android:mimeType="video/*" android:scheme="file"/>本地视频<data android:mimeType="audio/*" android:scheme="http"/>网络音频<data android:mimeType="audio/*" android:scheme="file"/>本地音频界面:加载控制视频界面的是一个PopupWindow,作为一种用户提醒而且其开销也比activity 要小,实现了播放,暂停,上一个(后退),下一个(判断一下是否是文件列表,如果是就播放下一个视频否则就快进),声音控制(0-15),自定义一个类控制PopupWindow显示和隐藏的,设置6秒隐藏,用到了handlerMessage消息机制,做了一个方法,6s中之后发一个消息,调用隐藏控制面板的方法硬解码和软解码的大概原理:硬解码:所谓的硬解码就是用系统的接口实现的播放器,那么就可以叫做用硬解码。
android 播放视频代码
android 播放视频播放视频的两种方式:使用VideoView播放视频(方便,推荐)使用MediaPlayer和SurfaceView播放视频(早期的方式)第一种方式:使用VideoView播放视频的步骤如下:在界面布局文件中定义VideoView组件,或在程序中创建VideoView组建调用VideoView的如下两个方法加载指定视频setVideoPath(String paht):加载path文件所代表的视频setVideoURI(URI uri):加载uri所对应的视频调用VideoVIew的start(),stop(),pause()方法来控制视频播放MediaContraller类与VideoView一起结合使用的还有一个MediaContraller类,它的作用时提供一个友好的图形控制界面,通过该控制界面来控制视频的播放,快进键,暂停键,后退键以及播放进度条都是该类提供例子代码:xml布局:?<!--?xml version="1.0"encoding="utf-8"?-->1<linearlayout2 3 4 5 xmlns:android="/apk/res/android "android:ori entation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 定义VideoView 播放视频 --><videoviewandroid:id="@+id/video"android:layout_width="match_parent"android:lay out_height="match_parent"></videoview></linearlayout>Activity : ?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 importjava.io.File;importandroid.app.Activity;importandroid.graphics.PixelFormat;importandroid.os.Bundle;importandroid.widget.MediaController;importandroid.widget.VideoView;publicclassVedioViewTestextendsActivity {VideoView videoView;MediaController mController;@OverridepublicvoidonCreate(Bundle savedInstanceState) {16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 super.onCreate(savedInstanceState);getWindow().setFormat(PixelFormat.TRANSLUCENT);setContentView(yout.main);// 获取界面上VideoView 组件videoView = (VideoView) findViewById(R.id.video);// 创建MediaController 对象mController =newMediaController(this);File video =newFile("/mnt/sdcard/movie.mp4");if(video.exists()) {videoView.setVideoPath(video.getAbsolutePath());//① // 设置videoView 与mController 建立关联videoView.setMediaController(mControl ler);//② // 设置mController 与videoView 建立关联mController.setMediaPlayer(videoView);//③// 让VideoView 获取焦点videoView.requestFocus();}}}第二种方式:使用MediaPlayer 播放视频的步骤如下:创建MediaPlayer 对象,并让它加载指定的视频文件在界面布局文件中定义SurfaceView 组件,或在程序中创建SurfaceView 组件,并为SurfaceView 的SurfaceView 的SurfaceHolder 增加Callback 监听器调用 MediaPlayer 对象的setPisplay(SurfaceHolder sh):将所播放的视频图像输出到指定的SurfaceView 组件调用MediaPlayer 对象的start(),stop(),和pause()方法来控制视频的播放例子代码:xml 布局: ?1234 56 78 9<!--?xml version="1.0"encoding="utf-8"?--><relativelayoutxmlns:android="/apk/res/android "android:ori entation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><surfaceview android:id="@+id/surfaceView"android:layout_width="match_parent"andro id:layout_height="360dp"> <linearlayout android:orientation="horizontal"android:layout_width="match_parent"an droid:layout_height="wrap_content"android:layout_alignparentbottom="t rue"android:gravity="center_horizontal"><imagebuttonandroid:id="@+id/play"android:layout_width="wrap_content"android:layo ut_height="wrap_content"android:src="@drawable/play"><imagebuttonandroid:id="@+id/pause"android:layout_width="wrap_content"android:lay out_height="wrap_content"android:src="@drawable/pause"> <imagebuttonandroid:id="@+id/stop"android:layout_width="wrap_content"android:layo ut_height="wrap_content"android:src="@drawable/stop"></imagebutton></imagebutton></imagebutton></linearlayout></surfaceview></relativelayout>Activity :?1 2 3 4 5 6 7 8 910111213141516171819202122 importjava.io.IOException;importandroid.app.Activity;importandroid.media.AudioManager;importandroid.media.MediaPlayer;importandroid.os.Bundle;importandroid.util.DisplayMetrics; importandroid.view.SurfaceHolder;importandroid.view.SurfaceView;importandroid.view.View;importandroid.view.View.OnClickListener; importandroid.view.WindowManager;youtParams; importandroid.widget.ImageButton;publicclassSurfaceViewPlayVideoextendsActivityimplementsOnClickListener{SurfaceView surfaceView;ImageButton play, pause, stop;MediaPlayer mPlayer;// 记录当前视频的播放位置2324252627282930313233343536373839404142434445 intposition;@OverridepublicvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(yout.main);// 获取界面中的3个按钮play = (ImageButton) findViewById(R.id.play);pause = (ImageButton) findViewById(R.id.pause);stop = (ImageButton) findViewById(R.id.stop);// 为3个按钮的单击事件绑定事件监听器play.setOnClickListener(this);pause.setOnClickListener(this);stop.setOnClickListener(this);// 创建MediaPlayermPlayer =newMediaPlayer();surfaceView = (SurfaceView)this.findViewById(R.id.surfaceView);// 设置播放时打开屏幕surfaceView.getHolder().setKeepScreenOn(true);surfaceView.getHolder().addCallback(newSurfaceListener());}4647484950515253545556575859606162636465666768 @OverridepublicvoidonClick(View source){try{switch(source.getId()){// 播放按钮被单击caseR.id.play:play();break;// 暂停按钮被单击caseR.id.pause:if(mPlayer.isPlaying()) {mPlayer.pause();}else{mPlayer.start();}break;// 停止按钮被单击6970717273747576777879808182838485868788899091 caseR.id.stop:if(mPlayer.isPlaying()) mPlayer.stop();break;}}catch(Exception e){e.printStackTrace();}}privatevoidplay()throwsIOException{mPlayer.reset();mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); // 设置需要播放的视频mPlayer.setDataSource("/mnt/sdcard/movie.3gp");// 把视频画面输出到SurfaceViewmPlayer.setDisplay(surfaceView.getHolder()); //①mPlayer.prepare();// 获取窗口管理器WindowManager wManager = getWindowManager();DisplayMetrics metrics =newDisplayMetrics();92 93 94 95 96979899100101102103104105106107108109110111112113114// 获取屏幕大小wManager.getDefaultDisplay().getMetrics(metrics); // 设置视频保持纵横比缩放到占满整个屏幕surfaceView.setLayoutParams(newLayoutParams(metrics.widthPixels , mPlayer.getVideoHeight() * metrics.widthPixels / mPlayer.getVideoWidth()));mPlayer.start();}privateclassSurfaceListenerimplementsSurfaceHolder.Callback {@OverridepublicvoidsurfaceChanged(SurfaceHolder holder,intformat, intwidth,intheight){}@OverridepublicvoidsurfaceCreated(SurfaceHolder holder){if(position >0){try115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 {// 开始播放play();// 并直接从指定位置开始播放 mPlayer.seekTo(position);position =0;}catch(Exception e){e.printStackTrace();}}}@OverridepublicvoidsurfaceDestroyed(SurfaceHolder holder) {}}// 当其他Activity 被打开,暂停播放@OverrideprotectedvoidonPause()138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 {if(mPlayer.isPlaying()){// 保存当前的播放位置position = mPlayer.getCurrentPosition(); mPlayer.stop();}super.onPause();}@OverrideprotectedvoidonDestroy(){// 停止播放if(mPlayer.isPlaying()) mPlayer.stop(); // 释放资源mPlayer.release();super.onDestroy();}}。
Android视频播放器(二):使用MediaPlayer播放视频
Android视频播放器(⼆):使⽤MediaPlayer播放视频在我们讲了⼀下如何使⽤VideoView播放视频,了解了基本的播放器的⼀些知识和内容。
也知道VideoView内部封装的就是MediaPlayer,本⽂就介绍如何使⽤MediaPlayer播放视频。
⼀、简介MediaPlayer是Android中的⼀个多媒体播放类,其提供的API能满⾜简单的⼤部分⾳视频的播放需求。
下⾯简单介绍⼀下MediaPlayer:MediaPlayer是使⽤Surface进⾏视频的展⽰的。
MediaPlayer只⽀持mp4、avi、3gp格式的视频,⽀持格式相对单⼀。
MediaPlayer可以播放⽹络视频,⽀持的⽹络视频的协议为:Http协议和RTSP协议两种。
⼆、MediaPlayer 使⽤⽅法MediaPlayer 的提供的⽅法如下:void setDataSource(String path) :通过⼀个具体的路径来设置MediaPlayer的数据源,path可以是本地的⼀个路径,也可以是⼀个⽹络路径void setDataSource(Context context, Uri uri):通过给定的Uri来设置MediaPlayer的数据源,这⾥的Uri可以是⽹络路径或是⼀个ContentProvider的Uri。
void setDataSource(MediaDataSource dataSource) :通过提供的MediaDataSource来设置数据源void setDataSource(FileDescriptor fd):通过⽂件描述符FileDescriptor来设置数据源int getCurrentPosition() :获取当前播放的位置int getAudioSessionId() :返回⾳频的session IDint getDuration() :得到⽂件的时间TrackInfo[] getTrackInfo() :返回⼀个track信息的数组boolean isLooping ():是否循环播放boolean isPlaying():是否正在播放void pause () :暂停void start () :开始void stop () :停⽌void prepare():同步的⽅式装载流媒体⽂件。
Android本地视频播放器开发--SDL编译
Android本地视频播放器开发--SDL编译其实1.3以后的版本就添加了android的支持,所以下载完源码后,在SDL目录下创建一个jni的目录,然后将原先SDL目录下面的文件以及文件夹都拷贝到jni目录下面,在jni目录下面我们会看见一个android.mk的文件,这就是官方给我们编写的编译文件,由于手机基本上都是使用的arm编译器,所以我在里面添加了LOCAL_ARM_MODE=arm,模块的编译使用arm编译器来编译,具体的内容如下:[cpp] ############################# SDL shared library############################include $(CLEAR_VARS)LOCAL_MODULE := SDL2LOCAL_ARM_MODE=armLOCAL_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_SRC_FILES := \$(subst $(LOCAL_PATH)/,, \$(wil dcard $(LOCAL_PATH)/src/*.c) \$(wil dcard $(LOCAL_PATH)/src/audio/*.c) \$(wil dcard $(LOCAL_PATH)/src/audio/android/*.c) \$(wil dcard $(LOCAL_PATH)/src/audio/dummy/*.c) \$(LOCAL_PATH)/src/atomic/SDL_atomic.c \$(LOCAL_PATH)/src/atomic/SDL_spinl ock.c.arm \$(wil dcard $(LOCAL_PATH)/src/core/android/*.cpp) \$(wil dcard $(LOCAL_PATH)/src/cpuinfo/*.c) \$(wil dcard $(LOCAL_PATH)/src/events/*.c) \$(wil dcard $(LOCAL_PATH)/src/fil e/*.c) \$(wil dcard $(LOCAL_PATH)/src/haptic/*.c) \$(wil dcard $(LOCAL_PATH)/src/haptic/dummy/*.c) \$(wil dcard $(LOCAL_PATH)/src/joystick/*.c) \$(wil dcard $(LOCAL_PATH)/src/joystick/android/*.c) \$(wil dcard $(LOCAL_PATH)/src/l oadso/dl open/*.c) \ $(wil dcard $(LOCAL_PATH)/src/power/*.c) \ $(wil dcard $(LOCAL_PATH)/src/power/android/*.c) \ $(wil dcard $(LOCAL_PATH)/src/render/*.c) \ $(wil dcard $(LOCAL_PATH)/src/render/*/*.c) \ $(wil dcard $(LOCAL_PATH)/src/stdlib/*.c) \$(wil dcard $(LOCAL_PATH)/src/thread/*.c) \ $(wil dcard $(LOCAL_PATH)/src/thread/pthread/*.c) \ $(wil dcard $(LOCAL_PATH)/src/timer/*.c) \$(wil dcard $(LOCAL_PATH)/src/timer/unix/*.c) \ $(wil dcard $(LOCAL_PATH)/src/video/*.c) \$(wil dcard $(LOCAL_PATH)/src/video/android/*.c)) LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES LOCAL_LDLIBS := -l dl -lGLESv1_CM -lGLESv2 -ll og include $(BUILD_SHARED_LIBRARY)############################# SDL shared library############################include $(CLEAR_VARS)LOCAL_MODULE := SDL2LOCAL_ARM_MODE=armLOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_SRC_FILES := \$(subst $(LOCAL_PATH)/,, \$(wil dcard $(LOCAL_PATH)/src/*.c) \$(wil dcard $(LOCAL_PATH)/src/audio/*.c) \$(wil dcard $(LOCAL_PATH)/src/audio/android/*.c) \ $(wil dcard $(LOCAL_PATH)/src/audio/dummy/*.c) \ $(LOCAL_PATH)/src/atomic/SDL_atomic.c \$(LOCAL_PATH)/src/atomic/SDL_spinl ock.c.arm \$(wil dcard $(LOCAL_PATH)/src/core/android/*.cpp) \$(wil dcard $(LOCAL_PATH)/src/cpuinfo/*.c) \$(wil dcard $(LOCAL_PATH)/src/events/*.c) \$(wil dcard $(LOCAL_PATH)/src/fil e/*.c) \$(wil dcard $(LOCAL_PATH)/src/haptic/*.c) \$(wil dcard $(LOCAL_PATH)/src/haptic/dummy/*.c) \$(wil dcard $(LOCAL_PATH)/src/joystick/*.c) \$(wil dcard $(LOCAL_PATH)/src/joystick/android/*.c) \$(wil dcard $(LOCAL_PATH)/src/l oadso/dl open/*.c) \$(wil dcard $(LOCAL_PATH)/src/power/*.c) \$(wil dcard $(LOCAL_PATH)/src/power/android/*.c) \$(wil dcard $(LOCAL_PATH)/src/render/*.c) \$(wil dcard $(LOCAL_PATH)/src/render/*/*.c) \$(wil dcard $(LOCAL_PATH)/src/stdlib/*.c) \$(wil dcard $(LOCAL_PATH)/src/thread/*.c) \$(wil dcard $(LOCAL_PATH)/src/thread/pthread/*.c) \$(wil dcard $(LOCAL_PATH)/src/timer/*.c) \$(wil dcard $(LOCAL_PATH)/src/timer/unix/*.c) \$(wil dcard $(LOCAL_PATH)/src/video/*.c) \$(wil dcard $(LOCAL_PATH)/src/video/android/*.c))LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPESLOCAL_LDLIBS := -l dl -lGLESv1_CM -lGLESv2 -ll oginclude $(BUILD_SHARED_LIBRARY)三、如果直接编译的话会提示如下错误[cpp] /home/SDL/jni/src/core/android/SDL_android.cpp:30:21: fatal error: EGL/egl.h: No such fil e or directory/home/SDL/jni/src/core/android/SDL_android.cpp:30:21: fatal error: EGL/egl.h: No such fil e or directory查看EGL的支持是在2.3版本以上,所以我们需要添加平台的支持,所以需要在jni目录下面创建一个Application.mk文件来指定编译平台,内容如下:[cpp] APP_ABI := armeabiAPP_PLATFORM := android-9APP_ABI := armeabiAPP_PLATFORM := android-9四、在jni目录终端下运行ndk-buil d,就会编译出libSDL2.so,编译过程如下:[cpp] root@zhangjie:/home/SDL/jni# ndk-buil dCompil e arm : SDL2 <= SDL_assert.cCompil e arm : SDL2 <= SDL.cCompil e arm : SDL2 <= SDL_error.cCompil e arm : SDL2 <= SDL_fatal.cCompil e arm : SDL2 <= SDL_hints.cCompil e arm : SDL2 <= SDL_l og.cCompil e arm : SDL2 <= SDL_audio.cCompil e arm : SDL2 <= SDL_audiocvt.cCompil e arm : SDL2 <= SDL_audiodev.cCompil e arm : SDL2 <= SDL_audiotypecvt.cCompil e arm : SDL2 <= SDL_mixer.cCompil e arm : SDL2 <= SDL_wave.cCompil e arm : SDL2 <= SDL_androidaudio.cCompil e arm : SDL2 <= SDL_dummyaudio.cCompil e arm : SDL2 <= SDL_atomic.cCompil e arm : SDL2 <= SDL_spinl ock.cCompil e++ arm : SDL2 <= SDL_android.cppCompil e arm : SDL2 <= SDL_cpuinfo.cCompil e arm : SDL2 <= SDL_clipboard events.cCompil e arm : SDL2 <= SDL_dropevents.cCompil e arm : SDL2 <= SDL_events.cCompil e arm : SDL2 <= SDL_gesture.cCompil e arm : SDL2 <= SDL_keyboard.cCompil e arm : SDL2 <= SDL_mouse.cCompil e arm : SDL2 <= SDL_quit.cCompil e arm : SDL2 <= SDL_touch.cCompil e arm : SDL2 <= SDL_windowevents.cCompil e arm : SDL2 <= SDL_rwops.cCompil e arm : SDL2 <= SDL_haptic.c Compil e arm : SDL2 <= SDL_syshaptic.c Compil e arm : SDL2 <= SDL_gamecontroll er.c Compil e arm : SDL2 <= SDL_joystick.c Compil e arm : SDL2 <= SDL_sysjoystick.c Compil e arm : SDL2 <= SDL_sysl oadso.c Compil e arm : SDL2 <= SDL_power.c Compil e arm : SDL2 <= SDL_syspower.c Compil e arm : SDL2 <= SDL_render.c Compil e arm : SDL2 <= SDL_yuv_mmx.c Compil e arm : SDL2 <= SDL_yuv_sw.c Compil e arm : SDL2 <= SDL_render_d3d.c Compil e arm : SDL2 <= SDL_render_gl es2.c Compil e arm : SDL2 <= SDL_shaders_gl es2.c Compil e arm : SDL2 <= SDL_render_gl es.c Compil e arm : SDL2 <= SDL_render_gl.c Compil e arm : SDL2 <= SDL_shaders_gl.c Compil e arm : SDL2 <= SDL_render_psp.c Compil e arm : SDL2 <= SDL_bl endfillrect.c Compil e arm : SDL2 <= SDL_bl endline.c Compil e arm : SDL2 <= SDL_bl endpoint.c Compil e arm : SDL2 <= SDL_drawline.c Compil e arm : SDL2 <= SDL_drawpoint.c Compil e arm : SDL2 <= SDL_render_sw.c Compil e arm : SDL2 <= SDL_rotate.c Compil e arm : SDL2 <= SDL_getenv.c Compil e arm : SDL2 <= SDL_iconv.c Compil e arm : SDL2 <= SDL_mall oc.c Compil e arm : SDL2 <= SDL_qsort.c Compil e arm : SDL2 <= SDL_stdlib.c Compil e arm : SDL2 <= SDL_string.cCompil e arm : SDL2 <= SDL_thread.cCompil e arm : SDL2 <= SDL_syscond.c Compil e arm : SDL2 <= SDL_sysmutex.c Compil e arm : SDL2 <= SDL_syssem.c Compil e arm : SDL2 <= SDL_systhread.c Compil e arm : SDL2 <= SDL_timer.cCompil e arm : SDL2 <= SDL_systimer.c Compil e arm : SDL2 <= SDL_blit_0.cCompil e arm : SDL2 <= SDL_blit_1.cCompil e arm : SDL2 <= SDL_blit_A.cCompil e arm : SDL2 <= SDL_blit_auto.c Compil e arm : SDL2 <= SDL_blit.cCompil e arm : SDL2 <= SDL_blit_copy.c Compil e arm : SDL2 <= SDL_blit_N.cCompil e arm : SDL2 <= SDL_blit_sl ow.c Compil e arm : SDL2 <= SDL_bmp.cCompil e arm : SDL2 <= SDL_clipboard.c Compil e arm : SDL2 <= SDL_fillrect.cCompil e arm : SDL2 <= SDL_pixels.cCompil e arm : SDL2 <= SDL_rect.cCompil e arm : SDL2 <= SDL_RLEaccel.c Compil e arm : SDL2 <= SDL_shape.cCompil e arm : SDL2 <= SDL_stretch.cCompil e arm : SDL2 <= SDL_surface.c Compil e arm : SDL2 <= SDL_video.cCompil e arm : SDL2 <= SDL_androidclipboard.c Compil e arm : SDL2 <= SDL_android events.c Compil e arm : SDL2 <= SDL_androidgl.c Compil e arm : SDL2 <= SDL_androidkeyboard.c Compil e arm : SDL2 <= SDL_androidtouch.c Compil e arm : SDL2 <= SDL_androidvideo.cCompil e arm : SDL2 <= SDL_androidwind ow.c StaticLibrary : libstdc++.aSharedLibrary : libSDL2.soInstall : libSDL2.so => libs/armeabi/libSDL2.so root@zhangjie:/home/SDL/jni# ndk-buil dCompil e arm : SDL2 <= SDL_assert.cCompil e arm : SDL2 <= SDL.cCompil e arm : SDL2 <= SDL_error.cCompil e arm : SDL2 <= SDL_fatal.cCompil e arm : SDL2 <= SDL_hints.cCompil e arm : SDL2 <= SDL_l og.cCompil e arm : SDL2 <= SDL_audio.cCompil e arm : SDL2 <= SDL_audiocvt.cCompil e arm : SDL2 <= SDL_audiodev.cCompil e arm : SDL2 <= SDL_audiotypecvt.c Compil e arm : SDL2 <= SDL_mixer.cCompil e arm : SDL2 <= SDL_wave.cCompil e arm : SDL2 <= SDL_androidaudio.c Compil e arm : SDL2 <= SDL_dummyaudio.c Compil e arm : SDL2 <= SDL_atomic.cCompil e arm : SDL2 <= SDL_spinl ock.cCompil e++ arm : SDL2 <= SDL_android.cpp Compil e arm : SDL2 <= SDL_cpuinfo.cCompil e arm : SDL2 <= SDL_clipboard events.c Compil e arm : SDL2 <= SDL_dropevents.cCompil e arm : SDL2 <= SDL_events.cCompil e arm : SDL2 <= SDL_gesture.cCompil e arm : SDL2 <= SDL_keyboard.cCompil e arm : SDL2 <= SDL_mouse.cCompil e arm : SDL2 <= SDL_quit.cCompil e arm : SDL2 <= SDL_touch.cCompil e arm : SDL2 <= SDL_windowevents.c Compil e arm : SDL2 <= SDL_rwops.c Compil e arm : SDL2 <= SDL_haptic.c Compil e arm : SDL2 <= SDL_syshaptic.c Compil e arm : SDL2 <= SDL_gamecontroll er.c Compil e arm : SDL2 <= SDL_joystick.c Compil e arm : SDL2 <= SDL_sysjoystick.c Compil e arm : SDL2 <= SDL_sysl oadso.c Compil e arm : SDL2 <= SDL_power.c Compil e arm : SDL2 <= SDL_syspower.c Compil e arm : SDL2 <= SDL_render.c Compil e arm : SDL2 <= SDL_yuv_mmx.c Compil e arm : SDL2 <= SDL_yuv_sw.c Compil e arm : SDL2 <= SDL_render_d3d.c Compil e arm : SDL2 <= SDL_render_gl es2.c Compil e arm : SDL2 <= SDL_shaders_gl es2.c Compil e arm : SDL2 <= SDL_render_gl es.c Compil e arm : SDL2 <= SDL_render_gl.c Compil e arm : SDL2 <= SDL_shaders_gl.c Compil e arm : SDL2 <= SDL_render_psp.c Compil e arm : SDL2 <= SDL_bl endfillrect.c Compil e arm : SDL2 <= SDL_bl endline.c Compil e arm : SDL2 <= SDL_bl endpoint.c Compil e arm : SDL2 <= SDL_drawline.c Compil e arm : SDL2 <= SDL_drawpoint.c Compil e arm : SDL2 <= SDL_render_sw.c Compil e arm : SDL2 <= SDL_rotate.c Compil e arm : SDL2 <= SDL_getenv.c Compil e arm : SDL2 <= SDL_iconv.c Compil e arm : SDL2 <= SDL_mall oc.c Compil e arm : SDL2 <= SDL_qsort.cCompil e arm : SDL2 <= SDL_stdlib.cCompil e arm : SDL2 <= SDL_string.cCompil e arm : SDL2 <= SDL_thread.cCompil e arm : SDL2 <= SDL_syscond.c Compil e arm : SDL2 <= SDL_sysmutex.c Compil e arm : SDL2 <= SDL_syssem.c Compil e arm : SDL2 <= SDL_systhread.c Compil e arm : SDL2 <= SDL_timer.cCompil e arm : SDL2 <= SDL_systimer.c Compil e arm : SDL2 <= SDL_blit_0.cCompil e arm : SDL2 <= SDL_blit_1.cCompil e arm : SDL2 <= SDL_blit_A.cCompil e arm : SDL2 <= SDL_blit_auto.c Compil e arm : SDL2 <= SDL_blit.cCompil e arm : SDL2 <= SDL_blit_copy.c Compil e arm : SDL2 <= SDL_blit_N.cCompil e arm : SDL2 <= SDL_blit_sl ow.c Compil e arm : SDL2 <= SDL_bmp.cCompil e arm : SDL2 <= SDL_clipboard.c Compil e arm : SDL2 <= SDL_fillrect.cCompil e arm : SDL2 <= SDL_pixels.cCompil e arm : SDL2 <= SDL_rect.cCompil e arm : SDL2 <= SDL_RLEaccel.c Compil e arm : SDL2 <= SDL_shape.cCompil e arm : SDL2 <= SDL_stretch.cCompil e arm : SDL2 <= SDL_surface.c Compil e arm : SDL2 <= SDL_video.cCompil e arm : SDL2 <= SDL_androidclipboard.c Compil e arm : SDL2 <= SDL_android events.c Compil e arm : SDL2 <= SDL_androidgl.c Compil e arm : SDL2 <= SDL_androidkeyboard.cCompil e arm : SDL2 <= SDL_androidtouch.cCompil e arm : SDL2 <= SDL_androidvideo.cCompil e arm : SDL2 <= SDL_androidwind ow.cStaticLibrary : libstdc++.aSharedLibrary : libSDL2.soInstall: libSDL2.so => libs/armeabi/libSDL2.so编译出sdl库后,我们就可以调用它的相关函数来实现我们的功能了。
android视频播放器源码
1.mian.xml代码<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/textview"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="@string/filename"/><EditTextandroid:id="@+id/filename"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="yueshen.mp4"/><SurfaceViewandroid:id="@+id/surfaceView"android:layout_width="fill_parent"android:layout_height="300dp"/><SeekBarandroid:id="@+id/move"android:layout_width="fill_parent"android:layout_height="wrap_content"/><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><ImageButtonandroid:id="@+id/play"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/play"android:layout_weight="1"/><ImageButtonandroid:id="@+id/suspend"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/suspend"android:layout_weight="1"/><ImageButtonandroid:id="@+id/reset"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/reset"android:layout_weight="1"/><ImageButtonandroid:id="@+id/stop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/stop"android:layout_weight="1"/><ImageButtonandroid:id="@+id/back"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/back"android:layout_weight="1"/><ImageButtonandroid:id="@+id/quick"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/quick"android:layout_weight="1"/><ImageButtonandroid:id="@+id/exit"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/exit"android:layout_weight="1"/></LinearLayout></LinearLayout>2.Activity_main.java代码package com.example.videoplayer;import java.io.File;import java.io.IOException;import android.media.AudioManager;import android.media.MediaPlayer;import android.os.Bundle;import android.os.Environment;import android.app.Activity;import android.util.Log;import android.view.Menu;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.ImageButton;import android.widget.SeekBar;import android.widget.Toast;import android.widget.SeekBar.OnSeekBarChangeListener; public class ZhaoActivity extends Activity {private static final String TAG="ZhaoActivity";private EditText filenameText;private String filename;private MediaPlayer mediaPlayer;private SurfaceView surfaceView;//private SeekBar seekbar;@SuppressWarnings("deprecation")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);filenameText=(EditText)this.findViewById(R.id.filename);mediaPlayer=new MediaPlayer();surfaceView=(SurfaceView)this.findViewById(R.id.surfaceView);surfaceView.getHolder().setFixedSize(176, 144);//设置分辨率surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);ButtonClickListener listener = new ButtonClickListener();ImageButton playButton =(ImageButton)this.findViewById(R.id.play);ImageButton susButton =(ImageButton)this.findViewById(R.id.suspend);ImageButton resetButton =(ImageButton)this.findViewById(R.id.reset);ImageButton stopButton =(ImageButton)this.findViewById(R.id.stop);ImageButton exitButton =(ImageButton)this.findViewById(R.id.exit);ImageButton quickButton =(ImageButton)this.findViewById(R.id.quick);ImageButton backButton =(ImageButton)this.findViewById(R.id.back);SeekBar seekbar=(SeekBar)this.findViewById(R.id.move);playButton.setOnClickListener(listener);susButton.setOnClickListener(listener);resetButton.setOnClickListener(listener);stopButton.setOnClickListener(listener);exitButton.setOnClickListener(listener);quickButton.setOnClickListener(listener);backButton.setOnClickListener(listener);seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar arg0) {// TODO Auto-generated method stub}@Overridepublic void onStartTrackingTouch(SeekBar arg0) {// TODO Auto-generated method stub}@Overridepublic void onProgressChanged(SeekBar seekBar, int progcess, boolean fromUser) {// TODO Auto-generated method stubint process = seekBar.getProgress();int max = seekBar.getMax();if (mediaPlayer != null) {mediaPlayer.seekTo(mediaPlayer.getDuration() * process / max);}}});}private final class ButtonClickListener implements View.OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {Toast.makeText(ZhaoActivity.this, R.string.sdcarderror, 1).show();return;}filename=filenameText.getText().toString();try {switch(v.getId()){case R.id.play:play();break;case R.id.suspend:if(mediaPlayer.isPlaying()){mediaPlayer.pause();}else{mediaPlayer.start();}break;case R.id.reset:if(mediaPlayer.isPlaying()){mediaPlayer.seekTo(0);}else{play();}break;case R.id.quick:if(mediaPlayer.isPlaying()){int i=mediaPlayer.getCurrentPosition()+5000;mediaPlayer.seekTo(i);}break;case R.id.back:if(mediaPlayer.isPlaying()){int i=mediaPlayer.getCurrentPosition()-5000;mediaPlayer.seekTo(i);}break;case R.id.stop:if(mediaPlayer.isPlaying()){mediaPlayer.stop();}break;case R.id.exit:mediaPlayer.release();//释放资源finish();break;}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();Log.e(TAG, e.toString());}}}private void play() throws IOException {File videoFile = new File(Environment.getExternalStorageDirectory(),filename);mediaPlayer.reset();//重置为初始状态mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setDisplay(surfaceView.getHolder());if(!videoFile.exists()){Toast.makeText(ZhaoActivity.this, R.string.fileerror, 1).show();return;}mediaPlayer.setDataSource(videoFile.getAbsolutePath());mediaPlayer.prepare();//缓冲mediaPlayer.start();//播放}}。
android视频播放器-源码
本文讲的是“android 视频播放器”,并附有播放器源代码1.开发环境:eclipse3.6ADT-0.9.7AVD1.62.程序运行效果A.启动AVD(虚拟设备)在应用程序界面主界面,我们可以看到“艾文播放器”B.点击打开后,会播放默认的一个coco的广告C.点击标题栏的按钮可以打开文件浏览器D.点击视频文件,会提示使用的播放器E.选择“艾文视频播放器”打开后,按ctrl+f12,切换到横屏,发现视频并没有中断,而是继续播放3.源码分析A.图片都是网上找的,还有就是自己收藏的地方翻出来的,不多讲了。
B.布局文件main.xml:期中包含一个videoview,用于播放视频图像titlebar.xml:主视图的标题栏布局,主要用于添加一个菜单按钮,点击后打开文件浏览器myfile.xml:为文件浏览器布局C.VideoPlay.javaview plaincopy to clipboardprint?1.package com.bestaone;2.3.import android.app.Activity;4.import android.content.Intent;5.import .Uri;6.import android.os.Bundle;7.import android.util.Log;8.import android.view.View;9.import android.view.View.OnClickListener;10.import android.view.Window;11.import android.view.WindowManager;12.import android.widget.ImageButton;13.import android.widget.MediaController;14.import android.widget.TextView;15.import android.widget.VideoView;16.17.public class VideoPlay extends Activity {18.19. private VideoView videoView;20. private static int index = 0;21.22.@Override23. public void onCreate(Bundle savedInstanceState) {24. super.onCreate(savedInstanceState);25. requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);26. setContentView(yout.main);27. getWindow().setFlags(youtParams.FLAG_FULLSCREEN, WindoyoutParams.FLAG_FULLSCREEN);//28. //设置标题栏的布局29. getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, yout.titlebar);30. //这个空间暂时没用31. final TextView titleTV = (TextView) findViewById(R.id.title);32. titleTV.setText("");33. ImageButton titleButton = (ImageButton) findViewById(R.id.titleButton);34. //为按钮添加鼠标点击事件35. titleButton.setOnClickListener(new OnClickListener() {36.@Override37. public void onClick(View v) {38. Intent intent = new Intent();39. intent.setClass(VideoPlay.this, MyFile.class);40. //打开MyFile activity41. startActivity(intent);42. }43. });44. Intent intent = getIntent();45. String value = intent.getDataString();46. videoView = (VideoView) findViewById(R.id.VideoView01);47. if(value==null){48. //加载默认视频49. videoView.setVideoURI(Uri.parse("android.resource://com.bestaone/" + R.drawable.coco));50. }else{51. //通过文件浏览器传过来的视频路径,播放52. videoView.setVideoPath(value);53. }54. videoView.setMediaController(new MediaController(VideoPlay.this));55. videoView.requestFocus();56. }57.58. //启动59.@Override60. protected void onStart() {61. super.onStart();62. Log.i("mp4", "@@@ on start");63. }64.65.@Override66. protected void onResume() {67. super.onResume();68. videoView.seekTo(index);69. videoView.start();70. Log.i("mp4", "@@@ on resume");71. }72.73. //暂停74.@Override75. protected void onPause() {76. super.onPause();77. Log.i("mp4", "@@@ on pause");78. }79.80. //停止81.@Override82. protected void onStop() {83. super.onStop();MyFile.javaview plaincopy to clipboardprint?1.package com.bestaone;2.3.import java.io.File;4.import java.util.ArrayList;5.import java.util.List;6.7.import android.app.ListActivity;8.import android.content.Intent;9.import .Uri;10.import android.os.Bundle;11.import android.view.KeyEvent;12.import android.view.View;13.import android.widget.AdapterView;14.import android.widget.AdapterView.OnItemLongClickListener;15.import android.widget.Button;16.import android.widget.EditText;17.import android.widget.ImageButton;18.import android.widget.ListView;19.import android.widget.TextView;20.import android.widget.Toast;21.22.public class MyFile extends ListActivity implements OnItemLongClickListener {23.24. //支持的视频格式25. private final String[][] FILE_MapTable = {26.27. // {后缀名, MIME类型}28. { ".3gp", "video/3gpp" },29. { ".mov", "video/quicktime" },30. { ".avi", "video/x-msvideo" },31. { ".rmvb", "audio/x-pn-realaudio" },32. { ".wmv", "audio/x-ms-wmv" }33.34. };35.36. private List<String> items = null; // items:存放显示的名称37. private List<String> paths = null; // paths:存放文件路径38. private List<String> sizes = null; // sizes:文件大小39. private String rootPath = "/"; // rootPath:起始文件夹40. private TextView path_edit;41. private ImageButton rb_qry;42. private int isZoom = 0;43. private int isOpen = 0;44.45.46. /**47. * 重写返回键功能:返回上一级文件夹48. */49.@Override50. public boolean onKeyDown(int keyCode, KeyEvent event) {51. // 是否触发按键为back键52. if (keyCode == KeyEvent.KEYCODE_BACK) {53. path_edit = (EditText) findViewById(R.id.path_edit);54. File file = new File(path_edit.getText().toString());55. if (rootPath.equals(path_edit.getText().toString())) {56. return super.onKeyDown(keyCode, event);57. } else {58. getFileDir(file.getParent());59. return true;60. }61. // 如果不是back键正常响应62. } else {63. return super.onKeyDown(keyCode, event);64. }65. }66.67.@Override68. protected void onCreate(Bundle icicle) {69. super.onCreate(icicle);70. setContentView(yout.myfile);71.72. path_edit = (EditText) findViewById(R.id.path_edit);73. rb_qry = (ImageButton) findViewById(R.id.qry_button);74. rb_qry.setOnClickListener(listener_qry);75. getListView().setOnItemLongClickListener(this);76. getFileDir(rootPath);77. }78.79. Button.OnClickListener listener_qry = new Button.OnClickListener() {80. public void onClick(View arg0) {81. File file = new File(path_edit.getText().toString());82. if (file.exists()) {83. if (file.isFile()) {84. openFile(file);85. } else {86. getFileDir(path_edit.getText().toString());87. }88. } else {89. Toast.makeText(MyFile.this, "找不到该位置,请确定位置是否正确!",Toast.LENGTH_SHORT).show();90. }91. }92. };93.94. /**95. * 设置ListItem被点击时要做的动作96. */97.@Override98. protected void onListItemClick(ListView l, View v, int position, long id) {99. File file = new File(paths.get(position));100. fileOrDirHandle(file);101. }102.103.104. /**105. * 处理文件或者目录的方法106. * @param file107. * @param flag108. */109. private void fileOrDirHandle(final File file) {110. if (file.isDirectory()) {111. getFileDir(file.getPath());112. } else {113. openFile(file);114. }115. }116.117. /**118. * 取得文件结构的方法119. * @param filePath120. */121. private void getFileDir(String filePath) {122. /* 设置目前所在路径 */123. path_edit.setText(filePath);124. items = new ArrayList<String>();125. paths = new ArrayList<String>();126. sizes = new ArrayList<String>();127. File f = new File(filePath);128. File[] files = f.listFiles();129. if (files != null) {130. /* 将所有文件添加ArrayList中 */131. for (int i = 0; i < files.length; i++) {132. if (files[i].isDirectory()) {133. items.add(files[i].getName());134. paths.add(files[i].getPath());135. sizes.add("");136. }137. }138.139. for (int i = 0; i < files.length; i++) {140. if (files[i].isFile()) {141. String fileName = files[i].getName();142. int index = stIndexOf(".");143. if(index>0){144. String endName = fileName.substring(index,fileName.length()).toLowe rCase();145. String type = null;146. for(int x=0; x<FILE_MapTable.length; x++){147. //支持的格式,才会在文件浏览器中显示148. if(endName.equals(FILE_MapTable[x][0])){149. type = FILE_MapTable[x][1];150. break;151. }152. }153. if(type!=null){154. items.add(files[i].getName());155. paths.add(files[i].getPath());156. sizes.add(MyUtil.fileSizeMsg(files[i]));157. }158. }159. }160. }161. }162. /* 使用自定义的MyAdapter来将数据传入ListActivity */163. setListAdapter(new FileListAdapter(this, items, paths, sizes, isZoom)); 164. }165.166.167. /**168. * 打开文件169. * @param f170. */171. private void openFile(File f) {172. Intent intent = new Intent();173. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);174. intent.setAction(android.content.Intent.ACTION_VIEW);175. // 跳出列表供选择176. String type = "video/*";177. if (isOpen == 0) {178. type = MyUtil.getMIMEType(f, true);179. }180. // 设置intent的file与MimeType181. intent.setDataAndType(Uri.fromFile(f), type);182.// intent.putExtra("path", "sms_context");183. startActivity(intent);184. }185.186.@Override187. public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, 188. long arg3) {189. // TODO Auto-generated method stub190. return false;191. }192.193.}。
Android原生视频播放VideoView的使用
Android原⽣视频播放VideoView的使⽤本⽂实例为⼤家分享了Android原⽣视频播放VideoView的具体代码,供⼤家参考,具体内容如下布局⽂件activity_video.xml<RelativeLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><VideoViewandroid:id="@+id/videoView"android:layout_width="match_parent"android:layout_height="match_parent" /><ProgressBarandroid:id="@+id/progressBar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true" /></RelativeLayout>对应的Avtivity:VideoActivity.javapackage com.example.administrator.main;import android.content.Intent;import android.media.MediaPlayer;import .Uri;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.MotionEvent;import android.view.View;import android.widget.MediaController;import android.widget.ProgressBar;import android.widget.RelativeLayout;import android.widget.VideoView;public class VideoActivity extends AppCompatActivity {private ProgressBar progressBar;private VideoView videoView;private MediaController mediaController;private int intPositionWhenPause = -1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_video);//调⽤系统⾃带视频播放或者安装的第三⽅播放器// Uri uri=Uri.parse("/mda-ig4tp6gnqwu5we8i/mda-ig4tp6gnqwu5we8i.mp4");// Intent intent=new Intent(Intent.ACTION_VIEW);// intent.setDataAndType(uri,"video/*");// startActivity(intent);initVideoView();}/*** 初始化videoview播放*/public void initVideoView() {//初始化进度条progressBar = (ProgressBar) findViewById(R.id.progressBar);//初始化VideoViewvideoView = (VideoView) findViewById(R.id.videoView);//初始化videoview控制条mediaController = new MediaController(this);//设置videoview的控制条videoView.setMediaController(mediaController);//设置显⽰控制条mediaController.show(0);//设置播放完成以后监听videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {}});//设置发⽣错误监听,如果不设置videoview会向⽤户提⽰发⽣错误videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {return false;}});//设置在视频⽂件在加载完毕以后的回调函数videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {progressBar.setVisibility(View.GONE);videoView.start();}});//设置videoView的点击监听videoView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return false;}});//设置⽹络视频路径Uri uri = Uri.parse("/mda-ig4tp6gnqwu5we8i/mda-ig4tp6gnqwu5we8i.mp4");videoView.setVideoURI(uri);//设置为全屏模式播放setVideoViewLayoutParams(2);}/*** 设置videiview的全屏和窗⼝模式** @param paramsType 标识 1为全屏模式 2为窗⼝模式*/public void setVideoViewLayoutParams(int paramsType) {//全屏模式if (1 == paramsType) {//设置充满整个⽗布局youtParams LayoutParams = new youtParams(youtParams.MATCH_PARENT, youtParams.MATCH_PARENT); //设置相对于⽗布局四边对齐LayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);LayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);LayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);LayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);//为VideoView添加属性videoView.setLayoutParams(LayoutParams);} else {//窗⼝模式//获取整个屏幕的宽⾼DisplayMetrics DisplayMetrics = new DisplayMetrics();this.getWindowManager().getDefaultDisplay().getMetrics(DisplayMetrics);//设置窗⼝模式距离边框50int videoHeight = DisplayMetrics.heightPixels;int videoWidth = DisplayMetrics.widthPixels;youtParams LayoutParams = new youtParams(videoWidth, videoHeight);//设置居中LayoutParams.addRule(RelativeLayout.ALIGN_TOP);//为VideoView添加属性videoView.setLayoutParams(LayoutParams);}}/*** 页⾯暂停效果处理*/@Overrideprotected void onPause() {super.onPause();//如果当前页⾯暂停则保存当前播放位置,全局变量保存intPositionWhenPause = videoView.getCurrentPosition();//停⽌回放视频⽂件videoView.stopPlayback();}/*** 页⾯从暂停中恢复*/@Overrideprotected void onResume() {super.onResume();//跳转到暂停时保存的位置if (intPositionWhenPause >= 0) {videoView.seekTo(intPositionWhenPause);//初始播放位置intPositionWhenPause = -1;}}}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
AndroidGSYVideoPlayer视频播放器功能的实现
AndroidGSYVideoPlayer视频播放器功能的实现GSYVideoPlayerGSYVideoPlayer ⼀个基于IJkPlayer的播放器⽀持调节声⾳亮度边播边缓存使⽤了AndroidVideoCache;ExoPlayer使⽤SimpleCache⽀持多种协议h263\4\5、Https、concat、rtsp、hls、rtmp、crypto、mpeg等等简单滤镜(马赛克、⿊⽩、⾊彩过滤、⾼斯、模糊、模糊等等20多种)、动画、(⽔印、画⾯多重播放等)视频第⼀帧、视频帧截图功能,视频⽣成gif功能。
调整显⽰⽐例:默认、16:9、4:3、填充;播放时旋转画⾯⾓度(0,90,180,270);镜像旋转IJKPlayer、EXOPlayer、MediaPlayer切换、⾃定义内核⼩窗⼝、多窗体下(包括桌⾯)的⼩窗⼝播放。
⽚头⼴告、跳过⼴告⽀持、中间插⼊⼴告功能。
暂停前后台切换不⿊屏;调整不同清晰度的⽀持;⽆缝切换⽀持;锁定/解锁全屏点击功能;进度条⼩窗⼝预览可⾃定义渲染层、⾃定义管理层、⾃定义播放层(控制层)、⾃定义缓存层使⽤依赖1、JCenter 引⼊⽅法(推荐)你可以选择下⾯三种的其中⼀种,在module下的build.gradle添加。
A、直接引⼊//完整版引⼊implementation 'com.shuyu:GSYVideoPlayer:8.1.2'B、添加java和你想要的so⽀持:implementation 'com.shuyu:gsyVideoPlayer-java:8.1.2'//是否需要ExoPlayer模式implementation 'com.shuyu:GSYVideoPlayer-exo2:8.1.2'//根据你的需求ijk模式的soimplementation 'com.shuyu:gsyVideoPlayer-armv5:8.1.2'implementation 'com.shuyu:gsyVideoPlayer-armv7a:8.1.2'implementation 'com.shuyu:gsyVideoPlayer-arm64:8.1.2'implementation 'com.shuyu:gsyVideoPlayer-x64:8.1.2'implementation 'com.shuyu:gsyVideoPlayer-x86:8.1.2'C、⽀持其他格式协议的(mpeg,rtsp, concat、crypto协议)implementation 'com.shuyu:gsyVideoPlayer-java:8.1.2'//是否需要ExoPlayer模式implementation 'com.shuyu:GSYVideoPlayer-exo2:8.1.2'//更多ijk的编码⽀持implementation 'com.shuyu:gsyVideoPlayer-ex_so:8.1.2'代码中的全局切换⽀持//EXOPlayer内核,⽀持格式更多PlayerFactory.setPlayManager(Exo2PlayerManager.class);//系统内核模式PlayerFactory.setPlayManager(SystemPlayerManager.class);//ijk内核,默认模式PlayerFactory.setPlayManager(IjkPlayerManager.class);//exo缓存模式,⽀持m3u8,只⽀持exoCacheFactory.setCacheManager(ExoPlayerCacheManager.class);//代理缓存模式,⽀持所有模式,不⽀持m3u8等,默认CacheFactory.setCacheManager(ProxyCacheManager.class);//切换渲染模式GSYVideoType.setShowType(GSYVideoType.SCREEN_MATCH_FULL);//默认显⽰⽐例GSYVideoType.SCREEN_TYPE_DEFAULT = 0;//16:9GSYVideoType.SCREEN_TYPE_16_9 = 1;//4:3GSYVideoType.SCREEN_TYPE_4_3 = 2;//全屏裁减显⽰,为了显⽰正常 CoverImageView 建议使⽤FrameLayout作为⽗布局GSYVideoType.SCREEN_TYPE_FULL = 4;//全屏拉伸显⽰,使⽤这个属性时,surface_container建议使⽤FrameLayoutGSYVideoType.SCREEN_MATCH_FULL = -4;/**** SCREEN_TYPE_CUSTOM 下⾃定义显⽰⽐例* @param screenScaleRatio ⾼宽⽐,如 16:9*/public static void setScreenScaleRatio(float screenScaleRatio)//切换绘制模式GSYVideoType.setRenderType(GSYVideoType.SUFRACE);GSYVideoType.setRenderType(GSYVideoType.GLSURFACE);GSYVideoType.setRenderType(GSYVideoType.TEXTURE);//ijk关闭logIjkPlayerManager.setLogLevel(IjkMediaPlayer.IJK_LOG_SILENT);//exoplayer⾃定义MediaSourceExoSourceManager.setExoMediaSourceInterceptListener(new ExoMediaSourceInterceptListener() {@Overridepublic MediaSource getMediaSource(String dataSource, boolean preview, boolean cacheEnable, boolean isLooping, File cacheDir) {//可⾃定义MediaSourcereturn null;}});⾃定义⼀个播放器public class LiveVideo extends StandardGSYVideoPlayer {public LiveDataFullscreenButtonClick liveDataClick;//点击全屏按钮回调/*** 恢复暂停状态*/public void onResume() {onVideoResume();}/*** 暂停状态*/public void onPause() {onVideoPause();}/*** 接⼝回调* @param liveDataClick*/public void setOnFullscreenButtonClick(LiveDataFullscreenButtonClick liveDataClick) { this.liveDataClick = liveDataClick;}/* 重写⽅法⾃定义layout id与video_layout_standard.xml⼀致不重新使⽤系统默认布局*/ @Overridepublic int getLayoutId() {return yout.test;}public LiveVideo(Context context, Boolean fullFlag) {super(context, fullFlag);init();}public LiveVideo(Context context) {super(context);init();}public LiveVideo(Context context, AttributeSet attrs) {super(context, attrs);init();}/* 初始化操作 */private void init() {//EXOPlayer内核,⽀持格式更多// PlayerFactory.setPlayManager(Exo2PlayerManager.class);//代理缓存模式,⽀持所有模式,不⽀持m3u8等,默认// CacheFactory.setCacheManager(ProxyCacheManager.class);//系统内核模式// PlayerFactory.setPlayManager(SystemPlayerManager.class);//ijk内核,默认模式PlayerFactory.setPlayManager(IjkPlayerManager.class);settingsVideo();}/* ⼀些播放器的设置做⼀些UI的隐藏可根据⾃⼰需求*/public void settingsVideo() {GSYVideoType.enableMediaCodec();//使能硬解码,播放前设置Debuger.enable();//打开GSY的Log//隐藏⼀些UIsetViewShowState(mBottomContainer, VISIBLE);setViewShowState(mTopContainer, VISIBLE);setViewShowState(mLockScreen, GONE);setViewShowState(mLoadingProgressBar, GONE);setViewShowState(mTopContainer, GONE);setViewShowState(mThumbImageView, GONE);setViewShowState(mBottomProgressBar, GONE);//显⽰⼀些UI 进度时间当前时间全屏返回加载Loading 暂停开始setViewShowState(mStartButton, VISIBLE);setViewShowState(mLoadingProgressBar, VISIBLE);setViewShowState(mFullscreenButton, VISIBLE);setViewShowState(mBackButton, GONE);setViewShowState(mProgressBar, VISIBLE);setViewShowState(mCurrentTimeTextView, VISIBLE);setViewShowState(mTotalTimeTextView, VISIBLE);setEnlargeImageRes(R.drawable.full);setShrinkImageRes(R.drawable.full);}//拦截事件@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {mFullscreenButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View view) {liveDataClick.onClick();}});return super.dispatchTouchEvent(ev);}/* 取消双击暂停 */@Overrideprotected void touchDoubleUp() {// super.touchDoubleUp();}public interface LiveDataFullscreenButtonClick {void onClick();}}<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/black"><RelativeLayoutandroid:id="@+id/surface_container"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"></RelativeLayout><RelativeLayoutandroid:id="@+id/thumb"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentBottom="true"android:layout_alignParentEnd="true"android:layout_alignParentLeft="true"android:layout_alignParentRight="true"android:layout_alignParentStart="true"android:layout_alignParentTop="true"android:background="#000000"android:scaleType="fitCenter" /><LinearLayoutandroid:id="@+id/layout_bottom"android:layout_width="match_parent"android:layout_height="40dp"android:layout_alignParentBottom="true"android:background="#99000000"android:gravity="center_vertical"android:orientation="horizontal"android:visibility="invisible"><TextViewandroid:id="@+id/current"android:textColor="@color/white"style="@style/news_des_style"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="16dp"android:text="00:00"/><SeekBarandroid:id="@+id/progress"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_weight="1.0"android:background="@null"android:padding="10dp"android:max="100"android:maxHeight="4dp"android:minHeight="4dp"android:paddingBottom="8dp"android:paddingTop="8dp"android:progressDrawable="@drawable/video_progress_bg" android:thumb="@drawable/video_seek_thumb" /><TextViewandroid:id="@+id/total"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="16dp"android:text="00:00"android:textColor="@color/white"style="@style/news_des_style"/></LinearLayout><LinearLayoutandroid:id="@+id/layout_top"android:layout_width="match_parent"android:layout_height="48dp"android:background="@drawable/video_title_bg"android:gravity="center_vertical"><ImageViewandroid:id="@+id/back"android:layout_width="48dp"android:layout_height="48dp"android:paddingLeft="10dp"android:scaleType="centerInside"android:src="@drawable/video_back" /><Viewandroid:layout_weight="1"android:layout_width="0dp"android:layout_height="match_parent"/><ImageViewandroid:id="@+id/fullscreen"style="@style/left_icon_style"android:src="@drawable/full" /></LinearLayout><ProgressBarandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/loading"android:layout_centerInParent="true"/><ImageViewandroid:visibility="gone"android:layout_width="50dp"android:layout_height="50dp"android:layout_centerInParent="true"android:padding="5dp"android:id="@+id/start"/></RelativeLayout>api/*** 设置播放URL** @param url 播放url* @param cacheWithPlay 是否边播边缓存* @param title title* @return*/video.setUp("url", false, "");//设置播放路径video.startPlayLogic();//开始播放到此这篇关于Android GSYVideoPlayer视频播放器功能的实现的⽂章就介绍到这了,更多相关Android GSYVideoPlayer视频播放器内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
Android视频自动播放
Android视频自动播放今天是内容是给游戏添加一个视频,用于开场公司logo播放。
要求:1.不要出现播放器那种"开始","暂停" "快进""快退"等按钮。
2.播放完成后需要事件监听移除掉视频。
首先在android中播放视频默认支持3GP,MP4格式,如果你需要支持其他格式必须软解码其他格式文件。
因为我做的不是一个播放器只需要在游戏开头播放一下视频就行了,所以这里选用MP4格式。
然后API的选择有MediaPlayer和VideoView用MediaPlayer要自己编写响应的代码,如果你熟悉MediaPlayer只是稍微复杂一点而已。
用VideoView 是android已经封装好的View 它继承自SurfaceView并实现了MediaPlayerControl接口。
稍微想了下,毫不犹豫的选择了VideoView 。
首先要重写VideoView因为他默认不是全屏的,我需要全屏package ss.ss;import android.content.Context;import android.util.AttributeSet;import android.widget.VideoView;public class MyVideoView extends VideoView {public static int WIDTH;public static int HEIGHT;public MyVideoView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = getDefaultSize(WIDTH, widthMeasureSpec);int height = getDefaultSize(HEIGHT, heightMeasureSpec);setMeasuredDimension(width,height);}}XML代码:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><ss.ss.MyVideoViewandroid:id="@+id/surface_view"android:layout_width="fill_parent"android:layout_height="fill_parent"/></LinearLayout>注意在这里设置为fill_parent或者wrap_content都是无影响的,他不会因为你设置成fill_parent就让视频全屏播放,感兴趣的朋友可以查VideoView.onMeasure()源码,视频的尺寸由这个方法控制,它是根据比例来显示的,所以我上面需要重写VideoView.onMeasure();然后我们看下Activity的代码:/** Copyright (C) 2009 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** /licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package ss.ss;import android.app.Activity;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import .Uri;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.Window;import android.view.WindowManager;import android.widget.Toast;public class VideoViewDemo extends Activity implements OnCompletionListener {/*** TODO: Set the path variable to a streaming video URL or a local media* file path.*/private String path = "/sdcard/main.mp4";private MyVideoView mVideoView;@Overridepublic void onCreate(Bundle icicle) {super.onCreate(icicle);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().addFlags(youtParams.FLAG_FULLSCREEN);setContentView(yout.videoview);mVideoView = (MyVideoView) findViewById(R.id.surface_view);mVideoView.setOnCompletionListener(this);DisplayMetrics dm = new DisplayMetrics();this.getWindowManager().getDefaultDisplay().getMetrics(dm);MyVideoView.WIDTH=dm.widthPixels;MyVideoView.HEIGHT=dm.heightPixels;if (path == "") {//Tell the user to provide a media file URL/path.Toast.makeText(VideoViewDemo.this,"Please edit VideoViewDemo Activity, and set path"+ "variable to your media file URL/path",Toast.LENGTH_LONG).show();} else {/** Alternatively,for streaming media you can use* mVideoView.setVideoURI(Uri.parse(URLstring));*///mVideoView.setVideoPath(path);mVideoView.setVideoURI(Uri.parse("android.resource://ss.ss/"+R.raw.main));//如果你需要添加控制条就取消改注释//mVideoView.setMediaController(new MediaController(this));//1.6中测试自动播放的播放代码是不需要.start()//2.1中测试自动播放的播放代码// mVideoView.start();//所以为了兼容性我们选择mVideoView.start();保证所有版本都在开始时自动播放 mVideoView.start();}}@Overrideprotected void onDestroy() {super.onDestroy();System.exit(0);}@Overridepublic void onCompletion(MediaPlayer mp) {System.out.println("播放完成");}}这里大部分是API demo中的源码,稍微做了下修改。
Android视频播放器代码
Java代码部分:import java.io.IOException;import java.util.Random;import android.app.Activity;import android.content.Context;import NotFoundException;import android.media.AudioManager;import android.media.MediaPlayer;import android.media.MediaPlayer.OnBufferingUpdateListener;import android.media.MediaPlayer.OnCompletionListener;import android.os.Bundle;import android.os.Handler;import android.view.GestureDetector.OnGestureListener;import android.view.Gravity;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.Window;import android.view.WindowManager;import android.view.View.OnClickListener;import android.view.View.OnTouchListener;import android.widget.ImageButton;import android.widget.LinearLayout;import youtParams;import android.widget.PopupWindow;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;import android.widget.TextView;import android.widget.Toast;public class PlayVideo extends Activity implementsOnGestureListener,OnClickListener,// 监听OnBufferingUpdateListener,// 当网络缓冲数据流变化的时候唤起的播放事件OnCompletionListener,// 当媒体资源在播放的时候到达终点时唤起的播放事件MediaPlayer.OnPreparedListener,SurfaceHolder.Callback// 回调函数{// 视频高和宽int videoWidth;int videoHeight;// 按钮ImageButton play;//定义快进按钮ImageButton fastPlay;//定义快退按钮ImageButton fastBack;// 控制栏LinearLayout layout_control; LinearLayout layout_prograss; LinearLayout videoBack;// 用来播放媒体MediaPlayer mediaPlayer; // 显示媒体SurfaceView surView;// 用来控制SurfaceView SurfaceHolder surHolder;// 路径String path;// 是否是播放状态boolean boTing = true;//获取播放的位置int num;//点击屏幕次数int count;//第一次点击int firClick;//第二次点击int secClick;//通过flag判断是否全屏boolean flag;//播放进度条SeekBar seekbar;//显示时间组建TextView showTime;//播放文件的时间int minute;int second;//进度条进度int progress;//线程控制MyThread mt;//声音控制SeekBar sound;//声音进度int soundId;//显示音量TextView showSound;//接取拖动进度条int videoLength;boolean f = true;//播放尺寸//按钮隐藏时间int hint = 5000;//用于接取点击ListView位置int position;//声称随机数Random random;//通过buttonFlag判断按钮背景boolean buttonFlag = true;//显示视频总时间TextView allTime;TextView distant;PopupWindow popuWindow;View view;boolean popFlag ;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);this.getWindow().setFlags(youtParams.FLAG_FULLSCREEN, youtParams.FLAG_FULLSCREEN);setContentView(yout.video);// 产生对象view = this.getLayoutInflater().inflate(yout.popuwindow, null);//得到布局的IDvideoBack = (LinearLayout)view.findViewById(R.id.videoback);// 产生对象play = (ImageButton) view.findViewById(R.id.video_bu_bofang);layout_control = (LinearLayout)findViewById(yout_control);layout_prograss= (LinearLayout)findViewById(yout_prograss);seekbar = (SeekBar)view.findViewById(R.id.seekbar);showTime = (TextView)view.findViewById(R.id.showtime);fastPlay = (ImageButton)view.findViewById(R.id.fastplay);fastBack = (ImageButton)view.findViewById(R.id.fastback);sound = (SeekBar)view.findViewById(R.id.sound);showSound = (TextView)view.findViewById(R.id.showsound);surView = (SurfaceView) findViewById(R.id.surfaceview_1);allTime = (TextView)view.findViewById(R.id.alltime);distant = (TextView)findViewById(R.id.distant);surHolder = surView.getHolder();popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);// 设置回调函数surHolder.addCallback(this);// 设置风格surHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//bu_boFang.setVisibility(View.INVISIBLE);// 设置按键监听play.setOnClickListener(this);//快进监听fastPlay.setOnClickListener(this);//快退按钮监听fastBack.setOnClickListener(this);//new随机数对象random = new Random();//接取到播放列表中点击的位置position = VideoList.position;try {//获取ShareActivity上下文VideoList.context = createPackageContext(".iotek", Context.CONTEXT_IGNORE_SECURITY);VideoList.share = VideoList.context.getSharedPreferences("setupadapter", VideoList.context.MODE_WORLD_READABLE);VideoList.editor = VideoList.share.edit();} catch (NameNotFoundException e) {e.printStackTrace();}//对读取的信息进行判断if (VideoList.share.getString("hinttime", "5秒").equals("5秒")) {hint = 5000;}if (VideoList.share.getString("hinttime", "5秒").equals("10秒")) {hint = 10000;}if (VideoList.share.getString("hinttime", "5秒").equals("15秒")) {hint = 15000;}//设置全屏播放surView.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stub// handler.sendEmptyMessageAtTime(0x11, 3000);if(MotionEvent.ACTION_DOWN == event.getAction()){count++;if(count == 1){new countClear().start();firClick = (int) System.currentTimeMillis();if (!popFlag) {// // // popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);popuWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);popFlag = true;handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}//设置layout显示// if (!flag) {/* layout_control.setVisibility(View.VISIBLE);layout_prograss.setVisibility(View.VISIBLE);*///点击surfaceView延时3S发送信息/* handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);*/// }} else if (count == 2){secClick = (int) System.currentTimeMillis();if(secClick - firClick < 1000){flag = !flag;count = 0;}if(flag){distant.setHeight(0);surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));surHolder.setFixedSize(480, 760);if (!popFlag) {// popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);popuWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);popFlag = true;handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}// 开始播放// mePlayer.start();}else{if (VideoList.share.getString("size", "4:3").equals("4:3")) {surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, 360));surHolder.setFixedSize(480, 360);distant.setHeight(250);if (!popFlag) {// popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);popuWindow.showAtLocation(view,Gravity.BOTTOM, 0, 0);popFlag = true;handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}}if (VideoList.share.getString("size", "4:3").equals("16:9")) {surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, 270));surHolder.setFixedSize(480, 270);distant.setHeight(250);if (!popFlag) {// popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);popuWindow.showAtLocation(view,Gravity.BOTTOM, 0, 0);popFlag = true;handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}}}count = 0;firClick = 0;secClick = 0;}}return true;}});//监听进度条进度seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {videoLength = seekBar.getProgress();// int q = mediaPlayer.getCurrentPosition();mediaPlayer.seekTo(videoLength);//获取进度条当前的位置// int dest = seekBar.getProgress();//设置播放器当期的播放位置// mediaPlayer.seekTo(num);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {//得到seekbar的进度/* seekbar.setProgress(progress);videoLength = seekBar.getProgress();*/}});sound.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stubint i= seekBar.getProgress();mediaPlayer.setVolume(i/100f,i/100f);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stub}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// TODO Auto-generated method stubint i= sound.getProgress();showSound.setText("音量:"+i);handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}});}private void playVideo(){// 构建MediaPlayer对象mediaPlayer = new MediaPlayer();try {// 设置媒体文件路径mediaPlayer.setDataSource(VideoList.path);// 设置通过SurfaceView来显示画面mediaPlayer.setDisplay(surHolder);// 准备mediaPlayer.prepare();distant.setHeight(200);// 设置事件监听mediaPlayer.setOnBufferingUpdateListener(this);mediaPlayer.setOnCompletionListener(this);mediaPlayer.setOnPreparedListener(this);mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);seekbar.setMax(mediaPlayer.getDuration());//设置当前播放音量最大soundId = sound.getProgress();mediaPlayer.setVolume(soundId, soundId);showSound.setText("音量:"+soundId);mt = new MyThread();mt.start();handler.sendEmptyMessage(0x13);int n = mediaPlayer.getDuration();//获得持续时间seekbar.setMax(n);n = n/1000;int m = n/60;int h = m/60;int s = n%60;m = m%60;allTime.setText(String.format("影片长度:"+"%02d:%02d:%02d", h,m,s));} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}// MediaPlayer.OnPreparedListenerpublic void onCompletion(MediaPlayer mp) {handler.sendEmptyMessage(0x14);}// MediaPlayer.OnPreparedListener// 这时能确保player处于Prepared状态,触发start是最合适的public void onPrepared(MediaPlayer mp) {if (VideoList.share.getString("size", "4:3").equals("4:3")) {surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, 360));// 设置播放视频的宽度和高度surHolder.setFixedSize(480, 360);// 开始播放mediaPlayer.start();}if (VideoList.share.getString("size", "4:3").equals("16:9")) {// 设置播放视频的宽度和高度surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, 270));surHolder.setFixedSize(480, 270);// 开始播放mediaPlayer.start();}}public void surfaceCreated(SurfaceHolder holder) {playVideo();}public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}protected void onDestroy(){super.onDestroy();if (mediaPlayer != null){mediaPlayer.release();mediaPlayer = null;//关闭cursor// VideoList.cursor.close();//关闭数据库// VideoList.db.close();//改变线程循环条件f = false;handler.removeMessages(0x11);popuWindow.dismiss();}}public void onClick(View v) {if(v==play){//如果正在播放if (buttonFlag) {play.setImageResource(R.drawable.pause_1);mediaPlayer.pause();buttonFlag = false;}else{play.setImageResource(R.drawable.play_1);mediaPlayer.start();buttonFlag = true;}handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}if (v == fastPlay) {int i = mediaPlayer.getCurrentPosition()+5000;mediaPlayer.seekTo(i);seekbar.setProgress(i);handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}if (v == fastBack) {int i = mediaPlayer.getCurrentPosition()-5000;mediaPlayer.seekTo(i);seekbar.setProgress(i);handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}}Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {if (msg.what == 0x11) {if(popuWindow.isShowing()&&f){popuWindow.dismiss();popFlag = false;}////启动后设置layout隐藏/* layout_control.setVisibility(View.INVISIBLE);layout_prograss.setVisibility(View.INVISIBLE);*/}if (msg.what == 0x12) {if(mediaPlayer!=null){num = mediaPlayer.getCurrentPosition();}seekbar.setProgress(num);// 为时分秒赋值num = num/1000;int minute = num/60;int hour = minute/60;int second = num%60;minute = minute%60;/* if (mediaPlayer!=null) {seekbar.setProgress(mediaPlayer.getCurrentPosition());}*/showTime.setText(String.format("播放进度:"+"%02d:%02d:%02d", hour,minute,second));// handler.sendEmptyMessage(0x12);}if (msg.what == 0x14) {if (VideoList.share.getString("playstyle","顺序播放").equals("单曲循环")) {//释放播放的视频mediaPlayer.release();//游标移动到点击ListView位置// VideoList.cursor.moveToPosition(VideoList.position);//在数据库中取出ListView点击的路径VideoList.path = VideoList.cursor.getString(1);//播放视频playVideo();}if (VideoList.share.getString("playstyle", "顺序播放").equals("顺序播放")) { //释放当前的MediaPlayermediaPlayer.release();//自加position ++;if (position==VideoList.videoList.getCount()) {position = 0;}//游标向下移动VideoList.cursor.moveToPosition(position);//取出移动后的视频路径VideoList.path = VideoList.cursor.getString(1);//播放视频playVideo();}if (VideoList.share.getString("playstyle", "顺序播放").equals("随机播放")) { //释放播放的视频mediaPlayer.release();int r = random.nextInt(VideoList.videoList.getCount()-1);VideoList.cursor.moveToPosition(r);//在数据库中取出ListView点击的路径VideoList.path = VideoList.cursor.getString(1);//播放视频playVideo();}}};};class MyThread extends Thread{@Overridepublic void run() {handler.sendEmptyMessageDelayed(0x11, hint);// if (mePlayer.getDuration()+"".equals("0") ) {while (f) {try {sleep(1000);handler.sendEmptyMessage(0x12);}catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}// }}}class countClear extends Thread{@Overridepublic void run() {try {sleep(1000);//睡一秒后count清0count = 0;} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub}@Overridepublic void onBufferingUpdate(MediaPlayer mp, int percent) { // TODO Auto-generated method stub}@Overridepublic boolean onDown(MotionEvent e) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {// TODO Auto-generated method stubreturn false;}@Overridepublic void onLongPress(MotionEvent e) {// TODO Auto-generated method stub}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {// TODO Auto-generated method stubreturn false;}@Overridepublic void onShowPress(MotionEvent e) {// TODO Auto-generated method stub}@Overridepublic boolean onSingleTapUp(MotionEvent e) {// TODO Auto-generated method stubreturn false;}}配置文件:Video.xml文件<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:id="@+id/videoback"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#00000000"android:id="@+id/distant"/><SurfaceViewandroid:id="@+id/surfaceview_1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="300px"android:layout_gravity="center_horizontal" /></LinearLayout>Popuwindow.xml配置文件<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:id="@+id/videoback"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><LinearLayoutandroid:id="@+id/layout_prograss"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:orientation="vertical" ><SeekBarandroid:id="@+id/seekbar"android:layout_width="match_parent"android:layout_height="8px"android:progressDrawable="@drawable/seekbar"android:thumb="@drawable/seekbutton"android:progress="0" /><TextViewandroid:id="@+id/showtime"android:layout_width="match_parent"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/alltime"android:layout_width="match_parent"android:layout_height="wrap_content"/><SeekBarandroid:id="@+id/sound"android:layout_height="8px"android:progressDrawable="@drawable/seekbar"android:thumb="@drawable/seekbutton"android:progress="50" /><TextViewandroid:id="@+id/showsound"android:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout><LinearLayoutandroid:id="@+id/layout_control"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:orientation="horizontal" ><ImageButtonandroid:id="@+id/fastback"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:background="#00000000"android:scaleType="fitCenter"android:src="@drawable/stepback" /><ImageButtonandroid:id="@+id/video_bu_bofang"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:background="#00000000"android:scaleType="fitCenter"android:src="@drawable/play_1" /><ImageButtonandroid:id="@+id/fastplay"android:layout_width="wrap_content"android:layout_weight="1"android:background="#00000000"android:scaleType="fitCenter"android:src="@drawable/stepfor" /> </LinearLayout></LinearLayout>。
安卓视频播放器完整项目
安卓视频播放器该项目是自己学习阶段研发的,如果有什么不足之处,希望还能共同探,按钮和背景图片,还需要自己找,下面上代码欢迎动画,WelcomeActivity.Java文件package .iotek;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class WelcomeActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);this.getWindow().setFlags(youtParams.FLAG_FULLSCREEN,youtParams.FLAG_FULLSCREEN);setContentView(yout.welcome);new MyWelcome().start();}class MyWelcome extends Thread{@Overridepublic void run() {try {sleep(3000);Intent intent=new Intent(WelcomeActivity.this,VideoPlayerActivity.class);startActivity(intent);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}@Overrideprotected void onStop() {finish();super.onStop();}}欢迎动画配置文件welcome.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="@drawable/welcome"android:orientation="vertical" ></LinearLayout>三秒后进行跳转,进入界面,利用TabHost,VideoPlayerActivity代码如下package .iotek;import .adapter.OverwriteSimpleCursorAdapter;import .adapter.OverwriterSimAdapter;import android.app.TabActivity;import android.content.Context;import android.content.Intent;import NotFoundException;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;import android.widget.SimpleAdapter;import android.widget.SimpleCursorAdapter;import android.widget.TabHost;import android.widget.TabHost.OnTabChangeListener;import android.widget.TabHost.TabSpec;public class VideoPlayerActivity extends TabActivity {/** Called when the activity is first created. */static boolean flag;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);this.getWindow().setFlags(youtParams.FLAG_FULLSCREEN,youtParams.FLAG_FULLSCREEN);setContentView(yout.main);try {//获取ShareActivity上下文VideoList.context = createPackageContext(".iotek", Context.CONTEXT_IGNORE_SECURITY);VideoList.share = VideoList.context.getSharedPreferences("setupadapter", VideoList.context.MODE_WORLD_READABLE);VideoList.editor = VideoList.share.edit();} catch (NameNotFoundException e) {e.printStackTrace();}if (VideoList.share.getString("setupadapter", "off").equals("on")) {flag = true;}if (VideoList.share.getString("setupadapter", "off").equals("off")) {flag = false;}VideoList.helper=new Dbhelper(this, "/mnt/sdcard/videoinfo.db", null, 1);//设置为可读// VideoList.db=VideoList.helper.getReadableDatabase();TabHost tabHost = getTabHost();//创建选项卡TabSpec localVideo=tabHost.newTabSpec("localvideo");TabSpec videoList=tabHost.newTabSpec("videoList");//设置选项卡名称localVideo.setIndicator("加载本地文件");videoList.setIndicator("播放列表");tabHost.setOnTabChangedListener(new OnTabChangeListener() {@Overridepublic void onTabChanged(String tabId) {// TODO Auto-generated method stub}});Intent intentLocal = new Intent(getApplicationContext(),ShowList.class);Intent intentList = new Intent(getApplicationContext(),VideoList.class);localVideo.setContent(intentLocal);videoList.setContent(intentList);// 添加选项卡tabHost.addTab(localVideo);tabHost.addTab(videoList);//设置监听tabHost.setOnTabChangedListener(new OnTabChangeListener() {@Overridepublic void onTabChanged(String tabId) {// TODO Auto-generated method stubboolean f = tabId.equals("videoList");boolean b = tabId.equals("localvideo");if (f) {if (flag) {VideoList.db=VideoList.helper.getReadableDatabase();String sql="select * from videoinfo";VideoList.cursor=VideoList.db.rawQuery(sql, null);VideoList.adapter=newOverwriteSimpleCursorAdapter(getApplicationContext(), yout.show, VideoList.cursor,new String[]{"path","videoname"},new int[]{R.id.picture,R.id.videoname});VideoList.videoList.setAdapter(VideoList.adapter);}if(!flag){VideoList.db=VideoList.helper.getReadableDatabase();String sql="select * from videoinfo";VideoList.cursor=VideoList.db.rawQuery(sql, null);VideoList.adapter=new SimpleCursorAdapter(getApplicationContext(), yout.show, VideoList.cursor,new String[]{"path","videoname"},new int[]{R.id.picture,R.id.videoname});VideoList.videoList.setAdapter(VideoList.adapter);}}if (b) {if (flag) {OverwriterSimAdapter adapter = new OverwriterSimAdapter(getApplicationContext(), ShowList.listItems, yout.filelist,new String[] { "filename", "icon", "modify" }, new int[] {R.id.file_name, R.id.icon, R.id.file_modify });ShowList.filesList.setAdapter(adapter);}if(!flag){SimpleAdapter adapter = new SimpleAdapter(getApplicationContext(), ShowList.listItems, yout.filelist,new String[] { "filename", "icon", "modify" }, new int[] {R.id.file_name, R.id.icon, R.id.file_modify });ShowList.filesList.setAdapter(adapter);}}}});}@Overrideprotected void onDestroy() {// VideoList.db.close();// VideoList.cursor.close();super.onDestroy();}}配置文件main.xml<?xml version="1.0" encoding="utf-8"?><TabHost xmlns:android="/apk/res/android"android:id="@android:id/tabhost"android:layout_width="fill_parent"android:layout_height="fill_parent"><LinearLayoutandroid:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"android:padding="5dp"><TabWidgetandroid:id="@android:id/tabs"android:layout_width="fill_parent"android:layout_height="wrap_content"android:background="#00000000"/><FrameLayoutandroid:id="@android:id/tabcontent"android:layout_width="fill_parent"android:layout_height="fill_parent"android:padding="5dp" /></LinearLayout></TabHost>遍历内存卡ShowList代码package .iotek;import java.io.File;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import .adapter.OverwriterSimAdapter;import android.app.Activity;import android.content.Context;import NotFoundException;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.Button;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.SimpleAdapter;import android.widget.T extView;import android.widget.Toast;public class ShowList extends Activity {private TextView filepath;static ListView filesList;private Button backButton;LinearLayout localBack;// 记录当前的父文件夹File floderParent;int i ;// 记录当前路径下的所有文件夹的文件数组File[] dirFiles;static List<Map<String, Object>> listItems ;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.showlist);localBack = (LinearLayout)findViewById(R.id.localback);localBack.setBackgroundResource(R.drawable.bleach3);VideoList.helper=new Dbhelper(this, "/mnt/sdcard/videoinfo.db", null, 1);//设置为可读// VideoList.db=VideoList.helper.getReadableDatabase();filesList = (ListView) this.findViewById(R.id.filesList);filepath = (TextView) this.findViewById(R.id.filepath);backButton = (Button) this.findViewById(R.id.backButton);VideoList.helper=new Dbhelper(this, "/mnt/sdcard/videoinfo.db", null, 1);// VideoList.db=VideoList.helper.getReadableDatabase();try {//获取ShareActivity上下文VideoList.context = createPackageContext(".iotek", Context.CONTEXT_IGNORE_SECURITY);VideoList.share = VideoList.context.getSharedPreferences("setupadapter", VideoList.context.MODE_WORLD_READABLE);VideoList.editor = VideoList.share.edit();} catch (NameNotFoundException e) {e.printStackTrace();}//对背景进行判断if (VideoList.share.getString("picture", "卡通").equals("卡通")) {localBack.setBackgroundResource(R.drawable.haizei);}if (VideoList.share.getString("picture", "卡通").equals("风景")) {localBack.setBackgroundResource(R.drawable.suround2);}if (VideoList.share.getString("picture", "卡通").equals("明星")) {localBack.setBackgroundResource(R.drawable.xuanya);}// 获取系统的SDCard的目录File root = new File("/mnt/sdcard/");// 如果SD卡存在的话if (root.exists()) {floderParent = root;dirFiles = root.listFiles();// 使用当前目录下的全部文件、文件夹来填充ListViewinflateListView(dirFiles);}filesList.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view,int position, long id) {// 如果用户单击了文件,直接返回,不做任何处理if (dirFiles[position].isFile()) {i = position;if(dirFiles[position].getPath().endsWith(".3gp")||dirFiles[position].getPath().endsWith(".mp4")||dirFiles[position].getPath().endsWith(".mp3")||dirFiles[position].getPath().endsWith(".rm vb")) {/* if(currentFiles[position].getPath().equals(VideoList.cursor.getString(1))) {Toast.makeText(getApplicationContext(), "你妹啊,路径名相同了", 1000).show();}else{*/VideoList.db=VideoList.helper.getReadableDatabase();String sqlSelect = "select * from videoinfo where path=?";VideoList.cursor = VideoList.db.rawQuery(sqlSelect, new String[]{dirFiles[position].getPath()});if(!VideoList.cursor.moveToNext()){// 放入数据库String sql="insert into videoinfo values(null,?,?)";VideoList.db.execSQL(sql,newString[]{dirFiles[position].getPath(),dirFiles[position].getName()});Toast.makeText(getApplicationContext(), "文件加载成功", 1000).show();}else{Toast.makeText(getApplicationContext(), "路径名相同了", 1000).show();}// }}return;// 也可自定义扩展打开这个文件等}// 获取用户点击的文件夹下的所有文件File[] tem = dirFiles[position].listFiles();if (tem == null || tem.length == 0) {Toast.makeText(ShowList.this,"空文件夹", Toast.LENGTH_LONG).show();} else {// 获取用户单击的列表项对应的文件夹,设为当前的父文件夹floderParent = dirFiles[position];// 保存当前的父文件夹内的全部文件和文件夹dirFiles = tem;// 再次更新ListViewinflateListView(dirFiles);}}});// 获取上一级目录backButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {if (!floderParent.getCanonicalPath().equals("/mnt/sdcard")) {// 获取上一级目录floderParent = floderParent.getParentFile();// 列出当前目录下的所有文件dirFiles = floderParent.listFiles();// 再次更新ListViewinflateListView(dirFiles);}} catch (Exception e) {// TODO: handle exception}}});}/*** 根据文件夹填充ListView** @param files*/private void inflateListView(File[] files) {listItems = new ArrayList<Map<String, Object>>();for (int i = 0; i < files.length; i++) {Map<String, Object> listItem = new HashMap<String, Object>();if (files[i].isDirectory()) {// 如果是文件夹就显示的图片为文件夹的图片listItem.put("icon", R.drawable.dir);}if(files[i].isFile()){//判断是否是视频if(files[i].getPath().endsWith(".3gp")||files[i].getPath().endsWith(".mp4")||files[i].getPath(). endsWith(".mp3")){if(files[i].getPath().endsWith(".3gp")||files[i].getPath().endsWith(".mp4")){if (VideoPlayerActivity.flag) {listItem.put("icon", files[i].getAbsolutePath());listItem.put("modify",size(files[i].length())+"");}if (!VideoPlayerActivity.flag) {listItem.put("icon", R.drawable.avi);listItem.put("modify",size(files[i].length())+"");}}}else if(files[i].getPath().endsWith(".mp3")){listItem.put("icon", R.drawable.mp3);}else{listItem.put("icon", R.drawable.els);}}// 添加一个文件名称listItem.put("filename", files[i].getName());listItems.add(listItem);}// 判断是否使用缩略图if (VideoPlayerActivity.flag) {OverwriterSimAdapter adapter = new OverwriterSimAdapter(ShowList.this, listItems, yout.filelist,new String[] { "filename", "icon", "modify" }, new int[] {R.id.file_name, R.id.icon, R.id.file_modify });filesList.setAdapter(adapter);}if(!VideoPlayerActivity.flag){SimpleAdapter adapter = new SimpleAdapter(ShowList.this, listItems, yout.filelist,new String[] { "filename", "icon", "modify" }, new int[] {R.id.file_name, R.id.icon, R.id.file_modify });filesList.setAdapter(adapter);}try {filepath.setText("当前路径为:" + floderParent.getCanonicalPath());//tvpath.setText("文件如下:");} catch (Exception e) {e.printStackTrace();}}public String size(long size){long mysize;if(size<1024*1024){mysize = size/1024;return mysize+"Kb";}else{mysize = size/(1024*1024);return mysize+"Mb";}}@Overrideprotected void onRestart() {if (VideoList.share.getString("picture", "卡通").equals("卡通")) { localBack.setBackgroundResource(R.drawable.haizei);}if (VideoList.share.getString("picture", "卡通").equals("风景")) { localBack.setBackgroundResource(R.drawable.suround2);}if (VideoList.share.getString("picture", "卡通").equals("明星")) { localBack.setBackgroundResource(R.drawable.xuanya);}super.onRestart();}@Overrideprotected void onDestroy() {// VideoList.db.close();// VideoList.cursor.close();super.onDestroy();}@Overrideprotected void onStop() {super.onStop();}}配置文件showlist.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"android:id="@+id/localback"><TextViewandroid:id="@+id/filepath"android:layout_gravity="center_horizontal"android:layout_width="fill_parent"android:layout_height="wrap_content"android:textSize="20dip"/><ListView android:id="@+id/filesList"android:layout_width="wrap_content"android:layout_height="wrap_content"></ListView><Button android:id="@+id/backButton"android:layout_width="30dp"android:layout_height="30dp"android:background="@drawable/back"android:paddingTop="20dip"android:layout_gravity="center"/><TextView android:layout_width="match_parent"android:layout_height="30dp"android:text="返回上一级菜单"android:gravity="center"/></LinearLayout>核心内容,MediaPlayer和SurfaceView实现比方视频,PlayVideo代码package .iotek;import java.io.IOException;import java.util.Random;import android.app.Activity;import android.content.Context;import NotFoundException; import android.media.AudioManager;import android.media.MediaPlayer;import android.media.MediaPlayer.OnBufferingUpdateListener;import android.media.MediaPlayer.OnCompletionListener;import android.os.Bundle;import android.os.Handler;import android.view.GestureDetector.OnGestureListener;import android.view.Gravity;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.Window;import android.view.WindowManager;import android.view.View.OnClickListener;import android.view.View.OnTouchListener;import android.widget.ImageButton;import android.widget.LinearLayout;import youtParams;import android.widget.PopupWindow;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;import android.widget.T extView;import android.widget.Toast;public class PlayVideo extends Activity implementsOnGestureListener,OnClickListener,// 监听OnBufferingUpdateListener,// 当网络缓冲数据流变化的时候唤起的播放事件OnCompletionListener,// 当媒体资源在播放的时候到达终点时唤起的播放事件MediaPlayer.OnPreparedListener,SurfaceHolder.Callback// 回调函数{// 视频高和宽int videoWidth;int videoHeight;// 按钮ImageButton play;//定义快进按钮ImageButton fastPlay;//定义快退按钮ImageButton fastBack;// 控制栏LinearLayout layout_control;LinearLayout layout_prograss;LinearLayout videoBack;// 用来播放媒体MediaPlayer mediaPlayer;// 显示媒体SurfaceView surView;// 用来控制SurfaceViewSurfaceHolder surHolder;// 路径String path;// 是否是播放状态boolean boTing = true;//获取播放的位置int num;//点击屏幕次数int count;//第一次点击int firClick;//第二次点击int secClick;//通过flag判断是否全屏boolean flag;//播放进度条SeekBar seekbar;//显示时间组建TextView showTime;//播放文件的时间int minute;int second;//进度条进度int progress;//线程控制MyThread mt;//声音控制SeekBar sound;//声音进度int soundId;//显示音量TextView showSound;//接取拖动进度条int videoLength;boolean f = true;//播放尺寸//按钮隐藏时间int hint = 5000;//用于接取点击ListView位置int position;//声称随机数Random random;//通过buttonFlag判断按钮背景boolean buttonFlag = true;//显示视频总时间TextView allTime;TextView distant; PopupWindow popuWindow;View view;boolean popFlag ;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);this.getWindow().setFlags(youtParams.FLAG_FULLSCREEN,youtParams.FLAG_FULLSCREEN);setContentView(yout.video);// 产生对象view = this.getLayoutInflater().inflate(yout.popuwindow, null);//得到布局的IDvideoBack = (LinearLayout)view.findViewById(R.id.videoback);// 产生对象play = (ImageButton) view.findViewById(R.id.video_bu_bofang);layout_control = (LinearLayout)findV iewById(yout_control);layout_prograss= (LinearLayout)findViewById(yout_prograss);seekbar = (SeekBar)view.findViewById(R.id.seekbar);showTime = (TextView)view.findViewById(R.id.showtime);fastPlay = (ImageButton)view.findViewById(R.id.fastplay);fastBack = (ImageButton)view.findViewById(R.id.fastback);sound = (SeekBar)view.findViewById(R.id.sound);showSound = (TextView)view.findViewById(R.id.showsound);surView = (SurfaceView) findViewById(R.id.surfaceview_1);allTime = (TextView)view.findViewById(R.id.alltime);distant = (TextView)findViewById(R.id.distant);distant.setHeight(0);surHolder = surView.getHolder();popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);// 设置回调函数surHolder.addCallback(this);// 设置风格surHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//bu_boFang.setVisibility(View.INVISIBLE);// 设置按键监听play.setOnClickListener(this);//快进监听fastPlay.setOnClickListener(this);//快退按钮监听fastBack.setOnClickListener(this);//new随机数对象random = new Random();//接取到播放列表中点击的位置position = VideoList.position;try {//获取ShareActivity上下文VideoList.context = createPackageContext(".iotek", Context.CONTEXT_IGNORE_SECURITY);VideoList.share = VideoList.context.getSharedPreferences("setupadapter", VideoList.context.MODE_WORLD_READABLE);VideoList.editor = VideoList.share.edit();} catch (NameNotFoundException e) {e.printStackTrace();}//对读取的信息进行判断if (VideoList.share.getString("hinttime", "5秒").equals("5秒")) {hint = 5000;}if (VideoList.share.getString("hinttime", "5秒").equals("10秒")) {hint = 10000;}if (VideoList.share.getString("hinttime", "5秒").equals("15秒")) {hint = 15000;}//设置全屏播放surView.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stub// handler.sendEmptyMessageAtTime(0x11, 3000);if(MotionEvent.ACTION_DOWN == event.getAction()){count++;if(count == 1){new countClear().start();firClick = (int) System.currentTimeMillis();if (!popFlag) {// // // popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);popuWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);popFlag = true;handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}//设置layout显示// if (!flag) {/* layout_control.setVisibility(View.VISIBLE);layout_prograss.setVisibility(View.VISIBLE);*///点击surfaceView延时3S发送信息/* handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);*/// }} else if (count == 2){secClick = (int) System.currentTimeMillis();if(secClick - firClick < 1000){flag = !flag;count = 0;}if(flag){distant.setHeight(0);surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MA TCH_PARENT));surHolder.setFixedSize(480, 760);if (!popFlag) {// popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);popuWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);popFlag = true;handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}// 开始播放// mePlayer.start();}else{if (VideoList.share.getString("size", "4:3").equals("4:3")) {surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, 360));surHolder.setFixedSize(480, 360);distant.setHeight(0);if (!popFlag) {// popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);popuWindow.showAtLocation(view,Gravity.BOTTOM, 0, 0);popFlag = true;handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}}if (VideoList.share.getString("size", "4:3").equals("16:9")) {surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, 270));surHolder.setFixedSize(480, 270);distant.setHeight(250);if (!popFlag) {// popuWindow = new PopupWindow(view, LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);popuWindow.showAtLocation(view,Gravity.BOTTOM, 0, 0);popFlag = true;handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}}}count = 0;firClick = 0;secClick = 0;}}return true;}});//监听进度条进度seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {videoLength = seekBar.getProgress();// int q = mediaPlayer.getCurrentPosition();mediaPlayer.seekTo(videoLength);//获取进度条当前的位置// int dest = seekBar.getProgress();//设置播放器当期的播放位置// mediaPlayer.seekTo(num);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {//得到seekbar的进度/* seekbar.setProgress(progress);videoLength = seekBar.getProgress();*/}});sound.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stubint i= seekBar.getProgress();mediaPlayer.setVolume(i/100f,i/100f);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stub}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// TODO Auto-generated method stubint i= sound.getProgress();showSound.setText("音量:"+i);handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}});}private void playVideo(){// 构建MediaPlayer对象mediaPlayer = new MediaPlayer();try {// 设置媒体文件路径mediaPlayer.setDataSource(VideoList.path);// 设置通过SurfaceView来显示画面mediaPlayer.setDisplay(surHolder);// 准备mediaPlayer.prepare();distant.setHeight(200);// 设置事件监听mediaPlayer.setOnBufferingUpdateListener(this);mediaPlayer.setOnCompletionListener(this);mediaPlayer.setOnPreparedListener(this);mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);seekbar.setMax(mediaPlayer.getDuration());//设置当前播放音量最大soundId = sound.getProgress();mediaPlayer.setVolume(soundId, soundId);showSound.setText("音量:"+soundId);mt = new MyThread();mt.start();handler.sendEmptyMessage(0x13);int n = mediaPlayer.getDuration();//获得持续时间seekbar.setMax(n);n = n/1000;int m = n/60;int h = m/60;int s = n%60;m = m%60;allTime.setText(String.format("影片长度:"+"%02d:%02d:%02d", h,m,s));} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}// MediaPlayer.OnPreparedListenerpublic void onCompletion(MediaPlayer mp) {handler.sendEmptyMessage(0x14);}// MediaPlayer.OnPreparedListener// 这时能确保player处于Prepared状态,触发start是最合适的public void onPrepared(MediaPlayer mp) {if (VideoList.share.getString("size", "4:3").equals("4:3")) {surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, 360));// 设置播放视频的宽度和高度surHolder.setFixedSize(480, 360);// 开始播放mediaPlayer.start();}if (VideoList.share.getString("size", "4:3").equals("16:9")) {// 设置播放视频的宽度和高度surView.setLayoutParams(newyoutParams(LayoutParams.MATCH_PARENT, 270));surHolder.setFixedSize(480, 270);// 开始播放mediaPlayer.start();}}public void surfaceCreated(SurfaceHolder holder) {playVideo();}public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}protected void onDestroy(){super.onDestroy();if (mediaPlayer != null){mediaPlayer.release();mediaPlayer = null;//关闭cursor// VideoList.cursor.close();//关闭数据库// VideoList.db.close();//改变线程循环条件f = false;handler.removeMessages(0x11);popuWindow.dismiss();}}public void onClick(View v) {if(v==play){//如果正在播放if (buttonFlag) {play.setImageResource(R.drawable.pause_1);mediaPlayer.pause();buttonFlag = false;}else{play.setImageResource(R.drawable.play_1);mediaPlayer.start();buttonFlag = true;}handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}if (v == fastPlay) {int i = mediaPlayer.getCurrentPosition()+5000;mediaPlayer.seekTo(i);seekbar.setProgress(i);handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}if (v == fastBack) {int i = mediaPlayer.getCurrentPosition()-5000;mediaPlayer.seekTo(i);seekbar.setProgress(i);handler.removeMessages(0x11);handler.sendEmptyMessageDelayed(0x11, hint);}}Handler handler = new Handler(){public void handleMessage(android.os.Message msg) { if (msg.what == 0x11) {if(popuWindow.isShowing()&&f){popuWindow.dismiss();popFlag = false;}。
Android最简单的视频播放器之MediaCodec硬件解码器封装(二)
Android最简单的视频播放器之MediaCodec硬件解码器封装(⼆)⼀、概述 MediaCodec是Android提供的硬件编解码器API,根据此api⽤户可以对媒体格式的⽂件执⾏编解码。
其单独没法⼯作还需要配合上⼀节介绍的 案例:本例最主要的是三个类,分别是BaseDecoder.java 、AudioDecoder、VideoDecoder.java即⾳视频解码类实例⼆、代码实例 1.BaseDecoder.java:硬件解码器基类import android.media.MediaCodec;import android.media.MediaFormat;import android.util.Log;import com.yw.thesimpllestplayer.extractor.IExtractor;import java.io.File;import java.nio.ByteBuffer;/*** @ProjectName: TheSimpllestplayer* @Package: com.yw.thesimpllestplayer.mediaplayer.decoder* @ClassName: BaseDecoder* @Description: 硬件解码器基类* @Author: wei.yang* @CreateDate: 2021/11/6 10:32* @UpdateUser: 更新者:wei.yang* @UpdateDate: 2021/11/6 10:32* @UpdateRemark: 更新说明:* @Version: 1.0*/public abstract class BaseDecoder implements IDecoder {private String filePath = null;public BaseDecoder(String filePath) {this.filePath = filePath;}private static final String TAG = "BaseDecoder";//-------------线程相关------------------------/*** 解码器是否在运⾏*/private boolean mIsRunning = true;/*** 线程等待锁*/private Object mLock = new Object();/*** 是否可以进⼊解码*/private boolean mReadyForDecode = false;//---------------状态相关-----------------------/*** ⾳视频解码器(硬件解码器)*/private MediaCodec mCodec = null;/*** ⾳视频数据读取器*/private IExtractor mExtractor = null;/*** 解码输⼊缓存区*/private ByteBuffer[] mInputBuffers = null;/*** 解码输出缓存区private ByteBuffer[] mOutputBuffers = null;/*** 解码数据信息*/private MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo(); /*** 初始化解码状态*/private DecodeState mState = DecodeState.STOP;/*** 解码状态回调*/protected IDecoderStateListener mStateListener;/*** 流数据是否结束*/private boolean mIsEOS = false;/*** 视频宽度*/private int mVideoWidth = 0;/*** 视频⾼度*/private int mVideoHeight = 0;/*** 视频时长*/private long mDuration = 0;/*** 视频结束时间*/private long mEndPos = 0;/*** 开始解码时间,⽤于⾳视频同步*/private long mStartTimeForSync = -1L;/*** 是否需要⾳视频渲染同步*/private boolean mSyncRender = true;@Overridepublic void pause() {mState = DecodeState.PAUSE;}@Overridepublic void goOn() {mState = DecodeState.DECODING;notifyDecode();}@Overridepublic long seekTo(long pos) {return0;}@Overridepublic long seekAndPlay(long pos) {return0;}@Overridepublic void stop() {mState = DecodeState.STOP;mIsRunning = false;notifyDecode();}@Overridepublic boolean isDecoding() {return mState == DecodeState.DECODING;}@Overridepublic boolean isSeeking() {return mState == DecodeState.SEEKING;}@Overridereturn mState == DecodeState.STOP;}@Overridepublic int getWidth() {return mVideoWidth;}@Overridepublic int getHeight() {return mVideoHeight;}@Overridepublic long getDuration() {return mDuration;}@Overridepublic long getCurTimeStamp() {return mBufferInfo.presentationTimeUs / 1000;}@Overridepublic int getRotationAngle() {return0;}@Overridepublic MediaFormat getMediaFormat() {return mExtractor.getFormat();}@Overridepublic int getTrack() {return0;}@Overridepublic String getFilePath() {return filePath;}@Overridepublic IDecoder withoutSync() {mSyncRender = false;return this;}@Overridepublic void setSizeListener(IDecoderProgress iDecoderProgress) {}@Overridepublic void setStateListener(IDecoderStateListener iDecoderStateListener) { this.mStateListener = iDecoderStateListener;}@Overridepublic void run() {//解码开始时改变解码状态if (mState == DecodeState.STOP) {mState = DecodeState.START;}if (mStateListener != null) {mStateListener.decoderPrepare(this);}//初始化并启动解码器,如果解码失败则暂停线程if (!init()) return;//开始解码Log.e(TAG, "开始解码");try {while (mIsRunning) {//循环解码渲染if (mState != DecodeState.START &&mState != DecodeState.DECODING &&mState != DecodeState.SEEKING) {Log.i(TAG, "进⼊等待:" + mState);//解码进⼊等待waitDecode();// ---------【同步时间矫正】-------------//当前系统时间减去bufferinfo中的时间=等待解码流失的时间mStartTimeForSync = System.currentTimeMillis() - getCurTimeStamp(); }//停⽌解码,就直接退出循环了if (!mIsRunning ||mState == DecodeState.STOP) {mIsRunning = false;break;}//更新开始解码时间if (mStartTimeForSync == -1L) {mStartTimeForSync = System.currentTimeMillis();}//如果数据没有解码完毕,将数据推⼊解码器解码if (!mIsEOS) {//【解码步骤:2. 见数据压⼊解码器输⼊缓冲】mIsEOS = pushBufferToDecoder();}//将解码后的数据从缓冲区中拉取出来int outputBufferIndex = pullBufferFromDecoder();if (outputBufferIndex >= 0) {// ---------【⾳视频同步】-------------if (mSyncRender && mState == DecodeState.DECODING) {sleepRender();}//渲染if (mSyncRender) {render(mOutputBuffers[outputBufferIndex], mBufferInfo);}//将解码数据传出去Frame frame = new Frame();frame.buffer = mOutputBuffers[outputBufferIndex];frame.setBufferInfo(mBufferInfo);if (mStateListener != null) {mStateListener.decodeOneFrame(this, frame);}//释放输出缓冲mCodec.releaseOutputBuffer(outputBufferIndex, true);if (mState == DecodeState.START) {mState = DecodeState.PAUSE;}}//判断是否解码完成if (mBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) { Log.e(TAG, "解码结束");mState = DecodeState.FINISH;if (mStateListener != null) {mStateListener.decoderFinish(this);}}}} catch (Exception e) {e.printStackTrace();} finally {finishDecode();release();}}/*** 初始化解码器,如果初始化失败则停⽌解码** @return*/private boolean init() {//如果⽂件路径不存在或者⽂件路径指定的⽂件为空if (filePath == null || !new File(filePath).exists()) {Log.e(TAG, "⽂件路径异常");if (mStateListener != null) {mStateListener.decoderError(this, "⽂件路径为空");}return false;}if (!check()) return false;//初始化数据提取器mExtractor = initExtractor(filePath);if (mExtractor == null || mExtractor.getFormat() == null) {Log.e(TAG, "⽆法解析⽂件");if (mStateListener != null) {mStateListener.decoderError(this, "⽆法解析⽂件");return false;}//初始化参数if (!initParams()) return false;//初始化渲染器if (!initRender()) return false;//初始化解码器if (!initCodec()) return false;return true;}/*** 初始化媒体时长及初始化媒体参数** @return*/private boolean initParams() {try {MediaFormat format = mExtractor.getFormat();mDuration = format.getLong(MediaFormat.KEY_DURATION) / 1000;if (mEndPos == 0L) mEndPos = mDuration;initSpecParams(format);} catch (Exception e) {e.printStackTrace();Log.e(TAG, "提取媒体⽂件时长或者初始化媒体参数失败:" + e.getMessage());if (mStateListener != null) {mStateListener.decoderError(this, "提取媒体⽂件时长或者初始化媒体参数失败"); }return false;}return true;}private boolean initCodec() {try {//获取媒体类型String mimeType = mExtractor.getFormat().getString(MediaFormat.KEY_MIME);//创建解码器mCodec = MediaCodec.createDecoderByType(mimeType);//配置解码器if (!configCodec(mCodec, mExtractor.getFormat())) {//解码线程进⼊等待waitDecode();}//开始解码mCodec.start();//从缓冲区中去取输⼊缓冲mInputBuffers = mCodec.getInputBuffers();//从缓冲区中取出输出缓冲mOutputBuffers = mCodec.getOutputBuffers();} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 解码线程进⼊等待*/private void waitDecode() {try {if (mState == DecodeState.PAUSE) {if (mStateListener != null) {mStateListener.decoderPause(this);}}synchronized (mLock) {mLock.wait();}} catch (Exception e) {e.printStackTrace();}}/*** 通知解码线程继续运⾏*/protected void notifyDecode() {synchronized (mLock) {mLock.notifyAll();if (mState == DecodeState.DECODING) {if (mStateListener != null) {mStateListener.decoderRunning(this);}}}/*** 向缓冲区中压缩解码前的数据** @return*/private boolean pushBufferToDecoder() {//从缓冲区中获取⼀个bufferindexint inputBufferIndex = mCodec.dequeueInputBuffer(1000);boolean isEndOfStream = false;if (inputBufferIndex >= 0) {//根据inputBufferIndex获取inputBufferByteBuffer inputBuffer = mInputBuffers[inputBufferIndex];//使⽤数据提取器Extractor读取⼀帧数据int sampleSize = mExtractor.readBuffer(inputBuffer);if (sampleSize < 0) {//如果数据帧兑取失败则说明读完了mCodec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); isEndOfStream = true;} else {//将读取到的数据送⼊缓冲区(压⼊)mCodec.queueInputBuffer(inputBufferIndex, 0, sampleSize, mExtractor.getCurrentTimestamp(), 0);}}return isEndOfStream;}/*** 从缓冲区中取出解码后的数据** @return*/private int pullBufferFromDecoder() {//从缓冲区中取出outputbufferindexint outputBufferIndex = mCodec.dequeueOutputBuffer(mBufferInfo, 1000);switch (outputBufferIndex) {case _OUTPUT_FORMAT_CHANGED:break;case _TRY_AGAIN_LATER:break;case _OUTPUT_BUFFERS_CHANGED:mOutputBuffers = mCodec.getOutputBuffers();break;default:return outputBufferIndex;}return -1;}/*** ⾳视频同步*/private void sleepRender() {try {long passTime = System.currentTimeMillis() - mStartTimeForSync;long currTime = getCurTimeStamp();if (currTime > passTime) {Thread.sleep(currTime - passTime);}} catch (Exception e) {e.printStackTrace();}}/*** 释放解码器*/private void release() {try {Log.i(TAG, "解码停⽌,释放解码器");mState = DecodeState.STOP;mIsEOS = false;mExtractor.stop();mCodec.stop();mCodec.release();if (mStateListener != null) {mStateListener.decoderDestroy(this);} catch (Exception e) {e.printStackTrace();}}/*** 检查⼦类参数** @return*/public abstract boolean check();/*** 初始化数据提取器** @param filePath 媒体⽂件路径* @return 数据提取器*/public abstract IExtractor initExtractor(String filePath);/*** 初始化⼦类⾃⼰持有的媒体参数** @param format*/public abstract void initSpecParams(MediaFormat format);/*** 配置解码器** @param codec 硬件解码器* @param format 媒体格式参数* @return*/public abstract boolean configCodec(MediaCodec codec, MediaFormat format);/*** 初始化渲染器** @return*/public abstract boolean initRender();/*** 执⾏渲染操作** @param outputBuffer 输出的渲染数据* @param bufferInfo 解码出来的数据*/public abstract void render(ByteBuffer outputBuffer, MediaCodec.BufferInfo bufferInfo); /*** 结束解码*/public abstract void finishDecode();} 2.AudioDecoder.java:⾳频解码器import android.media.MediaCodec;import android.media.MediaFormat;import com.yw.thesimpllestplayer.audioplayer.AudioPlayer;import com.yw.thesimpllestplayer.extractor.AudioExtractor;import com.yw.thesimpllestplayer.extractor.IExtractor;import java.nio.ByteBuffer;/*** @ProjectName: TheSimpllestplayer* @Package: com.yw.thesimpllestplayer.mediaplayer.decoder* @ClassName: AudioDecoder* @Description: ⾳频解码器* @Author: wei.yang* @CreateDate: 2021/11/6 13:55* @UpdateUser: 更新者:wei.yang* @UpdateDate: 2021/11/6 13:55* @UpdateRemark: 更新说明:* @Version: 1.0*/private AudioPlayer audioPlayer;public AudioDecoder(String filePath) {super(filePath);}@Overridepublic boolean check() {return true;}@Overridepublic IExtractor initExtractor(String filePath) {return new AudioExtractor(filePath);}@Overridepublic void initSpecParams(MediaFormat format) {if (audioPlayer == null) {audioPlayer = new AudioPlayer(format);}}@Overridepublic boolean configCodec(MediaCodec codec, MediaFormat format) {codec.configure(format, null, null, 0);return true;}@Overridepublic boolean initRender() {audioPlayer.initPlayer();return true;}@Overridepublic void render(ByteBuffer outputBuffer, MediaCodec.BufferInfo bufferInfo) { audioPlayer.play(outputBuffer, bufferInfo);}@Overridepublic void finishDecode() {audioPlayer.stop();audioPlayer.release();}} 2.VideoDecoder.java:视频解码器import android.media.MediaCodec;import android.media.MediaFormat;import android.util.Log;import android.view.Surface;import com.yw.thesimpllestplayer.extractor.IExtractor;import com.yw.thesimpllestplayer.extractor.VideoExtractor;import java.nio.ByteBuffer;/*** @ProjectName: TheSimpllestplayer* @Package: com.yw.thesimpllestplayer.mediaplayer.decoder* @ClassName: VideoDecoder* @Description: 视频解码器* @Author: wei.yang* @CreateDate: 2021/11/6 13:49* @UpdateUser: 更新者:wei.yang* @UpdateDate: 2021/11/6 13:49* @UpdateRemark: 更新说明:* @Version: 1.0*/public class VideoDecoder extends BaseDecoder {private static final String TAG = "VideoDecoder";private Surface surface;public VideoDecoder(String filePath, Surface surface) {super(filePath);this.surface = surface;@Overridepublic boolean check() {if (surface == null) {Log.e(TAG, "Surface不能为空");if (mStateListener != null) {mStateListener.decoderError(this, "显⽰器为空");}return false;}return true;}@Overridepublic IExtractor initExtractor(String filePath) {return new VideoExtractor(filePath);}@Overridepublic void initSpecParams(MediaFormat format) {}@Overridepublic boolean configCodec(MediaCodec codec, MediaFormat format) {if (surface != null) {codec.configure(format, surface, null, 0);notifyDecode();} else {if (mStateListener != null) {mStateListener.decoderError(this, "配置解码器失败,因为Surface为空"); }Log.e(TAG, "配置解码器失败,因为Surface为空");return false;}return true;}@Overridepublic boolean initRender() {return true;}@Overridepublic void render(ByteBuffer outputBuffer, MediaCodec.BufferInfo bufferInfo) { }@Overridepublic void finishDecode() {}}。
Android中如何使用ExoPlayer播放音频和视频
Android中如何使用ExoPlayer播放音频和视频ExoPlayer是Google开发的一个功能强大的多媒体播放器库,可以用于Android应用程序中的音频和视频播放。
它提供了灵活且可扩展的API,可以满足各种播放需求,同时还提供了全面的媒体格式和协议的支持。
本文将介绍如何在Android中使用ExoPlayer来实现音频和视频的播放。
一、ExoPlayer的引入要在Android项目中使用ExoPlayer,首先需要将其引入到项目中。
可以通过在项目的build.gradle文件中添加以下依赖项来引入ExoPlayer 库:```implementation 'com.google.android.exoplayer:exoplayer:2.X.X'```其中,'2.X.X'是ExoPlayer的版本号,可以根据需要进行替换。
二、创建ExoPlayer实例使用ExoPlayer播放音频和视频时,首先需要创建一个ExoPlayer实例。
可以通过调用ExoPlayerFactory的静态方法来创建默认的ExoPlayer实例:```javaSimpleExoPlayer player =ExoPlayerFactory.newSimpleInstance(context);```在创建ExoPlayer实例时,需要传入一个Context对象作为参数。
三、准备媒体资源在播放音频或视频之前,需要先准备好媒体资源。
ExoPlayer支持多种媒体格式和协议,包括本地文件、HTTP、HLS、DASH等。
其中,通过DataSource.Factory类可以创建一个数据源工厂,用于从不同的媒体源加载数据。
下面是一个使用本地文件作为媒体资源的示例:```javaDataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context, Util.getUserAgent(context, "YourApplicationName"));MediaSource mediaSource = newExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.f romFile(new File(filePath)));```在上述代码中,我们首先创建了一个数据源工厂,将其与应用程序的User-Agent关联起来。
Android使用FFmpeg--ffmpeg实现视频播放
Android使用FFmpeg--ffmpeg实现视频播放关于前言如果你已经准备好ffmpeg的开发环境,那么我们在这篇文章中实现对视频的一个播放,如果还没有准备好,请看前面的内容。
正文视频播放大概流程图.pngOk,上图就是使用ffmpeg实现了一个视频的播放的大概流程图,那么,我们将根据流程图来编写代码,这样子,代码的编写就会显得比较简单,比较好理解了。
1.注册各大组件,这一步很重要,如果不注册就无法使用后面的函数了。
av_register_all(;2.在解码之前我们得获取里面的内容吧,所以这一步就是打开地址并且获取里面的内容。
其中avFormatContext是内容的一个上下文,inputPath为输入的地址。
AVFormatContext *avFormatContext = avformat_alloc_context(;//获取上下文 avfor mat_open_input(&avFormatContext, inputPath, NULL, NULL)//解封装 avformat_fin d_stream_info(avFormatContext, NULL)3.我们在上面已经获取了内容,但是在一个音视频中包括了音频流,视频流和字幕流,所以在所有的内容当中,我们应当找出相对应的视频流。
int video_index=-1; for (int i = 0; i < avFormatContext->nb_streams; ++i) { if (a vFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { //如果是视频流,标记一哈 video_index = i; } }4.在第三步的时候已经找到了视频流,那么我们就对视频流进行解码、转换和绘制。
a.如果要进行解码,那么得有解码器并打开解码器。
Android三种播放视频的方式
Android三种播放视频的方式在Android中,我们有三种方式来实现视频的播放:1、使用其自带的播放器。
指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。
2、使用VideoView来播放。
在布局文件中使用VideoView结合MediaController来实现对其控制。
3、使用MediaPlayer类和SurfaceView来实现,这种方式很灵活。
1、调用其自带的播放器:1.Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+' /Test_Movie.m4v');2.//调用系统自带的播放器3.Intent intent = new Intent(Intent.ACTION_VIEW);4.Log.v('URI:::::::::', uri.toString());5.intent.setDataAndType(uri, 'video/mp4');6.startActivity(intent);2、使用VideoView来实现:1.Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+' /Test_Movie.m4v');2.VideoView videoView = (VideoView)this.findViewById(R.id.video_view);3.videoView.setMediaController(new MediaController(this));4.videoView.setVideoURI(uri);5.videoView.start();6.videoView.requestFocus();3、使用MediaPlayer:1.package demo.camera;2.import java.io.IOException;3.import android.app.Activity;4.import android.media.MediaPlayer;5.import android.media.MediaPlayer.OnCompletionListener;6.import android.media.MediaPlayer.OnErrorListener;7.import android.media.MediaPlayer.OnInfoListener;8.import android.media.MediaPlayer.OnPreparedListener;9.importandroid.media.MediaPlayer.OnSeekCompleteListener;10.importandroid.media.MediaPlayer.OnVideoSizeChangedListener;11.import android.os.Bundle;12.import android.os.Environment;13.import android.util.Log;14.import android.view.Display;15.import android.view.SurfaceHolder;16.import android.view.SurfaceView;17.import android.widget.LinearLayout;18./**19.* 该实例中使用MediaPlayer完成播放,同时界面使用SurfaceView来实现20.*21.* 这里我们实现MediaPlayer中很多状态变化时的监听器22.*23.* 使用Mediaplayer时,也可以使用MediaController类,但是需要实现MediaController.mediaController接口24.* 实现一些控制方法。
Android实现视频播放--腾讯浏览服务(TBS)功能
Android实现视频播放--腾讯浏览服务(TBS)功能TBS视频播放TBS视频播放器可以⽀持市⾯上⼏乎所有的视频格式,包括mp4, flv, avi, 3gp, webm, ts, ogv, m3u8, asf, wmv, rm, rmvb, mov, mkv等18种视频格式。
同时⽀持硬件解码,使得内存占⽤,稳定性相较于系统播放器都更优。
接⼊TBS1.导⼊jar⽂件和so⽂件2.初始化Application⾃定义⼀个Application类,对X5内核进⾏初始化public class MyAppliction extends Application {@Overridepublic void onCreate() {super.onCreate();//回调接⼝初始化完成接⼝回调QbSdk.PreInitCallback pcb=new QbSdk.PreInitCallback() {@Overridepublic void onCoreInitFinished() {}@Overridepublic void onViewInitFinished(boolean b) {//x5內核初始化完成的回调,为true表⽰x5内核加载成功,否则表⽰x5内核加载失败,会⾃动切换到系统内核。
Log.e("myApplication", " x5内核加载成功?" + b);}};//x5内核预加载,异步初始化x5 webview所需环境QbSdk.initX5Environment(getApplicationContext(), pcb);}}在AndroidManifest.xml进⾏声明<application android:name="com.example.xch.tbsvideoplay.MyAppliction"3.使⽤直接在清单⽂件AndroidManifest.xml中配置SDK中的视频播放Activity<activityandroid:name="com.tencent.smtt.sdk.VideoActivity"android:alwaysRetainTaskState="true"android:configChanges="orientation|screenSize|keyboardHidden"android:exported="false"android:launchMode="singleTask"><intent-filter><action android:name="com.tencent.smtt.tbs.video.PLAY" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></activity>在代码中直接调⽤TbsVideo.openVideo()播放/*** 直接调⽤播放视频* @param videoUrl 视频地址*/private void startPlay(String videoUrl){//判断当前是否可⽤if(TbsVideo.canUseTbsPlayer(getApplicationContext())){//播放视频TbsVideo.openVideo(getApplicationContext(), videoUrl);}}4.添加权限<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.READ_SETTINGS" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!-- 硬件加速对X5视频播放有利,建议开启 --><uses-permission android:name="android.permission.GET_TASKS" />效果图优化先看⼀下优化之后的效果⾃定义TBS的WebView,充分发挥X5内核的作⽤1.⾃定义webview需继承TBS的webview,包⼀定不能导错:com.tencent.smtt.sdk.WebView public class X5WebView extends WebView {private WebViewClient client = new WebViewClient() {/*** 防⽌加载⽹页时调起系统浏览器*/public boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}};@SuppressLint("SetJavaScriptEnabled")public X5WebView(Context arg0, AttributeSet arg1) {super(arg0, arg1);this.setWebViewClient(client);initWebViewSettings();this.getView().setClickable(true);}/*** 初始化webview设置*/private void initWebViewSettings() {WebSettings webSetting = this.getSettings();...}/*** 这⾥可以为⾃定义webview绘制背景或⽂字* @param canvas* @param child* @param drawingTime* @return*/@Overrideprotected boolean drawChild(Canvas canvas, View child, long drawingTime) {boolean ret = super.drawChild(canvas, child, drawingTime);canvas.save();...return ret;}public X5WebView(Context arg0) {super(arg0);setBackgroundColor(85621);}}2.布局中使⽤⾃定义WebView<com.example.xch.tbsvideoplay.tools.X5WebViewandroid:id="@+id/x5_webview"android:layout_width="match_parent"android:layout_height="200dp"android:scrollbars="none" />3.使⽤⾃定义WebView播放视频/*** 使⽤⾃定义webview播放视频* @param vedioUrl 视频地址*/private void startPlay(String vedioUrl) {x5webView.loadUrl(vedioUrl);getWindow().setFormat(PixelFormat.TRANSLUCENT);x5webView.getView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);x5webView.setWebChromeClient(new WebChromeClient());}4.⽀持横竖屏切换在AndroidManifest.xml中给当前Activity配置configChanges属性<activityandroid:name="com.example.xch.tbsvideoplay.VideoPlayActivity"android:configChanges="orientation|screenSize|keyboardHidden"/>总结以上所述是⼩编给⼤家介绍的Android实现视频播放--腾讯浏览服务(TBS),希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。
android视频播放简单实现示例(VideoViewMediaPlayer)
android视频播放简单实现⽰例(VideoViewMediaPlayer)如果你看过我的《android⾳乐播放简单实现(MediaPlayer)》,那么本篇将会毫⽆压⼒。
⾸先是主界⾯的三个按钮和⼀个播放控件<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.cofox.myplayvideo.MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/btnPlay"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="Play"android:textAllCaps="false" /><Buttonandroid:id="@+id/btnPause"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="Pause"android:textAllCaps="false" /><Buttonandroid:id="@+id/btnReplay"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="Replay"android:textAllCaps="false" /></LinearLayout><VideoViewandroid:id="@+id/vdvwFilm"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout>在 MainActivity.java 中这⾥需要⽤到的是 VideoView 作为视频播放时的显⽰位置。
30_android视频播放器
// requirePlay = true;
// 重置为初始状态
mediaPlayer.reset();
// 设置音频为流类型
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
// 设置画面输出
// 当有新的Activity打开,SurfaceView会被销毁,当新的Activity关闭后,当前Activity回
// 到前台,SurfaceView会在onResume()之后被重新创建.因此通过回调完成.
// 表层视图会随着activity的状态的变化而销毁
path = Environment.getExternalStorageDirectory() + "/youku.mp4";
} else {
Toast.makeText(this, "文件挂载问题", 1).show();
return;
}
mediaPlayer.setDataSource(path);
/>
</LinearLayout>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop"
android:id="@+id/btnStop"
findViewById(R.id.btnPlay).setOnClickListener(this);
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
android 播放视频播放视频的两种方式:使用VideoView播放视频(方便,推荐)使用MediaPlayer和SurfaceView播放视频(早期的方式)第一种方式:使用VideoView播放视频的步骤如下:在界面布局文件中定义VideoView组件,或在程序中创建VideoView组建调用VideoView的如下两个方法加载指定视频setVideoPath(String paht):加载path文件所代表的视频setVideoURI(URI uri):加载uri所对应的视频调用VideoVIew的start(),stop(),pause()方法来控制视频播放MediaContraller类与VideoView一起结合使用的还有一个MediaContraller类,它的作用时提供一个友好的图形控制界面,通过该控制界面来控制视频的播放,快进键,暂停键,后退键以及播放进度条都是该类提供例子代码:xml布局:?<!--?xml version="1.0"encoding="utf-8"?-->1<linearlayout2 3 4 5 xmlns:android="/apk/res/android "android:ori entation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 定义VideoView 播放视频 --><videoviewandroid:id="@+id/video"android:layout_width="match_parent"android:lay out_height="match_parent"></videoview></linearlayout>Activity : ?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 importjava.io.File;importandroid.app.Activity;importandroid.graphics.PixelFormat;importandroid.os.Bundle;importandroid.widget.MediaController;importandroid.widget.VideoView;publicclassVedioViewTestextendsActivity {VideoView videoView;MediaController mController;@OverridepublicvoidonCreate(Bundle savedInstanceState) {16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 super.onCreate(savedInstanceState);getWindow().setFormat(PixelFormat.TRANSLUCENT);setContentView(yout.main);// 获取界面上VideoView 组件videoView = (VideoView) findViewById(R.id.video);// 创建MediaController 对象mController =newMediaController(this);File video =newFile("/mnt/sdcard/movie.mp4");if(video.exists()) {videoView.setVideoPath(video.getAbsolutePath());//① // 设置videoView 与mController 建立关联videoView.setMediaController(mControl ler);//② // 设置mController 与videoView 建立关联mController.setMediaPlayer(videoView);//③// 让VideoView 获取焦点videoView.requestFocus();}}}第二种方式:使用MediaPlayer 播放视频的步骤如下:创建MediaPlayer 对象,并让它加载指定的视频文件在界面布局文件中定义SurfaceView 组件,或在程序中创建SurfaceView 组件,并为SurfaceView 的SurfaceView 的SurfaceHolder 增加Callback 监听器调用 MediaPlayer 对象的setPisplay(SurfaceHolder sh):将所播放的视频图像输出到指定的SurfaceView 组件调用MediaPlayer 对象的start(),stop(),和pause()方法来控制视频的播放例子代码:xml 布局: ?1234 56 78 9<!--?xml version="1.0"encoding="utf-8"?--><relativelayoutxmlns:android="/apk/res/android "android:ori entation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><surfaceview android:id="@+id/surfaceView"android:layout_width="match_parent"andro id:layout_height="360dp"> <linearlayout android:orientation="horizontal"android:layout_width="match_parent"an droid:layout_height="wrap_content"android:layout_alignparentbottom="t rue"android:gravity="center_horizontal"><imagebuttonandroid:id="@+id/play"android:layout_width="wrap_content"android:layo ut_height="wrap_content"android:src="@drawable/play"><imagebuttonandroid:id="@+id/pause"android:layout_width="wrap_content"android:lay out_height="wrap_content"android:src="@drawable/pause"> <imagebuttonandroid:id="@+id/stop"android:layout_width="wrap_content"android:layo ut_height="wrap_content"android:src="@drawable/stop"></imagebutton></imagebutton></imagebutton></linearlayout></surfaceview></relativelayout>Activity :?1 2 3 4 5 6 7 8 910111213141516171819202122 importjava.io.IOException;importandroid.app.Activity;importandroid.media.AudioManager;importandroid.media.MediaPlayer;importandroid.os.Bundle;importandroid.util.DisplayMetrics; importandroid.view.SurfaceHolder;importandroid.view.SurfaceView;importandroid.view.View;importandroid.view.View.OnClickListener; importandroid.view.WindowManager;youtParams; importandroid.widget.ImageButton;publicclassSurfaceViewPlayVideoextendsActivityimplementsOnClickListener{SurfaceView surfaceView;ImageButton play, pause, stop;MediaPlayer mPlayer;// 记录当前视频的播放位置2324252627282930313233343536373839404142434445 intposition;@OverridepublicvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(yout.main);// 获取界面中的3个按钮play = (ImageButton) findViewById(R.id.play);pause = (ImageButton) findViewById(R.id.pause);stop = (ImageButton) findViewById(R.id.stop);// 为3个按钮的单击事件绑定事件监听器play.setOnClickListener(this);pause.setOnClickListener(this);stop.setOnClickListener(this);// 创建MediaPlayermPlayer =newMediaPlayer();surfaceView = (SurfaceView)this.findViewById(R.id.surfaceView);// 设置播放时打开屏幕surfaceView.getHolder().setKeepScreenOn(true);surfaceView.getHolder().addCallback(newSurfaceListener());}4647484950515253545556575859606162636465666768 @OverridepublicvoidonClick(View source){try{switch(source.getId()){// 播放按钮被单击caseR.id.play:play();break;// 暂停按钮被单击caseR.id.pause:if(mPlayer.isPlaying()) {mPlayer.pause();}else{mPlayer.start();}break;// 停止按钮被单击6970717273747576777879808182838485868788899091 caseR.id.stop:if(mPlayer.isPlaying()) mPlayer.stop();break;}}catch(Exception e){e.printStackTrace();}}privatevoidplay()throwsIOException{mPlayer.reset();mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); // 设置需要播放的视频mPlayer.setDataSource("/mnt/sdcard/movie.3gp");// 把视频画面输出到SurfaceViewmPlayer.setDisplay(surfaceView.getHolder()); //①mPlayer.prepare();// 获取窗口管理器WindowManager wManager = getWindowManager();DisplayMetrics metrics =newDisplayMetrics();92 93 94 95 96979899100101102103104105106107108109110111112113114// 获取屏幕大小wManager.getDefaultDisplay().getMetrics(metrics); // 设置视频保持纵横比缩放到占满整个屏幕surfaceView.setLayoutParams(newLayoutParams(metrics.widthPixels , mPlayer.getVideoHeight() * metrics.widthPixels / mPlayer.getVideoWidth()));mPlayer.start();}privateclassSurfaceListenerimplementsSurfaceHolder.Callback {@OverridepublicvoidsurfaceChanged(SurfaceHolder holder,intformat, intwidth,intheight){}@OverridepublicvoidsurfaceCreated(SurfaceHolder holder){if(position >0){try115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 {// 开始播放play();// 并直接从指定位置开始播放 mPlayer.seekTo(position);position =0;}catch(Exception e){e.printStackTrace();}}}@OverridepublicvoidsurfaceDestroyed(SurfaceHolder holder) {}}// 当其他Activity 被打开,暂停播放@OverrideprotectedvoidonPause()138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 {if(mPlayer.isPlaying()){// 保存当前的播放位置position = mPlayer.getCurrentPosition(); mPlayer.stop();}super.onPause();}@OverrideprotectedvoidonDestroy(){// 停止播放if(mPlayer.isPlaying()) mPlayer.stop(); // 释放资源mPlayer.release();super.onDestroy();}}。