今天 学习 android多线程 atomininteger内存模型 以及自己项目的 视频播放功能
目前 对于android一些知识点 大家可以 去看今日头条的 android进阶小刘 这个博主 讲得很好
atomininteger内存模型 是啥
https://blog.csdn.net/fanrenxiang/article/details/80623884 没看懂
https://www.cnblogs.com/nightOfStreet/articles/11887169.html
好這裏说下我的視頻播放項目
我主要使用 videoView 去进行视频播放
xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:id="@+id/root_ll">
<!-- 视频播放-->
<VideoView
android:id="@+id/videoPlayView"
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_marginBottom="14dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="15dp"
/>
<ImageButton
android:id="@+id/ibBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="?android:listPreferredItemPaddingStart"
android:background="@android:color/transparent"
android:src="@drawable/ib_knight_return" />
</RelativeLayout>
xml文件很简单 主要是 VideoView的布局 去实现播放器的功能
activity代码 其实代码很简单 videoview的视频播放+缩略图背景 使用缩略图设置背景 然后在 加载完视频数据后 隐藏背景进行播放
package com.zsch.forestinventory.activity.left_activity;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;
import android.support.annotation.Nullable;
import com.zsch.androidlib.activity.BaseActivity;
import com.zsch.forestinventory.BuildConfig;
import com.zsch.forestinventory.R;
import com.zsch.forestinventory.ui.overlay.controller.MeasureController;
import java.io.IOException;
import java.util.HashMap;
import android.os.Handler;
import android.util.Log;
/**
* 播放视频
*/
public class ShowVideoViewActivity extends BaseActivity implements View.OnClickListener {
private ImageButton ibBack;
private Uri uri; /其他页面传过来的 uri对象
private MediaController mc; //视频播放控制器
private int bufferPercentage = 0;
private VideoView videoView;
private ImageView first_frame;
@Override
protected void initVariables() {
uri = getIntent().getData();
if (uri == null)
finish();
}
@Override
protected void initView(Bundle savedInstanceState) {
setContentView(R.layout.activity_show_video_view);
if (savedInstanceState == null) {
// Bundle类型的数据与Map类型的数据相似,都是以key-value的形式存储数据的。实际上,savedInstanceState也就是保存Activity的状态的
//onsaveInstanceState方法是用来保存Activity的状态的。当一个Activity在生命周期结束前,会调用该方法保存状态
// 用来保存状态信息的Bundle会同时传给两个method,即onRestoreInstanceState() and onCreate().
uri = getIntent().getData();
} else {
uri = savedInstanceState.getParcelable("uri");
}
if (uri == null) {
Toast.makeText(this, "无视频展示", Toast.LENGTH_SHORT).show();
finish();
return;
}
videoView = (VideoView) findViewById(R.id.videoPlayView);
ibBack=(ImageButton) findViewById(R.id.ibBack);
ibBack.setOnClickListener(this);
mc = new MediaController(this);
videoView.setMediaController(mc);
//设置视频控制器,组件可以控制视频的播放,暂停,快进,组件,不需要你实现
videoView.setVideoURI(uri);//设置视频的播放地址 加载uri所对应的视频
String videoUrl=uri.getPath();
Bitmap bitmapfirst_frame=getBitmapFormUrl(videoUrl); //生成缩略图
videoView.setBackgroundDrawable(new BitmapDrawable(getResources(), bitmapfirst_frame));
//解決 黑屏方法 这里最重要 因为在视频家在之前 就是 prepared前 会显示为黑屏 用以下方法解决
//先在videoView設置背景 利用 本地視頻 制作缩略图
//等到视频真正开始渲染后再去掉VideoView 的背景。最终的解决办法是在onPrepared回调中,加添加一个setOnInfoListener的监听,在这个监听中将VideoView的背景清除
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { //setOnPreparedListener 用于处理准备结束后的操作
@Override
public void onPrepared(MediaPlayer mp) {// 装载完毕回调 时的方法 OnPreparedListener里的ononPrepared方法
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START)
// first_frame.setVisibility(View.GONE); //组件看不到,不占用布局空间
// videoView.setVisibility(View.VISIBLE); //组件可见 并占用空间
videoView.setBackgroundColor(Color.TRANSPARENT); //将VideoView的背景清除 将背景颜色 设置为空
return true;
}
});
}
});
}
// 生成視頻 首帧 缩略图
public static Bitmap getBitmapFormUrl(String url) {
Bitmap bitmap = null;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(url); //因为是本地视频 不考虑 sdk 版本 问题 网络 流媒体 考虑 全部
// if (Build.VERSION.SDK_INT >= 14) {
// retriever.setDataSource(url, new HashMap<String, String>());
// } else {
// retriever.setDataSource(url);
// }
/*getFrameAtTime()--->在setDataSource()之后调用此方法。 如果可能,该方法在任何时间位置找到代表性的帧,
并将其作为位图返回。这对于生成输入数据源的缩略图很有用。**/
bitmap = retriever.getFrameAtTime();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} finally {
try {
retriever.release();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
return bitmap;
}
@Override
protected void onResume() {
super.onResume();
// try {
// Toast.makeText(ShowVideoActivity.this, "1", Toast.LENGTH_LONG).show();
// mediaPlayer.setDataSource(uri.getPath()); //播放存储设备的资源文件
// mediaPlayer.setOnBufferingUpdateListener(this); //监听事件,网络流媒体的缓冲监听。这个方法与上个接口中的方法int getBufferPercentage()进行结合使用
// //mediaPlayer.prepare();
// controller.setMediaPlayer(this);
// controller.setEnabled(true); //设置按钮可点击 false 设置为不可点击
// }catch (IOException e){
// e.printStackTrace();
// }
}
@Override
protected void loadData() {
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.ibBack:
onBackPressed();
break;
}
}
@Override
public void onBackPressed() {
finish(); // finish();//在Activity中执行this.finish()方法之后,执行如下过程: onPause(),onStop(),onDestory(),
}
@Override
public boolean onTouchEvent(MotionEvent event) { //实现这个方法来处理触摸屏幕引发的事件。
return super.onTouchEvent(event);
}
}