数据库的处理

音频文件的查找

既然是音乐播放器,就必须要面对一个问题:把你本地的音乐文件找出来,才能播放出来。但是每次播放都去找一次未免会浪费很多时间,所以就是第一次运行的时候扫描一次存储器,把音频文件找出来,并且把路径和相关信息保存到我们APP的数据库中。


数据库的创建

首先从数据库出发,Android用的是SQLite数据库,而且还有一个DataBaseHelper类来帮助我们获取数据库:

public class DatabaseHelper extends SQLiteOpenHelper
{

    private static SQLiteDatabase mdb;
    private static DatabaseHelper mHelper;
    private static final int DB_VERSION = 3;
    private static final String DB_NAME="musicstore_new";
    private static final String TABLE_ALBUM = "album_info";
    private static final String TABLE_ARTIST = "artist_info";
    private static final String TABLE_MUSIC = "music_info";
    private static final String TABLE_FOLDER = "folder_info";
    private static final String TABLE_FAVORITE = "favorite_info";


    //获取Helper中的数据库
    public static SQLiteDatabase getInstance(Context context)
    {
        if(mdb==null)
        {
            mdb=getHelper(context).getWritableDatabase();
        }
        return mdb;
    }
    //获取Helper本身
    public static DatabaseHelper getHelper(Context context)
    {
        if(mHelper==null)
        {
            mHelper=new DatabaseHelper(context);
        }
        return mHelper;
    }
    //包装一下的构造函数
    public DatabaseHelper(Context context)
    {
        super(context, DB_NAME, null, DB_VERSION);
    }
    //第一次运行getWritableDatabase()时获取不到数据库文件,就会创建一个在data/data/<package name>/文件夹中,并回调该函数
    @Override
    public void onCreate(SQLiteDatabase arg0)
    {
        // TODO Auto-generated method stub
        arg0.execSQL("create table "
                + TABLE_MUSIC
                + " (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
                + " songid integer, albumid integer, duration integer, musicname varchar(10), "
                + "artist char, data char, folder char, musicnamekey char, artistkey char, favorite integer)");
        arg0.execSQL("create table "
                + TABLE_ALBUM
                + "(_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                + "album_name char, album_id integer, number_of_songs integer, album_art char)");
        arg0.execSQL("create table "
                + TABLE_ARTIST
                + "(_id INTEGER PRIMARY KEY AUTOINCREMENT, artist_name char, number_of_tracks integer)");
        arg0.execSQL("create table "
                + TABLE_FOLDER
                + "(_id INTEGER PRIMARY KEY AUTOINCREMENT, folder_name char, folder_path char)");
        arg0.execSQL("create table "
                + TABLE_FAVORITE
                + " (_id integer,"
                + " songid integer, albumid integer, duration integer, musicname varchar(10), "
                + "artist char, data char, folder char, musicnamekey char, artistkey char, favorite integer)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2)
    {
        // TODO Auto-generated method stub
        if(arg2>arg1)
        {
            arg0.execSQL("DROP TABLE IF EXISTS " + TABLE_ARTIST);
            arg0.execSQL("DROP TABLE IF EXISTS " + TABLE_ALBUM);
            arg0.execSQL("DROP TABLE IF EXISTS " + TABLE_MUSIC);
            arg0.execSQL("DROP TABLE IF EXISTS " + TABLE_FOLDER);
            onCreate(arg0);
        }
    }

    public void clearTable()
    {
        SQLiteDatabase db=this.getWritableDatabase();
        db.delete(TABLE_ALBUM, null, null);
        db.delete(TABLE_ARTIST, null, null);
        db.delete(TABLE_FAVORITE, null, null);
        db.delete(TABLE_FOLDER, null, null);
        db.delete(TABLE_MUSIC, null, null);
    }
}

这里用到了设计模式中的单例模式,每次获取的都是static的那个一开始创建的database,第一次调用getInstance时会创建Helper本身,然后利用Helper.getWritableDatabase();来获取可以写的数据库,getWritableDatabase()运行时会看看数据库存不存在,不存在就会去创建一个新的数据库,执行onCeate()函数,顺带创建了各张表,然后返回给用户使用。数据库表中的各个属性就是要从Android系统中获取并且写进表中。


利用ContentReslover来获取Android数据
  1. 查找音乐文件的ID,专辑ID,持续时间,音乐名,歌手,所在路径(与音乐文件相关信息去URI=MediaStore.Audio.Media.EXTERNAL_CONTENT_URI)
private static String[] proj_music={MediaStore.Audio.Media._ID,MediaStore.Audio.Media.ALBUM_ID, MediaStore.Audio.Media.DURATION,MediaStore.Audio.Media.TITLE,MediaStore.Audio.Media.ARTIST,
        MediaStore.Audio.Media.DATA};
cr.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj_music, null, null, MediaStore.Audio.Media.ALBUM_KEY)

cr.query返回的是Cursor,我们要遍历浮标:

public static List<MusicInfo> getMusicList(Cursor cursor)
    {
        if(cursor==null)
        {
            return null;
        }
        List<MusicInfo> list=new ArrayList<>();
        while(cursor.moveToNext())
        {
            MusicInfo info=new MusicInfo();
            info.songid=cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media._ID));
            info.albumid=cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
            info.duration=cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
            info.musicname=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
            info.artist=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
            String filepath=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
            info.data=filepath;
            info.folder=filepath.substring(0, filepath.lastIndexOf(File.separator));
            list.add(info);
        }
        cursor.close();
        return list;
    }

2.找专辑相关信息
Alubms->android.provider.MediaStore.Audio.Albums;

private static String[] proj_album = new String[] { Albums.ALBUM,
        Albums.NUMBER_OF_SONGS, Albums._ID, Albums.ALBUM_ART };
getAlbumList(cr.query(Albums.EXTERNAL_CONTENT_URI, proj_album, null, null, Media.ALBUM_KEY));


3.找作者相关信息

private static String[] proj_artist = new String[] {
        MediaStore.Audio.Artists.ARTIST,
        MediaStore.Audio.Artists.NUMBER_OF_TRACKS };
getArtistList(cr.query(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, proj_artist, null, null, MediaStore.Audio.Artists.NUMBER_OF_TRACKS+" desc"));

4.寻找音频文件所在文件夹位置

ContentResolver cr=context.getContentResolver();
            Uri uri=MediaStore.Files.getContentUri("external");
            StringBuilder mSelection = new StringBuilder(FileColumns.MEDIA_TYPE
                    + " = " + FileColumns.MEDIA_TYPE_AUDIO + " and " + "("
                    + FileColumns.DATA + " like'%.mp3' or " + Media.DATA
                    + " like'%.wma')");
            mSelection.append(") group by ( " + FileColumns.PARENT);//这句把同目录的所有音频文件合并了
            List<FolderInfo> list=getFolderList(cr.query(uri, proj_folder, mSelection.toString(), null, null));

系统级ContentProvider深入探究

学习ContentProvider的时候我们知道要在Manifest.xml里面声明其URI,然后ContentReslover就能利用该URI找到这个ContentProvider,利用其重写的增改删除操作数据库,上面就涉及到了好几个URI:
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI
MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI
MediaStore.Files.getContentUri(“external”);

它们所对应的ContentProvider应该分别处理不同的,一个或多个数据库表。下面就来看看这些数据库的表到底是怎样情况的,怎样实现查找到一首歌的歌名之类。
这些ContentProvider对应的数据库存在哪里?Android是基于Linux内核,文件系统和Linux类似,平时手机的内部存储都是位于/目录下面的,而SD卡的目录则是在/mnt/sdcard下面

而/data/data/里面有好多应用的数据,存放着系统里面有哪些音乐文件,相关信息的数据库就在这个里面
我们可以用adb调试工具来看看里面的情况


里面有好多张表,其中有的表就存着我们要查找的数据了,例如我想找当前系统有哪些文件,可以先用sqlite的命令看看该表的列属性,我用红线画了一些常用的属性列

也可以用select语句把信息取出来看看

目前系统外存中所有的音频文件就找出来了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值