zoukankan      html  css  js  c++  java
  • Android 扫描SD卡内所有MP3(音频)文件

        这段时间一个MP3小项目,其中有一个功能就是扫描SD卡内所有MP3文件。

    在这儿我首先就想到了一个方法:遍历SD卡内所有目录或文件

    1.遍历SD卡内所有目录或文件

    package com.wenhao.test.sddemo;
    
    import java.io.File;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Environment;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.Toast;
    
    public class MainDemo extends Activity {
        /** Called when the activity is first created. */
        
        private Button button = null;
        private File path;
        
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
               
            button = (Button)findViewById(R.id.mybutton);
            
            //检测SD卡是否存在
            if (Environment.getExternalStorageState().equals(
                    Environment.MEDIA_MOUNTED)) {
                path = Environment.getExternalStorageDirectory();
            }else{
                Toast.makeText(this, "没有SD卡", Toast.LENGTH_LONG).show();
                finish();
            }
            
            button.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub                                
                    getAllFiles(path);
                }
            });
            
        }
        
        // 遍历接收一个文件路径,然后把文件子目录中的所有文件遍历并输出来 
        private void getAllFiles(File root){  
            File files[] = root.listFiles();  
            if(files != null){  
                for (File f : files){  
                    if(f.isDirectory()){  
                        getAllFiles(f);  
                    }else{  
                        System.out.println(f);  
                    }  
                }  
            }  
        }  
          
    }
    View Code

    但是这样做,我们先扫描所有文件或目录,然后将其加入到我们自己的数据库里。由于遍历全部文件或目录效率很低,所以这种方法不可取,这里只是顺带提及一下这个可行的方法。

    2.利用Android系统自建数据库

    上一篇文章里我们用到Android系统自建的数据库,使用ContentProvider提供联系人数据。

    android.provider.ContactsContract.Contacts.CONTENT_URI

    在Android机中,系统会根据SD卡内的目前所有MP3文件,定时更新(新建)音频文件信息数据库。这个数据在哪儿呢?

    并不在SD卡里,root后的机器通过R.E.管理器就可以看到相关数据库了。

    /data/data/com.android.providers.media/databases/external.db

    我的手机(魅族MX2)external.db里面的表

     将external.db用工具打开,

     红色框就是音频文件的相关属性,一般能包含音频文件的大部分属性,若其中没有包含你要的属性,你可以自建数据库。否则,你可以利用此数据库,可以减少一部分代码。

     由于我的音频属性中包含自带数据库中没有的属性,如:path,folder,format,channels,kbps,hz属性。

    因此我选则了自建数据库。

    下面是一段利用自带数据库获取SD卡内所有音频文件的路径代码:

        /**
         * 获取SD卡内所有音频文件的路径
         * 有多少条记录,List就有多大
         * @return
         *         ScanInfo类型的表
         */
        public List<ScanInfo> searchAllDirectory() {
            List<ScanInfo> list = new ArrayList<ScanInfo>();
            StringBuffer sb = new StringBuffer();//存放data的缓存
            //要返回的列(属性)
            String[] projection = { MediaStore.Audio.Media.DISPLAY_NAME,MediaStore.Audio.Media.DATA };
            /*
             * 参数:
             * uri 提供内容的地址
             * projection 查询要返回的列
             * selection 查询where字句
             * selectionArgs 查询条件属性值
             * sortOrder 结果排序规则
             */
            Cursor cr = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, null,null, MediaStore.Audio.Media.DISPLAY_NAME);
            String displayName = null;
            String data = null;
            while (cr.moveToNext()) {//移动到下一刻度,返回boolean类型值
                displayName = cr.getString(cr.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));//音频文件名
                data = cr.getString(cr.getColumnIndex(MediaStore.Audio.Media.DATA));//音频文件路径+文件名
                if(data!=null&&displayName!=null){
                    data = data.replace(displayName, " ");// 替换文件名留下它的上一级目录
                }
                
                if (!sb.toString().contains(data)) {
                    list.add(new ScanInfo(data, true));//默认全部勾选
                    sb.append(data);//加入到缓存里
                }
            }
            cr.close();//关闭游标
            return list;
        }
    View Code

    如果是获取音频文件其他属性也可类似用此方法。

    好了,最后一个问题<当你往sd卡中添加一些音频文件的时候,android没有自动及时将它刷新到数据库中。那么我们怎么让它手动刷新呢,如下:
    IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED); 
            intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); 
            intentFilter.addDataScheme("file"); 
            scanReceiver = new ScanSdFilesReceiver(); 
            registerReceiver(scanReceiver, intentFilter); 
            sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 
      
      
    private class ScanSdFilesReceiver extends BroadcastReceiver { 
            public void onReceive(Context context, Intent intent) { 
                String action = intent.getAction(); 
                if (Intent.ACTION_MEDIA_SCANNER_STARTED.equals(action)) { 
                    scanHandler.sendEmptyMessage(STARTED); 
                } 
                if (Intent.ACTION_MEDIA_SCANNER_FINISHED.equals(action)) { 
                    scanHandler.sendEmptyMessage(FINISHED); 
                } 
            } 
        } 
      
      
    private Handler scanHandler = new Handler() { 
            public void handleMessage(Message msg) { 
                super.handleMessage(msg); 
                switch (msg.what) { 
                case STARTED: 
                    MyDialog scanDialog = new MyDialog(LocalList.this); 
                    scanAlertDialog = scanDialog.scanFile(); 
                    scanAlertDialog.show(); 
                    Log.i(TAG, "showing"); 
                    break; 
                case FINISHED: 
                    ArrayList<Song> tempSongs = ReadFileList.readDataFromSD(LocalList.this, LOCAL); 
                    if (tempSongs != null && tempSongs.size()>0) { 
                        if (songs != null && songs.size()>0) { 
                            songs.clear(); 
                            songs.addAll(tempSongs); 
                            songAdapter.notifyDataSetChanged(); 
                        }else { 
                            songs = new ArrayList<Song>(); 
                            songs.addAll(tempSongs); 
                            initSong_lv(); 
                        } 
                    }else { 
                        Toast.makeText(LocalList.this, "SD卡中没有歌曲,请添加后再扫描", Toast.LENGTH_SHORT).show(); 
                    } 
                    Log.i(TAG, "finish"); 
                    if (scanAlertDialog!=null && scanAlertDialog.isShowing()) { 
                        scanAlertDialog.dismiss(); 
                    } 
                    unregisterReceiver(scanReceiver); 
                    break; 
                case DISMISS: 
                    Log.i(TAG, "dismiss"); 
                    if (scanAlertDialog!=null && scanAlertDialog.isShowing()) { 
                        scanAlertDialog.dismiss(); 
                    } 
                default: 
                    break; 
                } 
    View Code

    对于其他类型的文件,只要com.android.providers中有这种文件信息数据库,扫描SD卡内所有这种类型文件也可以同样这么做。

  • 相关阅读:
    MS SQL执行大脚本文件时,提示“未能完成操作,存储空间不足,无法处理此命令”的解决办法
    一、Flux 是什么?
    for...in for..of
    循环总结
    javascript中几种this指向问题
    redux
    布局方式
    js获取前几个月的具体日期
    动态引入js文件
    获取页面url信息
  • 原文地址:https://www.cnblogs.com/android-for-dh/p/4449605.html
Copyright © 2011-2022 走看看