2010-07-21 49 views
44

Điều này bắt đầu với tư cách là câu hỏi chung của người dùng trên các diễn đàn Android. Tuy nhiên nó trở thành, bởi sự cần thiết, một câu hỏi lập trình. Đây là vấn đề của tôi.Tôi làm cách nào để làm mới MediaStore trên Android?

Android có dịch vụ - MediaScanner - chạy trong nền bất kỳ lúc nào (tôi tin) thẻ SD chưa được gắn và gắn lại. Dịch vụ này thu thập dữ liệu trên tất cả các tệp phương tiện trên thẻ và cung cấp một DB SQLite có thể được truy vấn bởi các ứng dụng âm nhạc. Hầu hết các ứng dụng nhạc đều sử dụng dịch vụ này vì nó tiết kiệm pin khi kết hợp với việc quét thẻ SD.

Kể từ khi tôi bắt đầu sử dụng Android, tôi đã liên tục gặp sự cố khi danh sách M3U được đồng bộ hóa với thiết bị vẫn còn trong DB SQLite này ngay cả sau khi bị xóa khỏi Thẻ SD. Đã đến lúc tôi có bộ sưu tập khoảng 40 danh sách phát hiển thị trong mọi ứng dụng nhạc tôi sử dụng, mặc dù chỉ có khoảng 10 m3u tệp trên thẻ. Các danh sách phát còn lại không phát và trống. Tôi có thể xóa chúng bằng tay bằng cách xóa chúng khỏi ứng dụng nhạc, nhưng tôi bị bệnh vì làm điều này. Phải có cách tốt hơn để xóa các danh sách phát ma này.

Có hai ứng dụng trên Android Market - SDRescan và Máy quét nhạc, được cho là thực hiện chính xác việc này nhưng không phải ứng dụng nào hoạt động.

Tôi đặt về cách viết ứng dụng của riêng mình để làm mới hoặc xóa cơ sở dữ liệu MediaStore và bắt đầu từ đầu, nhưng tôi không nhận được rất xa. Tôi đã có một ứng dụng Android chạy mã sau:

Tôi đã tìm thấy một vài ví dụ về mã này trực tuyến như một cách để quét thẻ SD nhưng tôi không có bất kỳ may mắn nào với nó . Có lời khuyên nào không?

ĐẦY ĐỦ Mã sản phẩm:

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

Xin chào, Bạn có biết gửi sendcast (new Intent (Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file: //" + Environment.getExternalStorageDirectory()))); sẽ làm việc cho sdcard đó là thẻ khe cắm thêm? nói cách khác getExternalStorageDirectory() trả về một đường dẫn đến sdcard mà là nội bộ nhưng có thể được nhà sản xuất cung cấp thẻ bên ngoài? làm thế nào có thể được gọi là máy quét phương tiện truyền thông cho thẻ như vậy? – Ahmed

+0

dường như không có cách nào để thực hiện việc này vào lúc này. xem chủ đề này: http://stackoverflow.com/questions/5453708/android-how-to-use-environment-getexternalstoragedirectory – roryok

Trả lời

18

Ok, tôi đã thực hiện nó.

Thay vì quét lại thẻ, ứng dụng lặp qua tất cả các danh sách phát trong trung gian và kiểm tra độ dài của trường _data. Tôi phát hiện ra rằng đối với tất cả các danh sách không có tệp M3U liên quan, trường này luôn trống. Sau đó, nó chỉ là một trường hợp tìm mã nguồn cho ứng dụng nhạc android gốc, tìm phương pháp xóa và sử dụng để xóa mọi danh sách phát có độ dài là 0. Tôi đã đổi tên ứng dụng PlaylistPurge (vì nó không 'quét lại 'nữa) và đang đăng mã bên dưới.

tôi sẽ có lẽ cũng xuất bản một nơi nào đó, hoặc trên thị trường hoặc trên trang web của riêng tôi, 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:

Dưới đây là một liên kết đến một bài đăng trên blog của tôi về ứng dụng http://roryok.com/blog/index.php/2010/07/23/clearing-out-deleted-playlists-in-android/

UPDATE 2: thứ Ba 9 tháng 4, 2013

tôi đã nhận được rất nhiều lượng truy cập vào blog của tôi từ bài này, và một số lượng email khổng lồ từ những người cảm ơn tôi vì điều đó. Vui mừng nó đã giúp! Bất kỳ người dùng tiềm năng nào cũng nên biết rằng ứng dụng crappy của tôi hiện đang gặp sự cố ngay khi bạn chạy ứng dụng, nhưng thực sự là những gì nó phải làm! Tôi đã luôn luôn có ý định quay trở lại và sửa chữa hành vi này bị rơi và đặt nó trên thị trường, hy vọng năm 2013 sẽ là năm tôi làm điều đó.

+0

điều này sẽ xóa danh sách phát chưa bị xóa nhưng cũng không có bài hát nào? –

+0

Xin chào vinay. Không, nó sẽ chỉ xóa mục nhập cho danh sách phát đã bị xóa. Danh sách phát có 0 mục nhập sẽ không bị ảnh hưởng – roryok

+0

Cảm ơn! Giải pháp tốt –

10

Bạn có thể yêu cầu quét lại các tệp cụ thể bằng cách sử dụng mã sau.

LƯU Ý: LOẠI MIME được chuyển là quan trọng. Tôi nhận thấy những thay đổi thực hiện để thẻ MP3 ID3 không làm mới đúng trong SQLite nếu tôi sử dụng "*/*", tuy nhiên sử dụng "audio/mp3" làm việc

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

Bạn thực sự không phải vượt qua loại mime. Nếu tệp được đặt tên đúng (* .mp3, * .m4a, v.v.) thì trình quét sẽ xác định loại mime từ phần mở rộng. Vì vậy, thay vì chuỗi mới [] {** mime types **}, chỉ cần vượt qua null. – Baron

+0

Tác vụ này giúp tôi phát hiện việc xóa các tệp đã xóa và đã di chuyển. Đối với trường hợp của tôi, tôi đang giao tiếp qua MTP (Media Transfer Protocol) và không quét các tập tin một lần nữa họ vẫn xuất hiện để có mặt ở đó cho đến khi khởi động lại, vv – egfconnor

+0

như xa như tôi biết điều này sẽ vẫn không ảnh hưởng đến _playlists_ phương tiện truyền thông mà tài liệu tham khảo đã xóa chỉ, tài liệu tham khảo thư viện – roryok

42

Dưới đây là một 'tập tin dựa trên giải pháp đơn' dễ dàng :

Bất cứ khi nào bạn thêm một tệp, hãy MediaStore Content Provider biết về nó bằng cách sử

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

Đối xóa:. chỉ cần sử dụng getContentResolver() xóa (uri , null, null) (Tín dụng chuyển đến DDSports)

+0

có lẽ điều đó có nghĩa là sửa chữa vấn đề các tệp mồ côi cắt xén ngay từ đầu. Ứng dụng của tôi là để dọn dẹp mớ hỗn độn trái bởi _other_ các ứng dụng mà không làm – roryok

+1

này tôi đã cho điều này một phiếu bầu tán thành vì trong khi nó không giải quyết được vấn đề chính xác đề cập, đó là một mảnh rất có giá trị của thông tin mà tôi nghĩ là có liên quan. – Matt

+2

Điều này thực sự chỉ hoạt động khi thêm tệp. Nó không hoạt động khi một tập tin được xóa. Bạn cần getContentResolver(). Delete (uri, null, null); phương pháp cho điều đó. – DDSports

Các vấn đề liên quan