项目需要打开本地的一个指定路径下的文件夹,获取视频后再调用一个播放器播放。获取本地视频并生成缩略图我查到了两种思路:
1.使用安卓系统自带浏览器
这种方法不需要自己定义一个图片展示的布局文件,只写几行代码就可以,缺点是会获取存储中所有mp4和3gp的视频,无法指定打开路径,所以不符合项目需求没有采用。
先定义了一个按钮打开浏览器:
Button button2 = (Button) findViewById(R.id.xuanshipin);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("video/*");//这里是设置打开文件的类型,也可以换成图片
startActivityForResult(intent, VIDEO_CAPTURE1);//定义处理浏览结果的类,也就是说点击某一个文件后需要执行的操作,VIDEO_CAPTURE是参数,在多个按钮时使用
}
});
处理结果的类定义如下:
这里定义了一个imageview来显示选择后的视频第一帧,所及记得在一开始声明,bitmap和imageview
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == VIDEO_CAPTURE0) {
Uri uri = data.getData();
Cursor cursor = this.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex(VideoColumns._ID));
String filePath = cursor.getString(cursor.getColumnIndex(VideoColumns.DATA));
bitmap = Thumbnails.getThumbnail(getContentResolver(), id, Thumbnails.MICRO_KIND, null);
// ThumbnailUtils类2.2以上可用
// Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(filePath,
// Thumbnails.MICRO_KIND);
imageView.setImageBitmap(bitmap);
Log.d("ddd", "filepath==" + filePath);
File file=new File(filePath);
cursor.close();
}
}
else if (resultCode == Activity.RESULT_OK && requestCode == VIDEO_CAPTURE1) {
Uri uri = data.getData();
File file = getFileByUri(uri);
MediaMetadataRetriever mmr=new MediaMetadataRetriever();//实例化MediaMetadataRetriever对象
mmr.setDataSource(file.getAbsolutePath());
bitmap=mmr.getFrameAtTime(2000);//获得视频第一帧的Bitmap对象
String duration = mmr.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_DURATION);//时长(毫秒)
Log.d("ddd","duration=="+duration);
int int_duration= Integer.parseInt(duration);
if(int_duration>45000){
Toast.makeText(getApplicationContext(), "视频时长超过45秒请重新选择", Toast.LENGTH_SHORT).show();;
}
imageView.setImageBitmap(bitmap);
}
这种方法打开浏览器时很快,用户体验很好。
2.自己定义listview
缺点是代码量大,而且耗时操作不会处理
先看布局文件,其实也不怎么费事:
线性布局下整个listview
<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"
tools:context=".Choose_video" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/lv_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</RelativeLayout>
然后是往布局里填充文件预览图片的操作,直接是一个activity,
public class Choose_video extends Activity implements OnItemClickListener{
private String cur_path=Environment.getExternalStorageDirectory().toString()+"/VRDemo/video/";//这里就是自定义打开路径啦
private List<Picture> listPictures;
ListView listView ;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0) {
List<Picture> listPictures = (List<Picture>) msg.obj;
MyAdapter adapter = new MyAdapter(listPictures);
listView.setAdapter(adapter);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.choose_video);
new Thread(new Runnable() {
@Override
public void run() {
loadVaule();//oncreate()里定义这个方法特别耗时,导致整个界面启动超级慢,需要4/5秒的样子
}
}).start();
}
//下面就看看这个方法里有多耗时
private void loadVaule(){
File file = new File(cur_path);
File[] files = null;
files = file.listFiles();
listPictures = new ArrayList<Picture>();
for (int i = 0; i < files.length; i++) {
Picture picture = new Picture();
picture.setBitmap(getVideoThumbnail(files[i].getPath(), 200, 200, MediaStore.Images.Thumbnails.MICRO_KIND));
picture.setPath(files[i].getPath());
listPictures.add(picture);
}
listView = (ListView) findViewById(R.id.lv_show);
listView.setOnItemClickListener(this);
Message msg = new Message();
msg.what = 0;
msg.obj = listPictures;
handler.sendMessage(msg);
}
//获取视频的缩略图
private Bitmap getVideoThumbnail(String videoPath, int width, int height, int kind) {
Bitmap bitmap = null;
// 获取视频的缩略图
bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, kind);
// System.out.println("w"+bitmap.getWidth());
// System.out.println("h"+bitmap.getHeight());
bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,
ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
return bitmap;
}
//定义适配器放listview
public class MyAdapter extends BaseAdapter {
private List<Picture> listPictures;
public MyAdapter(List<Picture> listPictures) {
super();
this.listPictures = listPictures;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return listPictures.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return listPictures.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View v, ViewGroup arg2) {
// TODO Auto-generated method stu
View view = getLayoutInflater().inflate(R.layout.item,null);
ImageView imageView = (ImageView) view.findViewById(R.id.iv_show);
TextView textView = (TextView) view.findViewById(R.id.tv_show);
imageView.setImageBitmap(listPictures.get(position).getBitmap());
textView.setText(listPictures.get(position).getPath());
return view;
}
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "点击了"+arg2, 200).show();
startPlay(this, listPictures.get(arg2).getPath());//点击后打开播放器
Log.e("path", listPictures.get(arg2).getPath());
}
public static void startPlay(Context context, String url) {
if (url.contains(".mp4") || url.contains(".MP4")) {
Intent intent = new Intent();
intent.setClassName(context, "com.easemob.chatuidemo.activity.VideoPlayerActivity");
intent.putExtra("playpath", url);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}else if(url.contains("rtsp") || url.contains("RTSP")){
Intent intent = new Intent();
intent.setClassName(context, "com.easemob.chatuidemo.activity.MakeVideoActivity");
intent.putExtra("playpath", url);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else if (url.contains(".jpg") || url.contains(".png")) {
Intent intent = new Intent();
intent.setClassName(context, "com.easemob.chatuidemo.activity.VideoPlayerActivity");
intent.putExtra("playpath", "/sdcard/VRDemo/capture/aa.jpg");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}else {
Toast.makeText(context, "没有资源哦", Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.setClassName(context, "com.easemob.chatuidemo.activity.MainActivity");
}
}
}
onCreate()里有耗时操作的解决办法:
(1)在Activity启动前,尽量少做。
(2)对于布局比较复杂的时候,可以考虑不要一次性全部加载上,动态加载是一个好的办法。
(3)对于及时需要的数据,加载起来耗时的又有异常危险的,一定记得开辟一个线程来做这些动作,千万记得不要做阻塞主线程(UI线程)的任何事情。
(4)对于特殊情况下,Activity启动确实需要大量工作时候,可以考虑先加载一个简单的布局(或是Activity)来过渡.