19-监听播放外界网络和本地视频&如何调起其他播放器
19.1监听播放外界网络和本地视频,参照Gallery3D代码
<activity
android:name="com.atguigu.mobileplayer.video.VideoPlayerActivity"
android:configChanges="keyboardHidden|screenSize|orientation"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="rtsp" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
<data android:mimeType="application/sdp" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:mimeType="video/mpeg4" />
<data android:mimeType="video/mp4" />
<data android:mimeType="video/3gp" />
<data android:mimeType="video/3gpp" />
<data android:mimeType="video/3gpp2" />
</intent-filter>
</activity>
19.2 加载等待效果
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_player_loading_background"
android:gravity="center"
android:orientation="vertical">
<ProgressBar
android:layout_width="30dp"
android:layout_height="30dp" />
<TextView
android:layout_marginTop="3dp"
android:id="@+id/tv_laoding_netspeed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:gravity="center"
android:text="玩命加载中...30kb/s"
android:textColor="#ffffff"
android:textSize="10sp" />
</LinearLayout>
播放器控制面板设置为隐藏不可见
视频播放出来后隐藏加载等待页面
//隐藏加载页面
//把加载页面消失掉
ll_loading.setVisibility(View.GONE);
19.3 解决播放完成后的崩溃
/**
* 播放下一个视频
*/
private void playNextVideo()
{
if (mediaItems != null && mediaItems.size() > 0)
{
//播放下一个
position++;
if (position < mediaItems.size())
{
ll_loading.setVisibility(View.VISIBLE);
MediaItem mediaItem = mediaItems.get(position);
tvName.setText(mediaItem.getName());
isNetUri = utils.isNetUri(mediaItem.getData());
videoview.setVideoPath(mediaItem.getData());
//设置按钮状态
setButtonState();
}
}
else if (uri != null)
{
//设置按钮状态-上一个和下一个按钮设置灰色并且不可以点击
setButtonState();
}
}
/**
* 播放上一个视频
*/
private void playPreVideo()
{
if (mediaItems != null && mediaItems.size() > 0)
{
//播放上一个视频
position--;
if (position >= 0)
{
ll_loading.setVisibility(View.VISIBLE);
MediaItem mediaItem = mediaItems.get(position);
tvName.setText(mediaItem.getName());
isNetUri = utils.isNetUri(mediaItem.getData());
videoview.setVideoPath(mediaItem.getData());
//设置按钮状态
setButtonState();
}
}
else if (uri != null)
{
//设置按钮状态-上一个和下一个按钮设置灰色并且不可以点击
setButtonState();
}
}
19.4 处理播放外界资源的时候,下一个视频按钮和上一个要变灰
private void setButtonState()
{
if (mediaItems != null && mediaItems.size() > 0)
{
if (mediaItems.size() == 1)
{
setEnable(false);
}
else if (mediaItems.size() == 2)
{
if (position == 0)
{
btnVideoPre.setBackgroundResource(R.drawable.btn_pre_gray);
btnVideoPre.setEnabled(false);
btnVideoNext.setBackgroundResource(R.drawable.btn_video_next_selector);
btnVideoNext.setEnabled(true);
}
else if (position == mediaItems.size() - 1)
{
btnVideoNext.setBackgroundResource(R.drawable.btn_next_gray);
btnVideoNext.setEnabled(false);
btnVideoPre.setBackgroundResource(R.drawable.btn_video_pre_selector);
btnVideoPre.setEnabled(true);
}
}
else
{
if (position == 0)
{
btnVideoPre.setBackgroundResource(R.drawable.btn_pre_gray);
btnVideoPre.setEnabled(false);
}
else if (position == mediaItems.size() - 1)
{
btnVideoNext.setBackgroundResource(R.drawable.btn_next_gray);
btnVideoNext.setEnabled(false);
}
else
{
setEnable(true);
}
}
}
else if (uri != null)
{
//两个按钮设置灰色
setEnable(false);
}
}
private void setEnable(boolean isEnable)
{
if (isEnable)
{
btnVideoPre.setBackgroundResource(R.drawable.btn_video_pre_selector);
btnVideoPre.setEnabled(true);
btnVideoNext.setBackgroundResource(R.drawable.btn_video_next_selector);
btnVideoNext.setEnabled(true);
}
else
{
//两个按钮设置灰色
btnVideoPre.setBackgroundResource(R.drawable.btn_pre_gray);
btnVideoPre.setEnabled(false);
btnVideoNext.setBackgroundResource(R.drawable.btn_next_gray);
btnVideoNext.setEnabled(false);
}
}
20-判断uri是否网络资源&支持显示缓冲进度&手机播放电脑tomcat资源
20.1 判断是否是网络的资源
/**
* 判断是否是网络的资源
*
* @param uri
* @return
*/
public boolean isNetUri(String uri)
{
boolean reault = false;
if (uri != null)
{
if (uri.toLowerCase().startsWith("http") || uri.toLowerCase().startsWith("rtsp") || uri.toLowerCase().startsWith("mms"))
{
reault = true;
}
}
return reault;
}
20.2 在hanlder设置播放网络视频时候支持显示缓存进度
//缓存进度的更新
if (isNetUri)
{
//只有网络资源才有缓存效果
int buffer = videoview.getBufferPercentage();
int totalBuffer = buffer * seekbarVideo.getMax();
int secondaryProgress = totalBuffer / 100;
seekbarVideo.setSecondaryProgress(secondaryProgress);
}
21-监听卡并且提示&监听拖动完成&显示网速
21.1 监听卡并且提示
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#33000000"
android:gravity="center"
android:orientation="horizontal"
android:padding="3dp"
android:visibility="gone">
<ProgressBar
android:layout_width="30dp"
android:layout_height="30dp" />
<TextView
android:id="@+id/tv_buffer_netspeed"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:gravity="center"
android:text="缓存中...30kb/s"
android:textColor="#ffffff"
android:textSize="10sp" />
</LinearLayout>
21.2监听拖动完成
//播放完成了的监听
videoview.setOnCompletionListener(new MyOnCompletionListener());
class MyOnCompletionListener implements MediaPlayer.OnCompletionListener
{
@Override
public void onCompletion(MediaPlayer mp)
{
playNextVideo();
// Toast.makeText(SystemVideoPlayer.this, "播放完成了="+uri, Toast.LENGTH_SHORT).show();
}
}
private long lastTotalRxBytes = 0;
private long lastTimeStamp = 0;
/**
* 得到网络速度
* 每隔两秒调用一次
*
* @param context
* @return
*/
public String getNetSpeed(Context context)
{
String netSpeed = "0 kb/s";
long nowTotalRxBytes = TrafficStats.getUidRxBytes(context.getApplicationInfo().uid) == TrafficStats.UNSUPPORTED ? 0 : (TrafficStats.getTotalRxBytes() / 1024);//转为KB;
long nowTimeStamp = System.currentTimeMillis();
long speed = ((nowTotalRxBytes - lastTotalRxBytes) * 1000 / (nowTimeStamp - lastTimeStamp));//毫秒转换
lastTimeStamp = nowTimeStamp;
lastTotalRxBytes = nowTotalRxBytes;
netSpeed = String.valueOf(speed) + " kb/s";
return netSpeed;
}
22-监听播放出错的处理
//播放出错了的监听
videoview.setOnErrorListener(new MyOnErrorListener());
class MyOnErrorListener implements MediaPlayer.OnErrorListener
{
@Override
public boolean onError(MediaPlayer mp, int what, int extra)
{
// Toast.makeText(SystemVideoPlayer.this, "播放出错了哦", Toast.LENGTH_SHORT).show();
startVitamioPlayer();
return true;
}
}
23-添加Vitamio插件变成万能播放器
23.1,拷贝权限到项目中来
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
23.2 拷贝InitActivity的,在功能清单文件配置,代码如下:
<!-- Don't forgot InitActivity -->
<activity
android:name="io.vov.vitamio.activity.InitActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:launchMode="singleTop"
android:theme="@android:style/Theme.NoTitleBar"
android:windowSoftInputMode="stateAlwaysHidden" />
23.3,新创建一个Activity名字叫VitamioVideoPlayerActivity
重新创建布局文件activity_vitamio_videoplayer.xml,把布局文件里面的系统的VideoView换成Vitamio的VideoView,导入的包都要换成是Vitamio的
<io.vov.vitamio.widget.VideoView
android:id="@+id/surface_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
23.4.需要把VitamioVideoPlayerActivity在功能清单文件里面注册
<activity android:name=".VitamioVideoPlayerActivity"
android:configChanges="keyboardHidden|screenSize|orientation"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
/>
23.5,要在加载布局文件之前,初始化解码器
Vitamio.isInitialized(this);
23.6,当系统播放器出错的时候,记得跳转到Vitmaio播放中,并且不要忘记携带数据
/**
* 启动Vitamio解码播放器
* a,把数据按照原样传入VtaimoVideoPlayer播放器
* b,关闭系统播放器
*/
private void startVitamioPlayer()
{
if(videoview!=null)
{
videoview.stopPlayback();
}
Intent intent = new Intent(this, VitamioVideoPlayer.class);
if(mediaItems!=null && mediaItems.size()>0)
{
Bundle bundle = new Bundle();
bundle.putSerializable("videolist",mediaItems);
intent.putExtras(bundle);
intent.putExtra("position",position);
}
else if(uri!=null)
{
intent.setData(uri);
}
startActivity(intent);
finish();//关闭页面
}
24-当万能播放器播放失败的提示
24.1 当播放出错回调
//播放出错了的监听
videoview.setOnErrorListener(new MyOnErrorListener());
class MyOnErrorListener implements MediaPlayer.OnErrorListener
{
@Override
public boolean onError(MediaPlayer mp, int what, int extra)
{
// Toast.makeText(SystemVideoPlayer.this, "播放出错了哦", Toast.LENGTH_SHORT).show();
showErrorDialog();
//1.播放的视频格式不支持--跳转到万能播放器继续播放
//2.播放网络视频的时候,网络中断---1.如果网络确实断了,可以提示用于网络断了;2.网络断断续续的,重新播放
//3.播放的时候本地文件中间有空白---下载做完成
return true;
}
}
private void showErrorDialog()
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("提示");
builder.setMessage("抱歉,无法播放该视频!!");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
finish();
}
});
builder.show();
}
25-人为切换系统和万能播放器
25.1 系统播放器和万能播放器手动切换
/**
* 切换播放器系统-->万能解码(Vitamio框架)
*/
private void showSwichPlayerDialog()
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("系统播放器提醒您");
builder.setMessage("当您播放视频,有声音没有画面的时候,请切换万能播放器播放");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
startVitamioPlayer();
}
});
builder.setNegativeButton("取消", null);
builder.show();
}
/**
* 设置标题和播放数据
*/
private void setData()
{
if (mediaItems != null && mediaItems.size() > 0)
{
MediaItem mediaItem = mediaItems.get(position);
tvName.setText(mediaItem.getName());//设置视频的名称
isNetUri = utils.isNetUri(mediaItem.getData());
videoview.setVideoPath(mediaItem.getData());
}
else if (uri != null)
{
tvName.setText(uri.toString());//设置视频的名称
isNetUri = utils.isNetUri(uri.toString());
videoview.setVideoURI(uri);
}
else
{
Toast.makeText(VitamioVideoPlayer.this, "帅哥你没有传递数据", Toast.LENGTH_SHORT).show();
}
setButtonState();
}
25.3-屏蔽系统播放器和Vitamio播放器切换的动画
<style name="noAnimation_Theme" parent="android:Theme">
<item name="android:windowAnimationStyle">@style/noAnimation</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="noAnimation">
<item name="android:activityOpenEnterAnimation">@null</item>
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:activityCloseEnterAnimation">@null</item>
<item name="android:activityCloseExitAnimation">@null</item>
<item name="android:taskOpenEnterAnimation">@null</item>
<item name="android:taskOpenExitAnimation">@null</item>
<item name="android:taskCloseEnterAnimation">@null</item>
<item name="android:taskCloseExitAnimation">@null</item>
<item name="android:taskToFrontEnterAnimation">@null</item>
<item name="android:taskToFrontExitAnimation">@null</item>
<item name="android:taskToBackEnterAnimation">@null</item>
<item name="android:taskToBackExitAnimation">@null</item>
</style>
使用样式:
<activity android:name=".videoplayer.VitamioVideoPlayerActivity"
android:screenOrientation="landscape"
android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:theme="@style/noAnimation_Theme"/>
26-网络视频&xUtils3请求
26.1 xUtils3联网请求
/**
* 从网络中加载视频数据
*/
private void getDataFromNet()
{
//联网
//视频内容
RequestParams requestParams = new RequestParams(Constants.NET_URL);
x.http().get(requestParams, new Callback.CommonCallback<String>()
{
@Override
public void onSuccess(String result)
{
LogUtil.e("联网成功==" + result);
//缓存数据
CacheUtils.putString(context, Constants.NET_URL, result);
//主线程
processData(result);
}
@Override
public void onError(Throwable ex, boolean isOnCallback)
{
LogUtil.e("联网失败==" + ex.getMessage());
showData();
}
@Override
public void onCancelled(CancelledException cex)
{
LogUtil.e("onCancelled==" + cex.getMessage());
}
@Override
public void onFinished()
{
LogUtil.e("onFinished==");
}
});
}
26.2 Json解析
/**
* 处理Json数据
*
* @param json
*/
private void processData(String json)
{
if (!isLoadMore)
{
mediaItems = parseJson(json);
showData();
}
else
{
//加载更多
//要把得到更多的数据,添加到原来的集合中
// ArrayList<MediaItem> moreDatas = parseJson(json);
isLoadMore = false;
mediaItems.addAll(parseJson(json));
adapter.notifyDataSetChanged();
onLoad();
}
}
/**
* 解决json数据:
* 1.用系统接口解析json数据
* 2.使用第三方解决工具(Gson,fastjson)
*
* @param json
* @return
*/
private ArrayList<MediaItem> parseJson(String json)
{
ArrayList<MediaItem> mediaItems = new ArrayList<>();
try
{
JSONObject jsonObject = new JSONObject(json);
JSONArray jsonArray = jsonObject.optJSONArray("trailers");
if (jsonArray != null && jsonArray.length() > 0)
{
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject jsonObjectItem = (JSONObject) jsonArray.get(i);
if (jsonObjectItem != null)
{
MediaItem mediaItem = new MediaItem();
String movieName = jsonObjectItem.optString("movieName");
mediaItem.setName(movieName);
String videoTitle = jsonObjectItem.optString("videoTitle");//desc
mediaItem.setDesc(videoTitle);
String imageUrl = jsonObjectItem.optString("coverImg");//imageUrl
mediaItem.setImageUrl(imageUrl);
String hightUrl = jsonObjectItem.optString("hightUrl");//data
mediaItem.setData(hightUrl);
//把数据添加到集合
mediaItems.add(mediaItem);
}
}
}
}
catch (JSONException e)
{
e.printStackTrace();
}
return mediaItems;
}
27-视频列表集成xListView支持下拉刷新&加载更多
/**
* 上拉刷新加载更多
*/
private void getMoreDataFromNet()
{
//联网
//视频内容
RequestParams params = new RequestParams(Constants.NET_URL);
x.http().get(params, new Callback.CommonCallback<String>()
{
@Override
public void onSuccess(String result)
{
LogUtil.e("联网成功==" + result);
isLoadMore = true;
//主线程
processData(result);
}
@Override
public void onError(Throwable ex, boolean isOnCallback)
{
LogUtil.e("联网失败==" + ex.getMessage());
isLoadMore = false;
}
@Override
public void onCancelled(CancelledException cex)
{
LogUtil.e("onCancelled==" + cex.getMessage());
isLoadMore = false;
}
@Override
public void onFinished()
{
LogUtil.e("onFinished==");
isLoadMore = false;
}
});
}
28-文本数据的缓存
public class CacheUtils
{
/**
* 保持数据
*
* @param context
* @param key
* @param values
*/
public static void putString(Context context, String key, String values)
{
SharedPreferences sharedPreferences = context.getSharedPreferences("atguigu", Context.MODE_PRIVATE);
sharedPreferences.edit().putString(key, values).commit();
}
/**
* 得到缓存的数据
*
* @param context
* @param key
* @return
*/
public static String getString(Context context, String key)
{
SharedPreferences sharedPreferences = context.getSharedPreferences("atguigu", Context.MODE_PRIVATE);
return sharedPreferences.getString(key, "");
}
/**
* 保持播放模式
*
* @param context
* @param key
* @param values
*/
public static void putPlaymode(Context context, String key, int values)
{
SharedPreferences sharedPreferences = context.getSharedPreferences("hashub", Context.MODE_PRIVATE);
sharedPreferences.edit().putInt(key, values).commit();
}
/*
得到播放模式
*/
public static int getPlaymode(Context context, String key)
{
SharedPreferences sharedPreferences = context.getSharedPreferences("hashub", Context.MODE_PRIVATE);
return sharedPreferences.getInt(key, MusicPlayerService.REPEAT_NORMAL);
}
}
网友评论