我们经常需要获取手机信息,例如我们想做一个音乐播放器,我们需要拿到本地的音频信息,这样一来,我们就需要考虑如何拿到这些数据了
这个叫做MediaProvider.apk是干什么的呢,和我们今天讲的东西有啥关联吗,其实这是一个正在运行的apk,这个apk是没有界面的,因此我们是看不见的,他的作用就是在后台默默的为我们收集相关的数据信息。,然后保存在数据库里面
从上面的截图上看,这个apk把我们收集内的媒体信息都存储在数据库中了,那么接下来我们只需要读取数据库,拿到相关的资源即可了。
这里获取资源,我给大家提供三种方式
子线程+handler:
这个首先是创建子线程:
//这个是android中的内容提供者,上面所说的三种方式都需要用到这个,主要提供android手机的内的基本数据信息
val resolver = context?.contentResolver
Thread(
object:Runable{
override fun run(){
var cursor = resolver?.query(
//这方法不懂请看下面的源码分析,看完我们再接着往下看
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
arrayOf(
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.SIZE,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.ARIST
), null ,null.null
)
//上面返回的是一个游标,我们定义一个处理游标的方法类,接着看下面的游标类
CursorUtil(cursor)
var msg = Message.obtain()
msg.obj = cursor
handler.setMessage(mgs)
//注意 handler创建我这里就不写了,注意最好使用防止内存泄漏的写法
}
}
).start()
object CursorUtil{
fun logCursor(cursor: Cursor){
cursor.let{
//游标复位
it.moveToPisition(-1)
//每次游标向下移动一位,读取一条数据,然后获取每条数据的具体
while(it.moveToNext){
//每条数据来一次for循环
for(index in 0 until it.columnCount){
println("key======${it.getColumn(index)}----value===${it.getString(index)}")
}
println("=========下一条数据")
}
}
}
}
下面我们来看一下query的源码信息
/**
通过提供的uri信息,返回一个Cursor数据
* Query the given URI, returning a {@link Cursor} over the result set.
* 第一个参数是uri信息
* @param uri The URI, using the content:// scheme, for the content to
* retrieve.
* 第二个参数是需要返回的数据条目有哪些,例如名字、作者、大小
* @param projection A list of which columns to return. Passing null will
* return all columns, which is inefficient.
* 第三个参数是根据条件返回多少行。如果为空则返回所有行 这个相当于sql语句后面的where语句
* @param selection A filter declaring which rows to return, formatted as an
* SQL WHERE clause (excluding the WHERE itself). Passing null will
* return all rows for the given URI.
* 选择包括哪些选项,一般写null
* @param selectionArgs You may include ?s in selection, which will be
* replaced by the values from selectionArgs, in the order that they
* appear in the selection. The values will be bound as Strings.
* 这个参数相当于orderby的效果,一般写null
* @param sortOrder How to order the rows, formatted as an SQL ORDER BY
* clause (excluding the ORDER BY itself). Passing null will use the
* default sort order, which may be unordered.
* @return A Cursor object, which is positioned before the first entry, or null
* @see Cursor
*/
public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder) {
return query(uri, projection, selection, selectionArgs, sortOrder, null);
}
下面是打印出来的结果
2019-04-17 09:27:49.123 7252-7252/app.bxvip.com.myphone I/System.out: 搜索成功了
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: key=======_data---value====/data/hw_init/product/media/Pre-loaded/Music/Bach_Suite.flac
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: key=======_size---value====13016489
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: key=======_display_name---value====Bach_Suite.flac
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: key=======artist---value====Cory J. Wong
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: =========================下一条数据
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: key=======_data---value====/data/hw_init/product/media/Pre-loaded/Music/Dream_It_Possible.flac
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: key=======_size---value====25558969
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: key=======_display_name---value====Dream_It_Possible.flac
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: key=======artist---value====Delacey
2019-04-17 09:27:49.124 7252-7252/app.bxvip.com.myphone I/System.out: =========================下一条数据
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_data---value====/data/hw_init/product/media/Pre-loaded/Music/Goldberg_Variations.flac
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_size---value====15273741
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_display_name---value====Goldberg_Variations.flac
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======artist---value====Johann Sebastian Bach
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: =========================下一条数据
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_data---value====/data/hw_init/product/media/Pre-loaded/Music/Music_My_Love.flac
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_size---value====24201533
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_display_name---value====Music_My_Love.flac
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======artist---value====Marye Lobb
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: =========================下一条数据
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_data---value====/storage/emulated/0/msc/哈喽.wav
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_size---value====377600
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======_display_name---value====哈喽.wav
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: key=======artist---value====
2019-04-17 09:27:49.125 7252-7252/app.bxvip.com.myphone I/System.out: =========================下一条数据
上面是直接的handler+线程的方式
/**
*这里注意这个三个参数
第一个参数数传递进来的参数
第二个参数表示的进度更新的时候向外传递的数据
第三个参数是处理完后的参数
*/
class AudioTask:AsyncTask<ContentResolver,Void, Cursor>(){
ovrride fun doInBackground(vararg param: ContentResolver?):Cursor{
//这个方法是在子线程中运行的
val cursor = param[0]?.query(
//这方法不懂请看下面的源码分析,看完我们再接着往下看
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
arrayOf(
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.SIZE,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.ARIST
), null ,null.null
)
retturn cursor // 这里跟第三个参数对应
}
ovveride fun onPostExecute(result: Cursor?){
super.onPostExecute(result)
//打印
CursorUtil.logCursor(result!!)
}
//这个方式是在异步任务之前准备的函数
override fun onPreExecute() {
super.onPreExecute()
}
//这个函数是在主线程中执行的,一般用于更新进度
override fun onProgressUpdate(vararg values: Void?) {
super.onProgressUpdate(*values)
}
]
上面就是以异步任务的方式,是不是感觉很爽呢,下面再介绍一个种更爽的方式。
从名字上看是不是已经看出来了是异步加handler呢,接下来看怎么实现吧
val handler = object: AsyncQueryHandler(resolver){
//查询完成的回调 还没查嫩怎么回调,不要急,查询的在后面,相当于观察者模式一样
override fun onQueryComple(token: Int, cookie: Any?, cursor: Cursor?){
//回调到这里,线程就已经切换到了主线程
CursorUtil.logCursor(cursor!!)
}
}
handler.startQuery(0,null,MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,arrayOf(MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.SIZE,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.ARTIST),null,null,null)
上面这种是不是更爽呢,三种方式就介绍到这里把,看大家怎么选择