我的情况是这样的,拍摄好一段视频后,保存到本地,并且在上传之前判断时长,我这里是时长要不少于5秒,不大于15秒,符合这个时长才能上传。
然后我开始转向度娘,真的搜了好久,百度上的资料我基本上看了一遍,stackflow也逛了一遍……
//判断视频时长是否符合
private boolean judgeVideoTime(String vediopahth) {
int seconds=0;
String[] projection = new String[]{MediaStore.Video.Media.DURATION};
Cursor cursor = VedioFinishActivity.this.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI
, projection, MediaStore.Video.Media.DATA+"='"+vediopahth+"'", null, null);
if (cursor != null){
if(cursor.getCount()==1){
cursor.moveToFirst();
long duration=0;
if (cursor.moveToFirst()) {
do{
duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION));
}while (cursor.moveToNext());
}
seconds=(int)duration/1000;
}else {
Mytoast.makeText(this, "视频文件出错", 1).show();
}
}else {
Mytoast.makeText(this, "cuesor为空", 1).show();
}
cursor.close();
if(seconds>=5){
return true;
}else {
return false;
}
}
解释一下,这个是返回布尔值的一个方法,传入的参数videopath是视频拍完之后存到本地的地址。再解释一下query这个方法:首先要得到ContentResolver,
ContentResolver直译为内容解析器,代码里就是通过VedioFinishActivity.this.getContentResolver()来得到实例,Android中程序间数据的共享是通过Provider/Resolver进行的。提供数据(内容)的就叫Provider,Resovler提供接口对这个内容进行解读。
根据Android文档,
第二个参数,这个参数告诉Provider要返回的内容(列Column),我只要视频的时长,但是参数中是String[]格式,表示你可以拿到很多你想要的数据,比如视频的修改时间啊,文件大小,标题啊等等,我只要时长,所以String[] projection = new String[]{MediaStore.Video.Media.DURATION};
第三个参数,selection,设置条件。null表示不进行筛选。我有个视频的本地路径,这可以唯一表示一个视频;
第三个参数的地方我写MediaStore.Video.Media.DATA+"='"+vediopahth+"'",其中还有MediaStore.Video.Media.CONTENT_TYPE,MediaStore.Video.Media._ID,MediaStore.Video.Media.SIZE, MediaStore.Video.Media.TITLE等一些参数,看名字可以看出分别还能有内容类型,id,大小,标题这些,参数还有很多,但是我当时真心不知道data是指路径,于是郁闷了好久。
第四个参数,selectionArgs,这个参数是要配合第三个参数使用,如果你在第三个参数里面有?,那么你在selectionArgs写的数据就会替换掉?跟sql语句很像,因为我有绝对路径,没有就是没有,所以我设置了null;
第五个参数,sortOrder,排序,相当于SQL语句中的Order by。如果想要结果按照ID的降序排列: 列明+升降序类型就行。例如MediaStore.Video.Media.SIZE+“DESC”。我这找到的话就只有一个,所以这个也设为null;
后来遇到一个问题,就是拍摄好的视频没办法及时更新到视频库。意思就是我用我的项目录好视频然后也拿到了视频的绝对路径,视频本身是已经存在了,但是我进入图库里,相应目录下没有找到这个视频。所以我在判断时长之前还要手动更新一下图库。
关于这个问题网上有很多方法:
这里我说三个方法:
先普及一下uri:
Uri代表要操作的数据,Android上可用的每种资源 - 图像、视频片段等都可以用Uri来表示。Android平台而言,URI主要分三个部分:
scheme
authority
path
方法一:更新相关文件
Intent scanIntent = new Intent(Intent.Intent.ACTION_MEDIA_MOUNTED);
scanIntent.setData(Uri.parse(文件 ));
this.sendBroadcast(scanIntent);
方法二:更新单个文件
前面提到我已经有了视频的路径,就是这里的filePath,所以我用了这个方法。要在判断时长之前;
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(new File(filePath)));
ctx.sendBroadcast(scanIntent);
在项目里的代码块:
public void scanFileAsync(Context ctx, String filePath) {
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(new File(filePath)));
ctx.sendBroadcast(scanIntent);
}
方法三:提供一种思路和解决方案吧,试了一下报错了,但是为了能有技术成长(多凑字数),我先贴出来好吗
private MediaScannerConnection mediaScannerConnection= null;
MediaScannerConnectionClient client=new MediaScannerConnectionClient() {
public void onScanCompleted(String path, Uri uri) {
// TODO Auto-generated method stub
mediaScannerConnection.disconnect();
Log.d("tag", "onScanCompleted");
}
public void onMediaScannerConnected() {
// TODO Auto-generated method stub
Log.d("tag", "onMediaScannerConnected");
}
};
mediaScannerConnection=new MediaScannerConnection(this, client);
//获取连接
mediaScannerConnection.connect();
//扫描指定路径下的文件到系统数据库中
scanfile(new File(Environment.getExternalStorageDirectory() + File.separator + "xxx"));
mediaScannerConnection.disconnect();
private void scanfile(File f) {
if(f.isDirectory()){
File[] files=f.listFiles();//将指定文件夹下面的文件全部列出来
if(files!=null){
for(int i=0;i
解决问题了,花了大半天……