videoview实现视频引导页及从assets文件中读取文件到本地SD卡
来源:互联网 发布:神机妙算造价软件价格 编辑:程序博客网 时间:2024/05/21 06:39
视频放在assets文件下,这里的文件不会被编辑,但是使用的时候,需要用流转到本地,然后再使用
关于视频的相关测试数据,在文章最后
需要权限:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
目录结构:
代码:
1、准备工作:
1.1、
import android.os.Environment;/** * 全局变量 */public class CHEN { // 引导视频存放路径 public static String GuideVideoSavePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/chen/guide_video/"; // 引导视频播放路径 public static String GuideVideoPlayPath = "";}
1.2、工具类
import android.text.TextUtils;public class Utils { /** * 检查字符串是否是空 * * @param str * @return true:字符串为空 */ public static boolean checkStringIsEmpty(String str) { if (TextUtils.isEmpty(str) || "null".equals(str)) { return true; } else { return false; } }}
1.3、styles.xml文件下:这个属性给展示视频的activity,让视频全屏播放
<style name="fullscreen" parent="AppTheme"> <item name="android:windowFullscreen">true</item> </style>
2、自定义的videoview(保证能全屏的videoview)
import android.content.Context;import android.util.AttributeSet;import android.widget.VideoView;public class CustomVideoView extends VideoView { private Context context; public CustomVideoView(Context context) { this(context, null); } public CustomVideoView(Context context, AttributeSet attrs) { this(context, attrs, -1); } public CustomVideoView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; init(); } private void init() { //do something... } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //重新计算高度。保证全屏显示 int width = getDefaultSize(0, widthMeasureSpec); int height = getDefaultSize(0, heightMeasureSpec); setMeasuredDimension(width, height); }}
3、使用:
3.1、一开始的MainActivity,布局文件我不做任何处理,就用新建时默认的就行,核心是下一个展示视频的activity
import android.app.Activity;import android.content.Intent;import android.content.res.AssetManager;import android.os.Bundle;import android.os.Handler;import android.util.Log;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;public class MainActivity extends Activity { private int time = 3000; public Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case 100: if (!Utils.checkStringIsEmpty(CHEN.GuideVideoPlayPath)) { //播放视频成功生成了 startActivity(new Intent(MainActivity.this, VideoGuideActivity.class)); MainActivity.this.finish(); } else { //引导视频没有生成 //do something... } break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); creatGuideVideo(); //sendEmptyMessageDelayed(int what, long delayMillis) //延时time,发送一个what=100的值 mHandler.sendEmptyMessageDelayed(100, time); } /** * 创建视频引导页文件 */ private void creatGuideVideo() { new Thread() { public void run() { try { File path_file = new File(CHEN.GuideVideoSavePath); if (!path_file.exists()) { try { path_file.mkdirs(); } catch (Exception e) { CHEN.GuideVideoPlayPath = ""; } } long start = System.currentTimeMillis(); //第二个参数是生成的文件的名字(包括后缀名),一般和assets文件中要打开的一致 File file = new File(CHEN.GuideVideoSavePath, "guide_video.mp4"); if (!file.exists()) { AssetManager assetManager = getAssets();// 获取asset管理者 InputStream in = null; FileOutputStream out = null; try { //assets文件中要打开的文件的名字(包括后缀名) in = assetManager.open("guide_video.mp4"); out = new FileOutputStream(file); byte[] b = new byte[1024]; int len = -1; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } } catch (IOException e) { e.printStackTrace(); CHEN.GuideVideoPlayPath = ""; } finally { if (out != null) { out.close(); } if (in != null) { in.close(); } } } long end = System.currentTimeMillis(); Log.e("创建视频引导页播放视频用时===", "" + (end - start)); CHEN.GuideVideoPlayPath = file.getAbsolutePath(); } catch (Exception e) { CHEN.GuideVideoPlayPath = ""; } } }.start(); }}
3.2、VideoGuideActivity(为了保证全屏,在清单文件中)
<!--android:screenOrientation="portrait"是让屏幕旋转时视频不变--> <!--android:theme="@style/fullscreen"是让这个activity全屏,没有状态栏和标题栏--> <activity android:name=".VideoGuideActivity" android:screenOrientation="portrait" android:theme="@style/fullscreen"/>
import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.media.MediaPlayer;import android.net.Uri;import android.os.Bundle;import android.text.TextUtils;import android.util.Log;import android.widget.Toast;/** * 视频引导页 */public class VideoGuideActivity extends Activity { CustomVideoView video_view; private int videoIndex = -1; /** * 监听是否点击了home键将客户端推到后台 */ private BroadcastReceiver homeAndLockReceiver = new BroadcastReceiver() { String SYSTEM_REASON = "reason"; String SYSTEM_HOME_KEY = "homekey"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) { String reason = intent.getStringExtra(SYSTEM_REASON); if (TextUtils.equals(reason, SYSTEM_HOME_KEY)) { //表示按了home键,程序到了后台 video_view.pause(); //得到当前视频播放的位置。单位是毫秒 videoIndex = video_view.getCurrentPosition(); Log.e("videoIndex", videoIndex + ""); } } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { //按下锁屏键 video_view.pause(); //得到当前视频播放的位置。单位是毫秒 videoIndex = video_view.getCurrentPosition(); Log.e("videoIndex", videoIndex + ""); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.video_guide_layout); try { //注册广播,监听home键及锁屏键的按下 IntentFilter filter = new IntentFilter(); //锁屏广播,由系统发出 filter.addAction(Intent.ACTION_SCREEN_ON); //锁屏广播,由系统发出 filter.addAction(Intent.ACTION_SCREEN_OFF); //点击home键广播,由系统发出 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); registerReceiver(homeAndLockReceiver, filter); //注册广播结束 video_view = (CustomVideoView) findViewById(R.id.video_view); /** * 视频或者音频到结尾时触发的方法 */ video_view.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { doSomething(); } }); /** * 视频或者音频播放出错触发的方法 */ video_view.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { doSomething(); return false; } }); video_view.setVideoURI(Uri.parse(CHEN.GuideVideoPlayPath)); //播放 video_view.start(); } catch (Exception e) { doSomething(); } } @Override protected void onRestart() { super.onRestart(); Log.e("onRestart", videoIndex + ""); //video_view.start(); video_view.seekTo(videoIndex == -1 ? 0 : videoIndex); //先start,再seekTo,home键回来是重播;先seekTo,再start,都是续播。但是如果距离开始时间较短(经测试,大约10以内,可能有误差),还是会出现重播现象。这些细节,在用的时候,多测试测试。对效果影响不大 video_view.start(); } @Override protected void onDestroy() { super.onDestroy(); if (homeAndLockReceiver != null) { unregisterReceiver(homeAndLockReceiver); } } //对返回键的监听 @Override public void onBackPressed() { super.onBackPressed(); doSomething(); } /** * 播放失败、异常时做的事。一般都是跳转到下个页面 */ private void doSomething() { //do something... Toast.makeText(this, "do something...", Toast.LENGTH_SHORT).show(); }}
4、测试数据:
一般的使用视频引导页,之前还会有一个图片启动页,最好在图启动页展示的时候,在本地创建视频,然后在视频引导页直接展示。时间上有要求,既要展示启动页,还要尽可能的给本地生成视频文件留下时间:
我测试了3组数据(单位毫秒):
assets中视频文件大小为5.6M时:创建视频引导页播放视频用时===: 570assets中视频文件大小为6.6M时:创建视频引导页播放视频用时===: 648assets中视频文件大小为16M时:创建视频引导页播放视频用时===: 1697
注:我使用的是小米Note,我再使用魅族系列的一个低配手机的时候,出现过一次6.6M视频,在本地创建,时间为2700毫秒左右的情况。同一个手机,每次创建也会有差距,以上数据仅供参考
1 0
- videoview实现视频引导页及从assets文件中读取文件到本地SD卡
- android从assets目录复制文件到sd卡
- assets目录文件复制到SD卡中
- 将assets文件夹中的文件复制到sd卡中
- 复制Assets文件到SD卡
- 从assets文件夹中读取文件
- 从assets文件夹中读取文件
- android从res、assets中读取文件
- Android 将assets中的文件拷贝到本地SD卡使用
- 读取assets目录下的资源文件写入到本地
- Android从远程服务器下载文件到本地sd卡中
- 单片机 stm32读取ico图标文件 从SD卡中解码显示到LCD
- Android:从Apk本地Assets复制文件到指定文件夹
- 从本地读取文件到hdfs中注意事项
- VideoView实现视频引导页效果
- android中拷贝assets下的资源文件到SD卡中(可以超过1M)
- android中拷贝assets下的资源文件到SD卡中(可以超过1M)
- android中拷贝assets下的资源文件到SD卡中(可以超过1M)
- 工业控制领域的新标准:opc
- (转载借鉴) input[file]标签的accept=”image/*”属性在google浏览器上响应很慢的解决办法
- bzoj 1879 [Sdoi2009]Bill的挑战
- 移动端图片居多,加载过慢,使用延迟加载|懒加载( lazyload.js)
- Java学习笔记-异常
- videoview实现视频引导页及从assets文件中读取文件到本地SD卡
- SpringMVC 中 返回JSON 数据
- [Android]关于异步任务(AsyncTask)报leaked window com.android.internal.policy.PhoneWindow$DecorView错误
- 怎样用下面C语言代码实现直接对数据加密,不用写文件的方式。求助大神帮忙改改!
- 来自 Mathjax与LaTex公式简介—Ryan Zhao
- ie6兼容png24位的方法
- iOS--NSAttributedString的基本用法
- Android校招复习资料整理
- 唯品会11.11:频繁黑匣架构背景下,看唯品会的革命性重构