2010-07-21 47 views
44

这开始作为Android论坛上的一般用户问题。然而,它必然是一个编程问题。这是我的问题。如何在Android上刷新MediaStore?

Android有一个服务 - MediaScanner - 它随时在后台运行(我相信)SD卡是未安装和重新安装的。该服务收集卡上所有媒体文件的数据,并提供可由音乐应用程序查询的SQLite数据库。大多数音乐应用程序使用此服务,因为它可以节省与扫描SD卡相关的电池耗尽。

自从我开始使用android之后,我一直有一个问题,M3U播放列表与设备同步,即使在从SD卡中删除后,仍保留在此SQLite数据库中。现在,我已经收集了大约40个播放列表,并显示在我使用的任何音乐应用程序中,尽管卡上只有大约10 m3u的文件。剩余的播放列表不播放,并且是空的。我可以通过从音乐应用中删除它们手动删除它们,但我厌倦了这样做。必须有更好的方法来删除这些幽灵播放列表。

Android Market上有两个应用程序 - SDRescan和音乐扫描仪,据说可以做到这一点,但它们都不起作用。

我开始着手编写自己的应用程序来刷新或删除MediaStore数据库并从头开始,但我并没有走得太远。我有它运行下面的代码的Android应用:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
     Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 

我发现这段代码的几个例子在线,以此来扫描SD卡,但我没有与任何任何运气。有小费吗?

全码:

package com.roryok.MediaRescan; 

import android.app.Activity; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.Environment; 

public class MediaRescan extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
       Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 
     setContentView(R.layout.main); 
    } 

    //Rescan the sdcard after copy the file 
    private void rescanSdcard() throws Exception{  
     Intent scanIntent = new Intent(Intent.ACTION_MEDIA_MOUNTED, 
       Uri.parse("file://" + Environment.getExternalStorageDirectory())); 
     IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED); 
     intentFilter.addDataScheme("file");  
     sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
       Uri.parse("file://" + Environment.getExternalStorageDirectory())));  
    } 
} 
+0

嗨,你知道,如果sendBroadcast(新意图(Intent.ACTION_MEDIA_MOUNTED, Uri.parse( “文件://” + Environment.getExternalStorageDirectory())));将工作的SD卡是额外的插槽卡?换句话说getExternalStorageDirectory()返回一个sdcard的路径,这是内部的,但可能有制造商提供的外部卡?如何调用这种卡的媒体扫描仪? – Ahmed 2013-01-26 20:54:15

+0

目前似乎没有办法做到这一点。看到这个线程:http://stackoverflow.com/questions/5453708/android-how-to-use-environment-getexternalstoragedirectory – roryok 2013-01-28 10:30:44

回答

18

好吧,我已经做到了。

应用程序不是重新扫描卡片,而是遍历mediastore中的所有播放列表,并检查_data字段的长度。我发现,对于没有关联M3U文件的所有列表,此字段始终为空。然后,这只是找到原始android音乐应用程序的源代码,找到删除方法并使用它删除长度为0的任何播放列表。我已将应用程序PlaylistPurge重命名(因为它不重新扫描'了),并发布下面的代码。

我可能会也发布这个地方,无论是在市场还是在我自己的网站,http://roryok.com

package com.roryok.PlaylistPurge; 

import java.util.ArrayList; 
import java.util.List; 

import android.app.ListActivity; 
import android.content.ContentUris; 
import android.database.Cursor; 
import android.net.Uri; 
import android.os.Bundle; 
import android.provider.MediaStore; 
import android.widget.ArrayAdapter; 
import android.widget.ListAdapter; 

public class PlaylistPurge extends ListActivity { 

    private List<String> list = new ArrayList<String>(); 
    private final String [] STAR= {"*"}; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     ListAdapter adapter = createAdapter(); 
     setListAdapter(adapter); 
    } 

    /** 
    * Creates and returns a list adapter for the current list activity 
    * @return 
    */ 
    protected ListAdapter createAdapter() 
    { 
     // return play-lists 
     Uri playlist_uri= MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;  
     Cursor cursor= managedQuery(playlist_uri, STAR, null,null,null); 
     cursor.moveToFirst(); 
     for(int r= 0; r<cursor.getCount(); r++, cursor.moveToNext()){ 
      int i = cursor.getInt(0); 
      int l = cursor.getString(1).length(); 
      if(l>0){ 
       // keep any playlists with a valid data field, and let me know 
       list.add("Keeping : " + cursor.getString(2) + " : id(" + i + ")"); 
      }else{ 
       // delete any play-lists with a data length of '0' 
       Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, i); 
       getContentResolver().delete(uri, null, null); 
       list.add("Deleted : " + cursor.getString(2) + " : id(" + i + ")"); 
      } 
     }  
     cursor.close(); 
     // publish list of retained/deleted playlists 
     ListAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list); 

     return adapter; 
    } 
} 

UPDATE:

以下是关于应用http://roryok.com/blog/index.php/2010/07/23/clearing-out-deleted-playlists-in-android/到该帖子的链接我的博客

更新2:周二,2013年4月9日

我已经从这个帖子得到了很多的流量到我的博客,和来自人们的大量电子邮件感谢我。很高兴帮助!任何潜在的用户应该知道,我的蹩脚的应用程序目前崩溃,只要你运行它,但实际上做它应该做的!我一直打算回去修复这种崩溃的行为并将其投放市场,希望2013年能成为我这样做的一年。

+0

这会删除没有被删除但没有歌曲的播放列表? – 2013-07-30 08:16:30

+0

嗨vinay。不,它只会删除已删除播放列表的条目。有0个条目的播放列表不会受到影响 – roryok 2013-07-30 10:40:36

+0

谢谢!好的解决方案 – 2017-02-20 10:58:29

10

您可以使用以下代码请求重新扫描特定文件。

注意:传递的MIME类型非常重要。我注意到,以MP3的ID3标签的更改没有,如果我使用的SQLite的正确刷新“*/*”,但用“音频/ MP3”工作

MediaScannerConnection.scanFile(
    context, 
    new String[]{ pathToFile1, pathToFile2 }, 
    new String[]{ "audio/mp3", "*/*" }, 
    new MediaScannerConnectionClient() 
    { 
     public void onMediaScannerConnected() 
     { 
     } 
     public void onScanCompleted(String path, Uri uri) 
     { 
     } 
    }); 
+1

你真的不需要通过mime类型。如果文件名称正确(* .mp3,* .m4a等),则扫描器将从扩展名中确定MIME类型。所以,而不是新的String [] {** MIME类型**},只是传递null。 – Baron 2012-12-20 17:38:23

+0

这工作对我来说,检测删除和移动文件的删除。对于我的情况,我正在通过MTP(媒体传输协议)进行通信,并且没有再次扫描文件,它们仍然出现在那里,直到重新启动等。 – egfconnor 2014-11-13 18:36:10

+0

据我所知,这仍然不会影响参考已删除媒体的_playlists_,只有图书馆的参考文献 – roryok 2015-06-10 08:07:58

42

下面是一个简单的“单一的基于文件的解决方案” :

每当你关于它的使用

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageAdded))); 

添加文件,让MediaStore内容提供商知道对于删除:只需使用getContentResolver()删除(URI ,NULL,NULL)(幸得DDSports

+0

大概这意味着解决了孤立文件首先出现的问题。我的应用程序是清理_other_应用程序留下的垃圾,它不会执行此操作 – roryok 2013-02-13 12:24:17

+1

我给了这个赞赏,因为虽然它没有解决提到的确切问题,但它是我认为相关的非常有价值的信息。 – Matt 2013-12-23 19:11:14

+2

这实际上只在添加文件时才起作用。当文件被删除时它不起作用。你需要getContentResolver()。delete(uri,null,null);方法。 – DDSports 2014-03-03 14:47:24