AndoridStudio:视频的 存储/播放模块 开发与设计
准备工具
- Android Studio 2023.1.2 点击跳转至AndroidStudio官网下载
- Mysql 5.7 点击跳转至Mysql官网下载
- Mysql5.7 JDBC连接驱动包(mysql-connector-java-5.1.42.jar)点击跳转至Mysql官网下载
- Everything软件 点击跳转至voidtools官网下载
- 一个视频文件,存储在电脑的D盘(D://good.mp4)
- Navicat Premium 16 点击跳转至Navicat官网下载
文章目录
- AndoridStudio:视频的 存储/播放模块 开发与设计
1.Mysql存储视频资源
要实现将播放Mysql数据库中的视频,有两种解决方案:
(1)将视频文件以二进制字节流的形式存储到数据库中,格式为LongBlob;
(2)搭建一个文件资源服务器,在数据库中存储视频所在文件资源服务器中的地址,类似于超链接的形式实现读取视频文件;
由于视频文件一般较大,若是选择方案1,那么可能会出现的情况有:单个视频文件可能会被分为多条记录信息存在表中,想要再将其还原不仅需要编写将二进制转换为相应环境能够播放的视频文件格式,还需编写将多条记录信息整合为一个视频文件二进制流;此外当视频文件非常多时,数据存储内存很大,这对数据库的存储性能要求非常高,目前几乎没有以这种方式来存储视频的例子,所以暂且先不学习。本次选择方案2来实现读取数据库中的视频。
(1)搭建文件资源服务器
文件资源服务器就是一个可以共享文件的服务器,比如用户在浏览器或文件管理器中输入你的文件地址(192.168.1.1:8080/xxx)时可以直接访问到文件资源服务器或下载该文件,本次学习只涉及到*宿主机(电脑)和手机模拟器*中的文件访问,是位于同一局域网下的,所以可以直接使用软件来实现。
①搭建HTTP文件资源服务器
此处使用Everything实现搭建一个HTTP文件资源服务器:
打开Everything→菜单栏选择工具→选项→HTTp服务器→勾选启用HTTP服务器,其他的保持默认→点击应用后确认
②浏览文件资源服务器
设置好后直接打开宿主机浏览器,在地址栏中输入localhost或本机ip地址192.168.1.8后回车进入页面,若显示如下图所示页面,则HTTP文件资源服务器开启成功
③在模拟器中浏览文件资源服务器中的资源
此时可以在使用位于同一局域网下的设备如手机/手机模拟器中使用浏览器进入该ip地址,看看能否访问成功。
注意:访问的ip地址是开启了HTTP文件资源服务器的宿主机的ip地址,而非手机的ip地址,例如我的宿主机开启了HTTP文件资源服务器的ip地址为192.168.1.8,而手机的为192.168.1.7,在手机上我应该在浏览器中访问192.168.1.8而不是192.168.1.7。但是手机模拟器与手机不一样,手机模拟器是基于宿主机电脑的网络环境下运行的,所以其ip地址与电脑是一样的。
若是手机/手机模拟器也能正常访问,如上图所示,则说明该局域网文件资源管理器建立成功。
(2)将文件访问路径写入Mysql表中
①建立数据库表
使用Navicate打开数据库连接,用可视化工具添加数据库video并且在该数据库中添加数据库表videodb,表中的元数据有视频ID、标题、描述、URL。如下图所示
注意:若是使用用户操作界面新建表,要将表中数据字符集设置为utf-8(即支持中文字符格式)
也直接添加查询语句,将以下SQL查询代码语句复制进去后直接运行,可以生成相应表结构:
CREATE TABLE `videodb` ( `id` INT ( 11 ) NOT NULL, `title` VARCHAR ( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `profile` VARCHAR ( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `url` VARCHAR ( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY ( `id` ) USING BTREE ) ENGINE = INNODB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = DYNAMIC;
②写入视频信息数据
创建完表后,向数据库中写入视频文件的信息:
2.AndroidStudio连接Mysql
经一系列尝试,最终选择Mysql5,听说Mysql8有bug无法进行简单的局域网连接…
(1)为mysql添加一个可以远程连接的用户
操作解释:MySql位于宿主机(电脑)中,而AndroidStudio所运行的代码是运行在手机模拟器中,AndroidStduio的运行与Mysql的存储不在同一个机器中。所以想要实现AndroidStudio连接宿主机的Mysql,本质上来讲就是进行Mysql的远程连接,故首先要为Mysql添加一个远程连接的账户。(若选择SQLite数据库则不需要这样,因为SQLite数据库位于手机模拟器中,可以直接被AndroidStudio运行的项目访问)
这里有两种方式:
①Navicate可视化界面的键鼠操作实现(小白推荐,简单理解)
使用Navicate的可视化界面,键鼠操作来添加一个Mysql的用户,使其具备远程连接功能。(这里我添加的用户名为android,名字取什么都可以,影响不大)
为其添加相应信息,注意主机需要填写为“%”,才能实现远程连接,插件随便选一个影响不大(“%”的意思指的是任意的主机都可连接)
然后在服务器权限中选择相应权限,这里我选择了所有的权限,然后保存,即可看到一个新建的Mysql用户—>andorid
接下来测试该用户可否被连接,新建一个Mysql连接,连接名可以随便填写,主机填写位自己的ip地址,用户名为刚刚新建的用户名,然后点击测试连接,若显示连接成功则说明已经成功新建了一个可以被远程网络访问的数据库用户对象。
②通过命令控制窗口cmd实现
新建一个远程用户还可以通过命令控制窗口cmd实现,以管理员身份打开cmd,进入mysql:
mysql -uroot -pmysql123
-p后面接密码,这里我的用户名为root对应的密码:mysql123,大家改成自己的
随便进入一个mysql数据库: (此处use后面接数据库名字,这里以数据库名为:mysql的数据库为例)
use mysql
开启远程访问权限:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'amigo'
上述代码的意思为开启root用户的所有权限,并且可访问主机为“%”(任意主机)
强制刷新权限:
flush privileges
关闭mysql:
exit
(2)加载JDBC驱动
Mysql用户远程访问设置好之后就可以开始尝试在AndroidStudio中访问Mysql数据库了。
①准备好Mysql5对应的jdbc驱动版本,找到mysql-connector-java.jar文件
②在AndroidStudio中以Project的形式查看项目文件
③检查xxx(项目名)/app文件夹中是否有lib文件夹,若没有可以手动创建一个,然后将mysql-connector-java.jar文件粘贴进去
④然后右击该jar文件,选择将其添加为Libaray
之后会需要等待一段时间等他添加该jar文件为项目依赖文件,添加成功后会发现该jar文件可以被展开,并且展开后的文件夹那一部分内容有黄色标记背景,这说明添加成功如下图所示:
⑤写代码连接Mysql
添加好JDBC连接驱动后,就可以开始写代码尝试连接Mysql了。
此时们将项目视图切换回Android模式,并且先在AndroidManifest.xml文件中添加网络访问权限,因为数据库连接的是局域网中宿主机(电脑)上的Mysql,而不是手机模拟器中的数据库。
<uses-permission android:name="android.permission.INTERNET"/>
⑥编写连接Mysql的方法
创建一个新的java类如DatabaseHelper,在该类中新建一个全局静态的方法,使用该方法用于连接Mysql数据库
public class DatabaseHelper { public static void DatabaseConnection() { String url = "jdbc:mysql://192.168.1.8:3306/video?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC"; String username = "android"; String password = "mysql123"; Thread thread = new Thread(new Runnable() { @Override public void run() { try { Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); Log.d("Mysql连接","JDBC驱动加载成功......"); statement.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); Log.d("Mysql连接","JDBC驱动加载失败....."); } } }); thread.start(); try { // 等待数据库连接成功后再返回 thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } }
注意:
(1)此处的URL需换成用户自己当时的ip地址,URL中”?“后面接的参数不能漏掉,需按照这个格式来。
(2)username、password也需要修改为自己的可以被远程网络连接的Mysql用户名与对应密码
特别注意:Mysql的每一次连接与查询都需要在新的线程Thread中进行,Android网络编程的特性是网络访问需要在新线程中进行,因为每一次对数据库的访问都是进行网络请求的,所以不只是这里,今后每次对数据库的操作都需要在新的线程中进行,否则代码会运行失败报错。
⑦回到MainActivity.java文件中调用该方法
在写完上述方法后,回到MainActivity.java文件中调用该方法,因为Android程序的入口是Activity,所以在其他地方定义的方法都需要在Activity中调用后运行程序才会生效
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DatabaseHelper.DatabaseConnection(); } }
代码中的Log.d可以在AndroidStudio中的Logcat中查看日志的输出结果
若显示JDBC驱动连接成功,则说明Mysql数据库以及能够成功连接上了!
(3)实现查询数据库中表信息
JDBC驱动加载成功后,接下来就是使用SQL查询语句查询数据库表中信息。
例如:查询video数据库中,表videodb中的id=1的url
代码如下:
public class DatabaseHelper { public static void DatabaseConnection() { String url = "jdbc:mysql://192.168.1.8:3306/video?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC"; String username = "android"; String password = "mysql123"; Thread thread = new Thread(new Runnable() { @Override public void run() { try { Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); Log.d("Mysql连接","JDBC驱动加载成功......"); ResultSet resultSet = statement.executeQuery("SELECT url FROM videodb WHERE id = 1"); while (resultSet.next()){ String url = resultSet.getString("url"); Log.d("Mysql连接",url); } resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); Log.d("Mysql连接","JDBC驱动加载失败....."); } } }); thread.start(); try { // 等待数据库连接成功后再返回 thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } }
查询后可以在Logcat的左侧刷新一下即可出现查询结果,说明查询成功,数据库可以被AndroidStudio调用
若显示了如上图所示的查询的内容,则说明能够成功查询到Mysql,恭喜你马上就要实现这个模块了。
3.VideoView加载视频资源
当数据库、视频文件、数据库连接都准备好了之后,我们就可以使用Android的VideoView组件实现访问视频文件资源了。
操作方法如下所示:
(1)添加权限
在AndroidManifest.xml文件中添加网络权限、可读存储权限、写入存储权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET"/>
(2)在布局文件中添加组件
这里以MainActivity为例,在相应的布局文件activity_main.xml中添加组件VideoView,并且为其添加一个id
<VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="match_parent" />
(3)在java代码中配置VideoView
在布局资源相对应的java文件中,即MainActivity.java文件中的onCreate方法中找到VideoView组件对象,然后调用setVideoPath方法,为其配置视频播放的资源。(这里先尝试随便访问一个网络视频资源用来测试代码的编写是否正确)
public class MainActivity extends AppCompatActivity { private VideoView videoView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); videoView = findViewById(R.id.videoView); //资源URL地址 String videoUrl = "https://v6.huanqiucdn.cn/4394989evodtranscq1500012236/3303c0543270835014988484597/v.f100830.mp4"; //为videoView设置视频路径 videoView.setVideoPath(videoUrl); //视频控制器,即实现显示进度、播放、暂停、快进、后退功能的 MediaController mediaController = new MediaController(MainActivity.this); videoView.setMediaController(mediaController); videoView.requestFocus(); //播放视频 videoView.start(); } }
此处还设置了视频控制器MediaController,以实现能够控制视频播放。
注意:这里的视频地址应该是真正的视频地址例如该代码中的地址,若地址是一个网页资源,这个网页资源中含有一个视频,那么该地址无效不可被VideoView解读
(4)播放Mysql中的视频
①使用查询语句查询Mysql数据库中的视频资源地址并将其保存
public static String DatabaseConnection() { String url = "jdbc:mysql://192.168.1.8:3306/video?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC"; String username = "android"; String password = "mysql123"; final String[] video_url = new String[1]; Thread thread = new Thread(new Runnable() { @Override public void run() { try { Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); Log.d("Mysql连接","JDBC驱动加载成功......"); ResultSet resultSet = statement.executeQuery("SELECT url FROM videodb WHERE id = 1"); while (resultSet.next()){ video_url[0] = resultSet.getString("url"); Log.d("Mysql连接",url); } resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); Log.d("Mysql连接","JDBC驱动加载失败....."); } } }); thread.start(); try { // 等待数据库连接成功后再返回 thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } return video_url[0]; }
②播放视频资源,回到MainActivity.java中,在VideoView组件中播放该video_url中的视频资源,即可成功播放
public class MainActivity extends AppCompatActivity { private VideoView videoView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //资源URL地址 String video_url = DatabaseHelper.DatabaseConnection(); Log.d("video_url", video_url); VideoView videoView = findViewById(R.id.videoView); //为videoView设置视频路径 videoView.setVideoPath(video_url); //视频控制器,即实现显示进度、播放、暂停、快进、后退功能的 MediaController mediaController = new MediaController(MainActivity.this); videoView.setMediaController(mediaController); videoView.requestFocus(); //播放视频 videoView.start(); } }