zoukankan      html  css  js  c++  java
  • android操作sdcard中的多媒体文件(二)——音乐列表的更新

      在上一篇随笔中,我介绍了如何在程序中查询sdcard内的多媒体文件,并且显示到播放列表中,但是,如果在sdcard内删除、增加一些多媒体文件,如何让播放列表也更新呢,这里我分享一下自己在项目中的一些解决方法,希望对大家有所帮助。                                     
      首先,我简单介绍一下android是如何扫描sdcard内的多媒体信息的,详细请阅读stay的博文:http://www.cnblogs.com/stay/articles/1957571.html
      当android的系统启动的时候,系统会自动扫描sdcard内的多媒体文件,并把获得的信息保存在一个系统数据库中,以后在其他程序中如果想要访问多媒体文件的信息,其实就是在这个数据库中进行的,而不是直接去sdcard中取,理解了这一点以后,问题也随着而来:如果我在开机状态下在sdcard内增加、删除一些多媒体文件,系统会不会自动扫描一次呢?答案是否定的,也就是说,当你改变sdcard内的多媒体文件时,保存多媒体信息的系统数据库文件是不会动态更新的。
      那么如何让多媒体数据库中的数据更新呢?我们可以采用广播机制来实现:在应用程序中发送一个广播,让android系统扫描sdcard并更新多媒体数据库        
    private void scanSdCard(){
    	    IntentFilter intentfilter = new IntentFilter( Intent.ACTION_MEDIA_SCANNER_STARTED);
    	    intentfilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
    	    intentfilter.addDataScheme("file");
    	    scanSdReceiver = new ScanSdReceiver();
    	    registerReceiver(scanSdReceiver, intentfilter);
    	    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
    	    		Uri.parse("file://" + Environment.getExternalStorageDirectory().getAbsolutePath()))); }
    
      其中ScanSdReceiver是一个自定义的广播接收器,继承自BroadCastReceiver,因为android系统开始扫描sdcard以及扫描完毕时都会发送一个系统广播来表示当前扫描的状态,这样我们就可以很方便通过判断当前的扫描状态加一些自己的逻辑操作,ScanSdReceiver的代码如下:
    public class ScanSdReceiver extends BroadcastReceiver {
    
    	private AlertDialog.Builder  builder = null;
    	private AlertDialog ad = null;
    	private int count1;
    	private int count2;
    	private int count;
    	@Override
    	public void onReceive(Context context, Intent intent) {
    		String action = intent.getAction();
    		if (Intent.ACTION_MEDIA_SCANNER_STARTED.equals(action)){
    			Cursor c1 = context.getContentResolver()
    			.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
    					new String[]{MediaStore.Audio.Media.TITLE,
    					MediaStore.Audio.Media.DURATION,
    					MediaStore.Audio.Media.ARTIST,
    					MediaStore.Audio.Media._ID,
    					MediaStore.Audio.Media.DISPLAY_NAME },
    					null, null, null);
    			count1 = c1.getCount();
    			System.out.println("count:"+count);
    			builder = new AlertDialog.Builder(context);
    			builder.setMessage("正在扫描存储卡...");
    			ad = builder.create();
    			ad.show();
    			
    		}else if(Intent.ACTION_MEDIA_SCANNER_FINISHED.equals(action)){
    			Cursor c2 = context.getContentResolver()
    			.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
    					new String[]{MediaStore.Audio.Media.TITLE,
    					MediaStore.Audio.Media.DURATION,
    					MediaStore.Audio.Media.ARTIST,
    					MediaStore.Audio.Media._ID,
    					MediaStore.Audio.Media.DISPLAY_NAME },
    					null, null, null);
    			count2 = c2.getCount();
    			count = count2-count1;
    			ad.cancel();
    			if (count>=0){
    				Toast.makeText(context, "共增加" + 
    						count + "首歌曲", Toast.LENGTH_LONG).show();
    			} else {
    				Toast.makeText(context, "共减少" +
    						count + "首歌曲", Toast.LENGTH_LONG).show();
    			}	
    		}	
    	}
    }
    
      
      
      这里我们定义了两个Cursor对象,分别用来存储扫描前后的多媒体信息,并给出相应的提示。  
      以前有很多朋友问过我,为什么扫描以后播放列表中的数据条数没有发生相应的改变。要实现播放列表在扫描后更新,必须重新读取多媒体信息到Cursor中,并且重新设置adapter,最后还要调用XXXAdapter.notifyDataSetChanged()来通知UI更新。(可以参考第一张的内容)
      上面的操作都是手动在SDCARD中添加或着删除多媒体文件,下面介绍如何在列表中删除SDCARD中的多媒体文件。
      在上一篇随笔中,我们使用了系统提供的ContentProvider来查询sdcard中的多媒体文件,我们同样可以使用这个ContentProvider来进行删除操作: 
    private void deleteMusic(int position){
    	this.getContentResolver().delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, 
    			MediaStore.Audio.Media._ID + "=" + _ids[position], 
    			null);
    }
    
       其中“多媒体文件的ID”可以从_ids数组中取得(关于_ids数组请参考第一张的内容)。这样,我们是否就已经从SDCARD中删除了指定_ID的多媒体文件了呢?  其实当你打开FileExplorer时会发现,原来的文件并没有被删除,— —!杯具,搞了半天文件还在,我第一次遇到这个问题的时候也是纠结了老半天。。。
    为什么没有被删除,原因是上面的删除操作只是删除了系统多媒体数据库中的相应记录,而并没有删除SDCAED中的文件(注意:多媒体信息数据库和SDCARD中的多媒体文件并不会自动保持同步),这个时候如果再次扫描SDCARD,你会发现刚才从播放列表中删除的行会再次出现。
       其实要想真正的从SDCARD中删除多媒体文件并不难,可能有朋友会想到这样的方法:遍历SDCARD中的多媒体文件,然后把想要删除的文件和其他文件逐一比较,找到文件路径,最后进行删除。这种方法是可以实现删除操作的,不过效率很低,如果SDCARD中的文件夹以及文件很多,也不知道要用掉多少时间。。
      在上一张中我们从多媒体数据库中读出来一项很重要的信息:MediaStore.Audio.Media.DATA
    并且取得里面的字串并存放在了_path数组中,最终的数据格式为:/SDCARD/[子文件夹名]文件名,又了这个路径,我们就可以很方便的从SDCARD中删除多媒体文件了
    private void deleteMusicFile(int position){
    	File file = new File(_path[position]);
    	file.delete();
    }
    
       同样,删除文件后要想播放列表同步更新,也必须执行刚才介绍的一系列操作。  
  • 相关阅读:
    mongodb分片
    mongodb读写分离的一些选项的理解
    mongodb管理副本集(持续更新中)
    mongodb配置副本集(多台服务器间的副本集搭建) replica[ˈrɛplɪkə]
    mongodb副本集的基础概念和各种机制
    mongodb的查询
    mongodb文档的CRUD
    SQLServer2008数据库连接error40错误
    Did you forget about DBModel.InitializeModel the model [AAAdm] ?
    ERP中通过EDI导入资料的时候出现【Microsoft Office Excel不能访问文件‘C:WindowsTEMP433....’
  • 原文地址:https://www.cnblogs.com/zchajax/p/2030709.html
Copyright © 2011-2022 走看看