我怎样才能刷新MediaStore在Android? [英] How can I refresh MediaStore on Android?

查看:281
本文介绍了我怎样才能刷新MediaStore在Android?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这开始是在Android论坛一般用户的问题。然而,它已经成为根据需要,一个编程问题。这里是我的问题。

Android有一个服务 - MediaScanner - 它任何时候(我相信)SD卡未安装或重新安装在后台运行。此服务收集的卡上的所有媒体文件数据,并提供了一​​个SQLite数据库可以通过音乐应用程序进行查询。大多数的音乐应用程序使用此服务,因为它节省了使用扫描SD卡相关联的电池消耗。

自从我开始使用Android的,我一直有一个问题,即,即使从SD卡中被删除同步到设备M3U播放列表保持在此的SQLite数据库。它得到的地步,我现在有大约40播放列表显示在任何音乐应用程序,我用了一个集合,尽管有只对卡约10 m3u格式的文件。剩余的播放列表不玩了,都是空的。我可以从音乐应用程序删除这些手动删除它们,但我讨厌这样做的。必须有一个更好的方式来消除这些鬼播放列表。

有两个应用程序在Android Market上 - SDRescan和音乐扫描仪,这理应做的正是这一点,但他们都没有工作。

我开始写我自己的应用程序更新或删除MediaStore数据库,并从头开始,但我没有得到很远。我有一个Android应用程序,它运行以下code:

  sendBroadcast(新意图(Intent.ACTION_MEDIA_MOUNTED,
        Uri.parse(文件://+ Environment.getExternalStorageDirectory())));
 

我发现这个code的几个例子在线,以此来扫描SD卡,但我没有任何与它的运气任何责任。任何提示吗?

FULL code:

 包com.roryok.MediaRescan;

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

公共类MediaRescan延伸活动{
    / **第一次创建活动时调用。 * /
    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        sendBroadcast(新意图(Intent.ACTION_MEDIA_MOUNTED,
                Uri.parse(文件://+ Environment.getExternalStorageDirectory())));
        的setContentView(R.layout.main);
    }

    //复制该文件后重新扫描SD卡
    私人无效rescanSdcard()抛出异常{
      意图scanIntent =新的意图(Intent.ACTION_MEDIA_MOUNTED,
                Uri.parse(文件://+ Environment.getExternalStorageDirectory()));
      IntentFilter的IntentFilter的=新的IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
      intentFilter.addDataScheme(文件);
      sendBroadcast(新意图(Intent.ACTION_MEDIA_MOUNTED,
                Uri.parse(文件://+ Environment.getExternalStorageDirectory())));
    }
}
 

解决方案

好吧,我已经做到了。

,而不是通过在mediastore所有播放列表重新扫描卡,该应用迭代并检查_data字段的长度。我发现,所有没有相关的M3U文件列表,这一领域一直是空白。然后,它是发现源$ C ​​$ C为原生Android音乐应用程序,发现删除的方法并用它来删除任何播放列表长度为0的,我改名为应用程序PlaylistPurge的只是一个案件(因为它不 T'重新扫描'了)​​和我张贴低于code。

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

 包com.roryok.PlaylistPurge;

进口的java.util.ArrayList;
进口的java.util.List;

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

公共类PlaylistPurge扩展ListActivity {

    私人列表<字符串>名单=新的ArrayList<字符串>();
    私人最终的String [] STAR = {*};

    / **第一次创建活动时调用。 * /
    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);

        ListAdapter适配器= createAdapter();
        setListAdapter(适配器);
    }

    / **
     *创建并返回一个列表适配器当前列表活动
     * @返回
     * /
    保护ListAdapter createAdapter()
    {
        //返回播放列表
        乌里playlist_uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
        光标光标= managedQuery(playlist_uri,STAR,NULL,NULL,NULL);
        cursor.moveToFirst();
        对(INT R = 0;为r cursor.getCount(); R ++ cursor.moveToNext()){
            INT I = cursor.getInt(0);
            int类型l = cursor.getString(1).length();
            如果(升大于0){
                //保留任何播放列表与一个有效的数据字段,让我知道
                list.add(保持+ cursor.getString(2)+:ID(+ I +));
            }其他{
                //删除与0的数据长度的任何播放列表
                开放的我们的uri = ContentUris.withAppendedId(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,我);
                。getContentResolver()删除(URI,NULL,NULL);
                list.add(已删除+ cursor.getString(2)+:ID(+ I +));
            }
        }
        cursor.close();
        //发布保留/删除播放列表
        ListAdapter适配器=新的ArrayAdapter<字符串>(这一点,android.R.layout.simple_list_item_1,清单);

        返回适配器;
    }
}
 

更新:

下面是一个关于应用程序的http://roryok.com/blog/index.php/2010/07/23/clearing-out-deleted-playlists-in-android/

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

我已经得到了很多的流量到我的博客从这个职位,并从人的数量庞大的电子邮件,感谢我吧。很高兴它帮助了!任何潜在的用户应该知道,我的蹩脚的应用程序现在,只要你运行它崩溃,但实际上做什么它应该做的!我一直打算回去解决这个崩溃的行为,并把它放到市场上,希望2013年将是今年我做到这一点。

This started out as a general user question on Android forums. However it's become, by necessity, a programming question. Here's my problem.

Android has a service - MediaScanner - which runs in the background any time (I believe) the SD card is un-mounted and re-mounted. This service collects data on all the media files on the card, and provides a SQLite DB which can be queried by music applications. Most music applications use this service as it saves on battery-drain associated with scanning the SD card.

Since I started using android, I've consistently had a problem whereby M3U playlists synchronised to the device remain in this SQLite DB even after being deleted from the SD Card. It's gotten to the point where I now have a collection of about 40 playlists showing up in any music app I use, despite there only being around 10 m3u files on the card. The remaining playlists do not play, and are empty. I can remove them manually by deleting them from the music app, but I'm sick of doing this. There has to be a better way to remove these ghost playlists.

There are two apps on the Android Market - SDRescan and Music Scanner, which supposedly do exactly this but neither of them work.

I set about writing my own app to refresh or delete the MediaStore database and start from scratch, but I'm not getting very far. I've got an android app which runs the following code :

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

I've found a few examples of this code online as a way to scan the SD Card but I'm not having any luck with it whatsoever. Any tips?

FULL CODE:

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())));    
    }
}

解决方案

Ok, I've done it.

Rather than rescan the card, the app iterates through all the playlists in mediastore and checks the length of the _data field. I discovered that for all the lists with no associated M3U file, this field was always empty. Then it was just a case of finding the source code for the original android music app, finding the delete method and using that to delete any playlists with a length of 0. I've renamed the app PlaylistPurge (since it doesn't 'rescan' anymore) and am posting the code below.

I'll probably also publish this somewhere, either on the Market or on my own site, 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:

Here's a link to a post on my blog about the app http://roryok.com/blog/index.php/2010/07/23/clearing-out-deleted-playlists-in-android/

UPDATE 2: Tuesday, April 9, 2013

I've gotten a lot of traffic to my blog from this post, and a huge number of emails from people thanking me for it. Glad it helped out! Any potential users should know that my crappy app currently crashes as soon as you run it, but actually does what it's supposed to do! I've always intended to go back and fix this crashing behaviour and put it on the market, hopefully 2013 will be the year I do that.

这篇关于我怎样才能刷新MediaStore在Android?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆