http://www.2cto.com/kf/201703/619114.html
http://www.2cto.com/kf/201703/619114.html
Android ijkplayer的使用解析
ijkplayer是Bilibili基于ffmpeg开发并开源的轻量级视频播放器,支持播放本地网络视频,也支持流媒体播放。支持Android&iOS。
ijkplayer的编译这里不多阐述,我也是直接获取别人编译完成的so库文件,直接使用的。如果你对ijkplayer的编译感兴趣,可以百度一下,有很多文章。
使用ijkplayer
导包
ijkplayer源码官方下载地址:https://github.com/Bilibili/ijkplayer
上面是官方提供的ijkplayer的源码地址,但是它是没有编译过的。下面我给大家分享一份编译好的ijkplayer源码,由于比较大,分了三个包才上传完成,需要三个包都下载后才能一起解压:
编译好的ijkplayer.part1
编译好的ijkplayer.part2
编译好的ijkplayer.part3
我们下载完成,进入android/ijkplayer目录:
<img alt="这里写图片描述" src="http://www.2cto.com/uploadfile/Collfiles/20170329/20170329091248241.png" title="" kf="" ware="" vc="" "="" target="_blank" class="keylink" style="border-width: 0px; padding: 0px; margin: 0px auto; list-style: none; display: block; width: 438px; height: 169px;">vczltcShozwvbGk+DQo8bGk+aWprcGxheWVyLWV4b6O6Z29vZ2xlv6rUtLXE0ru49tDCtcSypbfFxvdFeG9QbGF5ZXKjrNTaRGVtb9bQus1pamtwbGF5ZXK21LHI08O1xKGjzai5/bCy17BpamtwbGF5ZXK/ydLUt6LP1nNldHRpbmfA78Pmv8nS1NGh1PGyu82scGxheWVywLTk1si+tuDDvczlz9TKvqOsuMPEo7/pz8LD5r7NysfSu7j2TWVkaWFQbGF5ZXKhozwvbGk+DQo8bGk+aWprcGxheWVyLWV4YW1wbGWjurLiytSzzNDyPC9saT4NCjxsaT5pamtwbGF5ZXIte2FyY2h9o7qx4NLrs/bAtLXEuPe49rDmsb61xC5zb87EvP6how0KPHA+udm3vczhuam1xERlbW+1xLT6wuu7ucrHzaa24LXEo6zJ9dbBu7nTw8HLb3R0byzQ6NKqttS52be9tcRkZW1vvfjQ0L6rvPKjrMils/3Su9Cp08Oyu7W9tcS0+sLroaM8YnIgLz4NCsrXz8jQ6NKqtcTKx2lqa3BsYXllci17YXJjaH2homlqa3BsYXllci08YSBjbGFzcz0="replace_word" href="http://lib.youkuaiyun.com/base/javase" target="_blank" title="Java SE知识库">Java两个库。exo是Google提供的新的播放器,这里不需要,直接砍掉。其次是ijkplayer-example里的,我们需要的只有tv.danmaku.ijk.media.example.widget.media包下的部分类。
注:
链接库ijkplayer-arm64,ijkplayer-armv5,ijkplayer-armv7a,ijkplayer-x86,ijkplayer-x86_64是不同体系架构的动态链接库,在当前工程结构里面作为一个模块,如果不想做兼容多平台问题,可以删除其他目录结构,单独保留自己需要的平台目录。
新建一个工程:
(1)把ijkplayer-armv7a/src/main/libs下的文件拷贝到新工程app目录的libs下。
(2)把ijkplayer-java/build/outputs/aar/ijkplayer-java-release.aar复制到新工程app目录的libs下。
(3)修改APP下的build.gradle, 主要设置.so及.aar的位置:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
apply plugin:
'com.android.application'
android {
compileSdkVersion
24
buildToolsVersion
"25.0.0"
defaultConfig {
applicationId
"com.hx.ijkplayer_demo"
minSdkVersion
14
targetSdkVersion
24
versionCode
1
versionName
"1.0"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled
false
proguardFiles getDefaultProguardFile(
'proguard-android.txt'
),
'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = [
'libs'
]
/**在libs文件夹下找so文件*/
}
}
}
repositories {
mavenCentral()
flatDir {
dirs
'libs'
/**在libs文件夹下找aar文件*/
}
}
dependencies {
compile fileTree(dir:
'libs'
, include: [
'*.jar'
])
androidTestCompile(
'com.android.support.test.espresso:espresso-core:2.2.2'
, {
exclude group:
'com.android.support'
, module:
'support-annotations'
})
compile
'com.android.support:appcompat-v7:24.2.1'
testCompile
'junit:junit:4.12'
compile(name:
'ijkplayer-java-release'
, ext:
'aar'
)
/**编译ijkplayer-java-release.aar文件*/
}
|
(4)复制ijkplayer-example下面的tv.danmaku.ijk.media.example.widget.media到新的工程,删掉一些不需要类。

(5)IjkVideoView里面还是有很多如exo等没用的东西,删!具体可以参见我后面的Demo。
(6)Manifest
|
1
2
3
4
5
6
|
...
...
</activity>
..
<uses-permission android:name=
"android.permission.INTERNET"
></uses-permission>
|
播放实现
Xml代码
|
1
2
3
4
5
|
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<relativelayout android:layout_height=
"match_parent"
android:layout_width=
"match_parent"
tools:context=
".MainActivity"
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
>
<com.hx.ijkplayer_demo.widget.media.ijkvideoview android:id=
"@+id/video_view"
android:layout_height=
"match_parent"
android:layout_width=
"match_parent"
>
</com.hx.ijkplayer_demo.widget.media.ijkvideoview></relativelayout>
|
Java代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public
class
MainActivity
extends
AppCompatActivity {
private
IjkVideoView videoView;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
videoView = (IjkVideoView) findViewById(R.id.video_view);
videoView.setAspectRatio(IRenderView.AR_ASPECT_FIT_PARENT);
videoView.start();
}
}
|
常用函数
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
/**
* 参数aspectRatio(缩放参数)参见IRenderView的常量:IRenderView.AR_ASPECT_FIT_PARENT,
IRenderView.AR_ASPECT_FILL_PARENT,
IRenderView.AR_ASPECT_WRAP_CONTENT,
IRenderView.AR_MATCH_PARENT,
IRenderView.AR_16_9_FIT_PARENT,
IRenderView.AR_4_3_FIT_PARENT
*/
public
void
setAspectRatio(
int
aspectRatio);
//改变视频缩放状态。
public
int
toggleAspectRatio();
//设置视频路径。
public
void
setVideoPath(String path);
//设置视频URI。(可以是网络视频地址)
public
void
setVideoURI(Uri uri);
//停止视频播放,并释放资源。
public
void
stopPlayback();
/**
* 设置媒体控制器。
* 参数controller:媒体控制器,注意是com.hx.ijkplayer_demo.widget.media.IMediaController。
*/
public
void
setMediaController(IMediaController controller);
//改变媒体控制器显隐
private
void
toggleMediaControlsVisiblity();
//注册一个回调函数,在视频预处理完成后调用。在视频预处理完成后被调用。此时视频的宽度、高度、宽高比信息已经获取到,此时可调用seekTo让视频从指定位置开始播放。
public
void
setOnPreparedListener(OnPreparedListener l);
//播放完成回调
public
void
setOnCompletionListener(IMediaPlayer.OnCompletionListener l);
//播放错误回调
public
void
setOnErrorListener(IMediaPlayer.OnErrorListener l);
//事件发生回调
public
void
setOnInfoListener(IMediaPlayer.OnInfoListener l);
//获取总长度
public
int
getDuration();
//获取当前播放位置。
public
long
getCurrentPosition();
//设置播放位置。单位毫秒
public
void
seekTo(
long
msec);
//是否正在播放。
public
boolean
isPlaying();
//获取缓冲百分比。
public
int
getBufferPercentage();
|
封装ijkplayer
上面只是ijkplayer的一个基本用法。我们可以对ijkplayer进行一次封装,让ijkplayer使用起来更加简单。
功能:
- 使用Vitamio的VideoView进行视频播放
- 视频左侧界面(左1/2以内)上下滑动调节亮度
- 视频右侧界面(右1/2以外)上下滑动调节声音
- 双击切换视频窗口布局
- 非直播状态,可以左右滑动调节当前播放进度
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
publicclassPlayerManager {/*** 可能会剪裁,保持原视频的大小,显示在中心,当原视频的大小超过view的大小超过部分裁剪处理*/publicstaticfinalString SCALETYPE_FITPARENT="fitParent";/*** 可能会剪裁,等比例放大视频,直到填满View为止,超过View的部分作裁剪处理*/publicstaticfinalString SCALETYPE_FILLPARENT="fillParent";/*** 将视频的内容完整居中显示,如果视频大于view,则按比例缩视频直到完全显示在view中*/publicstaticfinalString SCALETYPE_WRAPCONTENT="wrapContent";/*** 不剪裁,非等比例拉伸画面填满整个View*/publicstaticfinalString SCALETYPE_FITXY="fitXY";/*** 不剪裁,非等比例拉伸画面到16:9,并完全显示在View中*/publicstaticfinalString SCALETYPE_16_9="16:9";/*** 不剪裁,非等比例拉伸画面到4:3,并完全显示在View中*/publicstaticfinalString SCALETYPE_4_3="4:3";/*** 状态常量*/privatefinalintSTATUS_ERROR=-1;privatefinalintSTATUS_IDLE=0;privatefinalintSTATUS_LOADING=1;privatefinalintSTATUS_PLAYING=2;privatefinalintSTATUS_PAUSE=3;privatefinalintSTATUS_COMPLETED=4;privatefinalActivity activity;privatefinalIjkVideoView videoView;privatefinalAudioManager audioManager;publicGestureDetector gestureDetector;privatebooleanplayerSupport;privatebooleanisLive =false;//是否为直播privatebooleanfullScreenOnly;privatebooleanportrait;privatefinalintmMaxVolume;privateintscreenWidthPixels;privateintcurrentPosition;privateintstatus=STATUS_IDLE;privatelongpauseTime;privateString url;privatefloatbrightness=-1;privateintvolume=-1;privatelongnewPosition = -1;privatelongdefaultRetryTime=5000;privateOrientationEventListener orientationEventListener;privatePlayerStateListener playerStateListener;publicvoidsetPlayerStateListener(PlayerStateListener playerStateListener) {this.playerStateListener = playerStateListener;}privateOnErrorListener onErrorListener=newOnErrorListener() {@OverridepublicvoidonError(intwhat,intextra) {}};privateOnCompleteListener onCompleteListener=newOnCompleteListener() {@OverridepublicvoidonComplete() {}};privateOnInfoListener onInfoListener=newOnInfoListener(){@OverridepublicvoidonInfo(intwhat,intextra) {}};privateOnControlPanelVisibilityChangeListener onControlPanelVisibilityChangeListener=newOnControlPanelVisibilityChangeListener() {@Overridepublicvoidchange(booleanisShowing) {}};/*** try to play when error(only for live video)* @param defaultRetryTime millisecond,0 will stop retry,default is 5000 millisecond*/publicvoidsetDefaultRetryTime(longdefaultRetryTime) {this.defaultRetryTime = defaultRetryTime;}publicPlayerManager(finalActivity activity) {try{IjkMediaPlayer.loadLibrariesOnce(null);IjkMediaPlayer.native_profileBegin("libijkplayer.so");playerSupport=true;}catch(Throwable e) {Log.e("GiraffePlayer","loadLibraries error", e);}this.activity=activity;screenWidthPixels = activity.getResources().getDisplayMetrics().widthPixels;videoView = (IjkVideoView) activity.findViewById(R.id.video_view);videoView.setOnCompletionListener(newIMediaPlayer.OnCompletionListener() {@OverridepublicvoidonCompletion(IMediaPlayer mp) {statusChange(STATUS_COMPLETED);onCompleteListener.onComplete();}});videoView.setOnErrorListener(newIMediaPlayer.OnErrorListener() {@OverridepublicbooleanonError(IMediaPlayer mp,intwhat,intextra) {statusChange(STATUS_ERROR);onErrorListener.onError(what,extra);returntrue;}});videoView.setOnInfoListener(newIMediaPlayer.OnInfoListener() {@OverridepublicbooleanonInfo(IMediaPlayer mp,intwhat,intextra) {switch(what) {caseIMediaPlayer.MEDIA_INFO_BUFFERING_START:statusChange(STATUS_LOADING);break;caseIMediaPlayer.MEDIA_INFO_BUFFERING_END:statusChange(STATUS_PLAYING);break;caseIMediaPlayer.MEDIA_INFO_NETWORK_BANDWIDTH://显示下载速度// Toast.show("download rate:" + extra);break;caseIMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:statusChange(STATUS_PLAYING);break;}onInfoListener.onInfo(what,extra);returnfalse;}});audioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);mMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);gestureDetector =newGestureDetector(activity,newPlayerGestureListener());if(fullScreenOnly) {activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);}portrait=getScreenOrientation()== ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;if(!playerSupport) {DebugLog.e("播放器不支持此设备");}}privatevoidstatusChange(intnewStatus) {status = newStatus;if(!isLive && newStatus==STATUS_COMPLETED) {DebugLog.d("statusChange STATUS_COMPLETED...");if(playerStateListener !=null){playerStateListener.onComplete();}}elseif(newStatus == STATUS_ERROR) {DebugLog.d("statusChange STATUS_ERROR...");if(playerStateListener !=null){playerStateListener.onError();}}elseif(newStatus==STATUS_LOADING){// $.id(R.id.app_video_loading).visible();if(playerStateListener !=null){playerStateListener.onLoading();}DebugLog.d("statusChange STATUS_LOADING...");}elseif(newStatus == STATUS_PLAYING) {DebugLog.d("statusChange STATUS_PLAYING...");if(playerStateListener !=null){playerStateListener.onPlay();}}}publicvoidonPause() {pauseTime= System.currentTimeMillis();if(status==STATUS_PLAYING) {videoView.pause();if(!isLive) {currentPosition = videoView.getCurrentPosition();}}}publicvoidonResume() {pauseTime=0;if(status==STATUS_PLAYING) {if(isLive) {videoView.seekTo(0);}else{if(currentPosition>0) {videoView.seekTo(currentPosition);}}videoView.start();}}publicvoidonDestroy() {orientationEventListener.disable();videoView.stopPlayback();}publicvoidplay(String url) {this.url = url;if(playerSupport) {videoView.setVideoPath(url);videoView.start();}}privateString generateTime(longtime) {inttotalSeconds = (int) (time /1000);intseconds = totalSeconds %60;intminutes = (totalSeconds /60) %60;inthours = totalSeconds /3600;returnhours >0? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d", minutes, seconds);}privateintgetScreenOrientation() {introtation = activity.getWindowManager().getDefaultDisplay().getRotation();DisplayMetrics dm =newDisplayMetrics();activity.getWindowManager().getDefaultDisplay().getMetrics(dm);intwidth = dm.widthPixels;intheight = dm.heightPixels;intorientation;// if the device's natural orientation is portrait:if((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) && height > width ||(rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) && width > height) {switch(rotation) {caseSurface.ROTATION_0:orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;break;caseSurface.ROTATION_90:orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;break;caseSurface.ROTATION_180:orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;break;caseSurface.ROTATION_270:orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;break;default:orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;break;}}// if the device's natural orientation is landscape or if the device// is square:else{switch(rotation) {caseSurface.ROTATION_0:orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;break;caseSurface.ROTATION_90:orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;break;caseSurface.ROTATION_180:orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;break;caseSurface.ROTATION_270:orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;break;default:orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;break;}}returnorientation;}/*** 滑动改变声音大小** @param percent*/privatevoidonVolumeSlide(floatpercent) {if(volume == -1) {volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);if(volume <0)volume =0;}intindex = (int) (percent * mMaxVolume) + volume;if(index > mMaxVolume) {index = mMaxVolume;}elseif(index <0){index =0;}// 变更声音audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index,0);// 变更进度条inti = (int) (index *1.0/ mMaxVolume *100);String s = i +"%";if(i ==0) {s ="off";}DebugLog.d("onVolumeSlide:"+s);}privatevoidonProgressSlide(floatpercent) {longposition = videoView.getCurrentPosition();longduration = videoView.getDuration();longdeltaMax = Math.min(100*1000, duration - position);longdelta = (long) (deltaMax * percent);newPosition = delta + position;if(newPosition > duration) {newPosition = duration;}elseif(newPosition <=0) {newPosition=0;delta=-position;}intshowDelta = (int) delta /1000;if(showDelta !=0) {String text = showDelta >0? ("+"+ showDelta) :""+ showDelta;DebugLog.d("onProgressSlide:"+ text);}}/*** 滑动改变亮度** @param percent*/privatevoidonBrightnessSlide(floatpercent) {if(brightness <0) {brightness = activity.getWindow().getAttributes().screenBrightness;if(brightness <=0.00f){brightness =0.50f;}elseif(brightness <0.01f){brightness =0.01f;}}DebugLog.d("brightness:"+brightness+",percent:"+ percent);WindowManager.LayoutParams lpa = activity.getWindow().getAttributes();lpa.screenBrightness = brightness + percent;if(lpa.screenBrightness >1.0f){lpa.screenBrightness =1.0f;}elseif(lpa.screenBrightness <0.01f){lpa.screenBrightness =0.01f;}activity.getWindow().setAttributes(lpa);}publicvoidsetFullScreenOnly(booleanfullScreenOnly) {this.fullScreenOnly = fullScreenOnly;tryFullScreen(fullScreenOnly);if(fullScreenOnly) {activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);}else{activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);}}privatevoidtryFullScreen(booleanfullScreen) {if(activityinstanceofAppCompatActivity) {ActionBar supportActionBar = ((AppCompatActivity) activity).getSupportActionBar();if(supportActionBar !=null) {if(fullScreen) {supportActionBar.hide();}else{supportActionBar.show();}}}setFullScreen(fullScreen);}privatevoidsetFullScreen(booleanfullScreen) {if(activity !=null) {WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();if(fullScreen) {attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;activity.getWindow().setAttributes(attrs);activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);}else{attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);activity.getWindow().setAttributes(attrs);activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);}}}/**** @param scaleType */ public void setScaleType(String scaleType) { if (SCALETYPE_FITPARENT.equals(scaleType)) { videoView.setAspectRatio(IRenderView.AR_ASPECT_FIT_PARENT); }else if (SCALETYPE_FILLPARENT.equals(scaleType)) { videoView.setAspectRatio(IRenderView.AR_ASPECT_FILL_PARENT); }else if (SCALETYPE_WRAPCONTENT.equals(scaleType)) { videoView.setAspectRatio(IRenderView.AR_ASPECT_WRAP_CONTENT); }else if (SCALETYPE_FITXY.equals(scaleType)) { videoView.setAspectRatio(IRenderView.AR_MATCH_PARENT); }else if (SCALETYPE_16_9.equals(scaleType)) { videoView.setAspectRatio(IRenderView.AR_16_9_FIT_PARENT); }else if (SCALETYPE_4_3.equals(scaleType)) { videoView.setAspectRatio(IRenderView.AR_4_3_FIT_PARENT); } } public void start() { videoView.start(); } public void pause() { videoView.pause(); } public boolean onBackPressed() { if (!fullScreenOnly && getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); return true; } return false; } class Query { private final Activity activity; private View view; public Query(Activity activity) { this.activity=activity; } public Query id(int id) { view = activity.findViewById(id); return this; } public Query image(int resId) { if (view instanceof ImageView) { ((ImageView) view).setImageResource(resId); } return this; } public Query visible() { if (view != null) { view.setVisibility(View.VISIBLE); } return this; } public Query gone() { if (view != null) { view.setVisibility(View.GONE); } return this; } public Query invisible() { if (view != null) { view.setVisibility(View.INVISIBLE); } return this; } public Query clicked(View.OnClickListener handler) { if (view != null) { view.setOnClickListener(handler); } return this; } public Query text(CharSequence text) { if (view!=null && view instanceof TextView) { ((TextView) view).setText(text); } return this; } public Query visibility(int visible) { if (view != null) { view.setVisibility(visible); } return this; } private void size(boolean width, int n, boolean dip){ if(view != null){ ViewGroup.LayoutParams lp = view.getLayoutParams(); if(n > 0 && dip){ n = dip2pixel(activity, n); } if(width){ lp.width = n; }else{ lp.height = n; } view.setLayoutParams(lp); } } public void height(int height, boolean dip) { size(false,height,dip); } public int dip2pixel(Context context, float n){ int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, n, context.getResources().getDisplayMetrics()); return value; } public float pixel2dip(Context context, float n){ Resources resources = context.getResources(); DisplayMetrics metrics = resources.getDisplayMetrics(); float dp = n / (metrics.densityDpi / 160f); return dp; } } public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListener { private boolean firstTouch; private boolean volumeControl; private boolean toSeek; /** * 双击 */ @Override public boolean onDoubleTap(MotionEvent e) { videoView.toggleAspectRatio(); return true; } @Override public boolean onDown(MotionEvent e) { firstTouch = true; return super.onDown(e); } /** * 滑动 */ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { float mOldX = e1.getX(), mOldY = e1.getY(); float deltaY = mOldY - e2.getY(); float deltaX = mOldX - e2.getX(); if (firstTouch) { toSeek = Math.abs(distanceX) >= Math.abs(distanceY); volumeControl=mOldX > screenWidthPixels * 0.5f; firstTouch = false; } if (toSeek) { if (!isLive) { onProgressSlide(-deltaX / videoView.getWidth()); } } else { float percent = deltaY / videoView.getHeight(); if (volumeControl) { onVolumeSlide(percent); } else { onBrightnessSlide(percent); } } return super.onScroll(e1, e2, distanceX, distanceY); } @Override public boolean onSingleTapUp(MotionEvent e) { return true; } } /** * is player support this device * @return */ public boolean isPlayerSupport() { return playerSupport; } /** * 是否正在播放 * @return */ public boolean isPlaying() { return videoView!=null?videoView.isPlaying():false; } public void stop(){ videoView.stopPlayback(); } public int getCurrentPosition(){ return videoView.getCurrentPosition(); } /** * get video duration * @return */ public int getDuration(){ return videoView.getDuration(); } public PlayerManager playInFullScreen(boolean fullScreen){ if (fullScreen) { activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } return this; } public PlayerManager onError(OnErrorListener onErrorListener) { this.onErrorListener = onErrorListener; return this; } public PlayerManager onComplete(OnCompleteListener onCompleteListener) { this.onCompleteListener = onCompleteListener; return this; } public PlayerManager onInfo(OnInfoListener onInfoListener) { this.onInfoListener = onInfoListener; return this; } public PlayerManager onControlPanelVisibilityChange(OnControlPanelVisibilityChangeListener listener){ this.onControlPanelVisibilityChangeListener = listener; return this; } /** * set is live (can't seek forward) * @param isLive * @return */ public PlayerManager live(boolean isLive) { this.isLive = isLive; return this; } public PlayerManager toggleAspectRatio(){ if (videoView != null) { videoView.toggleAspectRatio(); } return this; } public interface PlayerStateListener{ void onComplete(); void onError(); void onLoading(); void onPlay(); } public interface OnErrorListener{ void onError(int what, int extra); } public interface OnCompleteListener{ void onComplete(); } public interface OnControlPanelVisibilityChangeListener{ void change(boolean isShowing); } public interface OnInfoListener{ void onInfo(int what, int extra); } }1* fitParent:可能会剪裁,保持原视频的大小,显示在中心,当原视频的大小超过view的大小超过部分裁剪处理 * fillParent:可能会剪裁,等比例放大视频,直到填满View为止,超过View的部分作裁剪处理 * wrapContent:将视频的内容完整居中显示,如果视频大于view,则按比例缩视频直到完全显示在view中 * fitXY:不剪裁,非等比例拉伸画面填满整个View *16:9:不剪裁,非等比例拉伸画面到16:9,并完全显示在View中 *4:3:不剪裁,非等比例拉伸画面到4:3,并完全显示在View中 *使用封装后的PlayerManager播放视频:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546publicclassMainActivityextendsAppCompatActivityimplementsPlayerManager.PlayerStateListener{privatePlayerManager player;@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initPlayer();}privatevoidinitPlayer() {player =newPlayerManager(this);player.setFullScreenOnly(true);player.setScaleType(PlayerManager.SCALETYPE_FILLPARENT);player.playInFullScreen(true);player.setPlayerStateListener(this);player.play(url1);}@OverridepublicbooleanonTouchEvent(MotionEvent event) {if(player.gestureDetector.onTouchEvent(event))returntrue;returnsuper.onTouchEvent(event);}@OverridepublicvoidonComplete() {}@OverridepublicvoidonError() {}@OverridepublicvoidonLoading() {}@OverridepublicvoidonPlay() {}}
2560

被折叠的 条评论
为什么被折叠?



