一、案例效果
二、主界面的设计与功能
2.1 案例效果
2.2 布局界面 activity_main.xml 参考代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:background="@drawable/bg_picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:text="进入视频列表"
android:textColor="#000000"
android:textSize="30sp"
android:textStyle="bold"
android:layout_gravity="center"
android:layout_marginTop="60dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
2.3、类文件 MainActivity.java 参考代码:
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
//定义对象
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定控件
button=findViewById(R.id.button);
//点击跳转事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity.this,VideoActivity.class);
startActivity(intent);
}
});
}
}
三、视频列表界面的设计与功能
3.1 案例效果
3.2、布局界面 activity_video.xml 参考代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".VideoActivity">
<TextView
android:text="视频列表"
android:textColor="#00007f"
android:textSize="40sp"
android:textStyle="bold"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
3.3、类文件 VideoActivity.java 参考代码:
package com.example.myvideoplayer;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
public class VideoActivity extends AppCompatActivity {
//定义对象
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
initView();//控件初始化
initData();//数据初始化
}
private void initView() {
recyclerView=findViewById(R.id.recyclerview);
}
private void initData() {
//准备视频数据
List<Video> videolist=new ArrayList<>();
//1、网络视频
Video firstvideo=new Video("紧急救援 ","http://vfx.mtime.cn/Video/2019/03/19/mp4/190319222227698228.mp4");
videolist.add(firstvideo);
Video secondvideo=new Video("玩具总动员 ","http://vfx.mtime.cn/Video/2019/03/21/mp4/190321153853126488.mp4");
videolist.add(secondvideo);
//2、本工程中的视频
Video thirdvideo=new Video("see you again","android.resource://"+getPackageName()+"/"+R.raw.seeyouagain);
videolist.add(thirdvideo);
Video fourthvideo=new Video("why live","android.resource://"+getPackageName()+"/"+R.raw.whylive);
videolist.add(fourthvideo);
//3、模拟器中的视频
Video fifthvideo=new Video("天生我材必有用","file:///storage/emulated/0/Pictures/天生我材必有用.mp4");
videolist.add(fifthvideo);
Video sixthvideo=new Video("罗密欧与朱丽叶","file:///storage/emulated/0/Pictures/罗密欧与朱丽叶.mp4");
videolist.add(sixthvideo);
//适配器
VideoAdapter adapter=new VideoAdapter(videolist);
//让数据显示到 recyclerview 控件上
StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
}
3.4、类文件 MusicAdapter.java 参考代码:
package com.example.myvideoplayer;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class VideoAdapter extends
RecyclerView.Adapter<VideoAdapter.ViewHolder> {
private List<Video> videolist;
public VideoAdapter(List<Video> videolist) {
this.videolist = videolist;
}
//方法 1:用于创建 ViewHolder 实例
@NonNull
@Override
public VideoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.video_item,parent,false);
final ViewHolder holder=new ViewHolder(view);
holder.videoview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//单击任意视频跳转到播放界面
int position=holder.getAdapterPosition();
Video video =videolist.get(position);
String myvideoname=video.getVideoName();
String myvideoUrl=video.getVideoUrl();
Intent intent=new Intent(view.getContext(),PlayActivity.class);
intent.putExtra("videoname",myvideoname);
intent.putExtra("videourl",myvideoUrl);
view.getContext().startActivity(intent);
}
});
return holder;
}
//方法 2:用于对 Recyclerview 中子项的数据进行赋值的
@Override
public void onBindViewHolder(@NonNull VideoAdapter.ViewHolder holder, int position) {
Video video=videolist.get(position);
holder.video_name.setText(video.getVideoName());
}
//方法 3:返回 Recyclerview 中数据源长度
@Override
public int getItemCount() {
return videolist.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView video_name;
View videoview;
public ViewHolder(@NonNull View view) {
super(view);
video_name=view.findViewById(R.id.video_name);
videoview=view;
}
}
}
3.5、布局界面 video_item.xml 参考代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<ImageView
android:src="@drawable/video_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"/>
<TextView
android:id="@+id/video_name"
android:text="视频的名字"
android:textColor="#000000"
android:textSize="30sp"
android:textStyle="bold"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
3.6、类文件 Video.java 参考代码:
package com.example.myvideoplayer;
public class Video {
private String videoName;
private String videoUrl;
public String getVideoName() {
return videoName;
}
public String getVideoUrl() {
return videoUrl;
}
public Video(String videoName, String videoUrl) {
this.videoName = videoName;
this.videoUrl = videoUrl;
}
}
3.7、代码详解:
提醒:
(1)添加依赖,由于 RecyclerView 是 android 5.0 新增的控件,所以需要在 build.gradle 里面添加依赖:如下
implementation'com.android.support:recyclerview-v7:28.0.0'
(2)因为要读写 sd 卡上的歌曲,所以需要在配置文件中添加权限,如下
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" tools:ignore="ProtectedPermissions" />
(3)在配置文件中,开通网络权限
<uses-permission android:name="android.permission.INTERNET"/>
(4)右击 res 文件夹,new---Directory,文件名:raw(文件名不能自定义),让一个视频文件粘贴到该文件夹下。
(5)选择视频,将该视频存储到模拟器 sdcard 文件夹中的 Movies 文件夹里。(本案例实用的方法二)
模拟器中的Url应该怎么书写???
方法一:String path1 = Environment.getExternalStorageDirectory().getPath() + “/文件所在子目录/视频文件名.MP4";
方法二:String path2 = “file:///路径/视频文件名.MP4";
(6)这里的view.getContext()返回的是Activity,表示上下文环境
四、视频播放界面的设计与功能
4.1 案例效果
4.2、布局界面 activity_play.xml 参考代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".PlayActivity">
<TextView
android:id="@+id/my_videoname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="视频名称"
android:textStyle="bold"
android:textSize="30sp"
android:textColor="#00008F"
android:layout_gravity="center"
android:layout_marginTop="30dp"/>
<VideoView
android:layout_width="match_parent"
android:layout_height="400dp"
android:id="@+id/my_videoview"/>
</LinearLayout>
4.3、类文件 PlayActivity.java 参考代码:
package com.example.myvideoplayer;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.VideoView;
public class PlayActivity extends AppCompatActivity {
//定义对象
private TextView my_videoname;
private VideoView my_videoview; //视频播放器
private MediaController mediaController;//定义媒体控制柄
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
initView();//控件初始化
initData();//数据初始化
}
private void initView() {
my_videoname=findViewById(R.id.my_videoname);
my_videoview=findViewById(R.id.my_videoview);
mediaController=new MediaController(this);
}
private void initData() {
//1、获取从音乐列表传过来的视频名称和视频地址
String myvideoname=getIntent().getStringExtra("videoname");
String myvideourl=getIntent().getStringExtra("videourl");
//2、将视频名称显示在文本框中,将视频地址关联到播放器中
my_videoname.setText(myvideoname);
my_videoview.setVideoPath(myvideourl);
//视频播放器和媒体控制柄关联起来
my_videoview.setMediaController(mediaController);
//媒体控制柄和视频播放器关联起来
mediaController.setMediaPlayer(my_videoview);
//3、启动视频播放器播放视频
my_videoview.start();
}
}
4.4、代码讲解:
(1)VideoView详解
在Android的界面控件中有一个视频播放控件VideoView,可以直接在手机上 面开辟一个视频播放的UI,播放视频。程序中利用控件进行播放比较简单,几 个重要的方法如下:
// 指定需要播放的视频的地址videoView.setVideoURI(Uri.parse("android.resource://poet.android.factory/"+R.raw.demo));
//设置视频路径 videoView.setVideoPath();
// 设置播放器的控制条 videoView.setMediaController(new MediaController(this));
// 开始播放视频 videoView.start();
(2)媒体控制柄MediaController详解
VideoView控制视频播放的功能相对较少,具体而言,它只有start和pause方 法。为了提供更多的控制,可以实例化一个MediaController,并通过 setMediaController方法设置其为VideoView的控制器。
默认的MediaController有后退(rewind)、暂停(pause)、播放(play)和快进 (fast-forward)按钮,还有一个清除和进度条组合控件,可以用来定位到视频中的任何一个位置。
到目前为止,程序的功能都已经完成了;
假如我们有200个视频需要存储,显然存储到raw文件夹下和模拟器中都是不可取的。
接下来是补充内容!!!
五、获取 Bmob 服务器上的视频
5.1 案例效果
注意: 在百度中输入“比目后端云”,进入主页。注册账号,登录 创建应用。名称任意。比如我的应用名称为:MyOne 类型其他,创建应用。
接下来,通过 5 个步骤让程序有服务器关联起来。
步骤 1
第一步:在 Project 的 build.gradle 文件中添加 Bmob 的 maven 仓库地址:如下:
allprojects {
repositories {
google()
jcenter()
//第一步:在 Project 的 build.gradle 文件中添加 Bmob 的 maven 仓库地址:
//Bmob 的 maven 仓库地址--必填
maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
}
}
步骤 2
第二步: 在 app 的 build.gradle 文件中添加 compile 依赖文件:
android {
„„„„„„„„„„
//第二步: 在 app 的 build.gradle 文件中添加 compile 依赖文件:
useLibrary 'org.apache.http.legacy'
}
dependencies {
„„„„„„„„
//第二步: 在 app 的 build.gradle 文件中添加 compile 依赖文件:
implementation 'cn.bmob.android:bmob-sdk:3.7.0'
implementation "io.reactivex.rxjava2:rxjava:2.2.2"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'com.squareup.okio:okio:2.1.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
}
步骤 3
<!--第三步:在你的应用程序的 AndroidManifest.xml 文件中添加相应的权限:-->
<!--允许联网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!--获取 GSM(2g)、WCDMA(联通 3g)等网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--获取 wifi 网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--保持 CPU 运转,屏幕和键盘灯有可能是关闭的,用于文件上传和下载 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--获取 sd 卡写的权限,用于文件上传和下载-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--允许读取手机状态 用于创建 BmobInstallation-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
步骤 4
<!-- 第四步: 配置 ContentProvider¶ -->
<application
„„„„„„„„„„„„
</activity>
<!-- 第四步: 配置 ContentProvider¶ -->
<provider
android:name="cn.bmob.v3.util.BmobContentProvider"
android:authorities="com.example.musicvideoplayer.BmobContentProvider">
</provider>
</application>
步骤 5
第五:在你想用 bmob 云的页面,初始化比目云//第五步:默认初始化参 2:app ID
public class VideoActivity extends AppCompatActivity {
private static final String TAG = "VideoActivity";
private RecyclerView recy_videoview;
private List<VideoInfo> videoarrlist;
private VideoAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
initView();//控件初始化
initData();//数据初始化
initBmobData();//比目云数据初始化
}
„„„„„„„„
private void initBmobData() {
//第五步:默认初始化
Bmob.initialize(this, "7c7717065cecdc8037c9d5180ac6bcea");
„„„„„„„„
}
5.2 在比目云上创建表
在比目云服务器上,创建一个表,表明 video_table,添加列数据,第一列:video_name; 第二列:video_url; 接下来添加行:单击视频地址下方,选择文件,上传一个视频,单击名字下方,输入视频的名字。
5.3 新建类文件 video_table.java
注意:工程中,创建类 video_table 类名要与比目云上的表名一模一样。变量名要与表中的 字段名一模一样。
package com.example.videoplayer;
import cn.bmob.v3.BmobObject;
import cn.bmob.v3.datatype.BmobFile;
public class video_table extends BmobObject {
private String video_name;
private BmobFile video_url;
public String getVideo_name() {
return video_name;
}
public BmobFile getVideo_url() {
return video_url;
}
}
5.4 在类文件中书写代码实现功能 VideoActivity.java
package com.example.videoplayer;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.datatype.BmobFile;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.FindListener;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class VideoActivity extends AppCompatActivity {
//定义对象
RecyclerView recyclerView;
List<Video> videolist;
VideoAdapter adapter;
private static final String TAG = "VideoActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
initview(); //控件初始化
initData();//数据初始化
initBmobData();//比目云数据初始化
}
private void initview() {
recyclerView=findViewById(R.id.recyclerview);
}
private void initData() {
videolist= new ArrayList<>();
//获取网络视频
Video firstvideo = new Video("玩具总动员", "http://vfx.mtime.cn/Video/2019/03/21/mp4/190321153853126488.mp4");
videolist.add(firstvideo);
Video secondvideo = new Video("紧急救援", "http://vfx.mtime.cn/Video/2019/03/19/mp4/190319222227698228.mp4");
videolist.add(secondvideo);
//获取本地视频
Video thirdvideo=new Video("see you again","android.resource://"+getPackageName()+"/"+R.raw.seeyouagain);
videolist.add(thirdvideo);
Video fourthvideo=new Video("why live","android.resource://"+getPackageName()+"/"+R.raw.whylive);
videolist.add(fourthvideo);
//获取模拟器中的视频
Video fifthvideo=new Video("天生我才必有用", "file:///storage/emulated/0/Pictures/天生我材必有用.mp4");
videolist.add(fifthvideo);
Video sixthvideo=new Video("罗密欧与朱丽叶", "file:///storage/emulated/0/Pictures/罗密欧与朱丽叶.mp4");
videolist.add(sixthvideo);
//让数据显示到 recyclerview 控件上
adapter=new VideoAdapter(videolist);
StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
private void initBmobData() {
//第 5 步:默认初始化
Bmob.initialize(this, "fe59338cc50a44d1468bf8642a7e275b");
//把视频文件存储在比目云
BmobQuery<video_table> myquery=new BmobQuery();
myquery.findObjects(new FindListener<video_table>() {
@Override
public void done(List<video_table> list, BmobException e) {
if(e==null){
for (video_table video_table1 : list) {
//Log.d(TAG, "视频名称: "+video_table1.getVideo_name()+video_table1.getVideo_url());
Video seventhvideo=new Video(video_table1.getVideo_name(),video_table1.getVideo_url().getUrl());
videolist.add(seventhvideo);
}
adapter.notifyDataSetChanged();
}else{
Toast.makeText(VideoActivity.this,"查询失败 ",Toast.LENGTH_SHORT).show();
}
}
});
}
}