精华内容
下载资源
问答
  • Android MediaStore的基本使用
    千次阅读
    2022-03-16 17:43:38

    Android cursor query && 访问MediaStore

    MediaStore这个类是Android系统提供的一个多媒体数据库,android中多媒体信息都可以从这里提取。这个MediaStore包括了多媒体数据库的所有信息,包括音频,视频和图像,android把所有的多媒体数据库接口进行了封装,所有的数据库不用自己进行创建,直接使用ContentResolver去调用那些封装好的接口就可以进行数据库的操作了。
    //获取ContentResolver实例
    ContentResolver mResolver = ctx.getContentResolver();
    //ContentResolver实例获得后,就可以进行各种增删改查的方法
    
    查看android提供的多媒体表:内部数据库和外部数据库
    /data/data/com.google.android.providers.media.module/databases/external.db
    /data/data/com.google.android.providers.media.module/databases/internal.db
    adb sqlite3命令
    然后输入命令sqlite3加上这个数据库的名字就可以查询android的多媒体数据库了。.table命令可以列出所有多媒体数据库的表,.schema加上表名可以查询表中的所有列名。这里可以利用SQL语句来查看你想要的数据,记得最后一定要记住每条语句后面都加上分号。
    

    源码MediaStore.java

    /**
     * Implement this to handle query requests from clients.
     *
     * @param uri The URI to query. This will be the full URI sent by the client;
     *      if the client is requesting a specific record, the URI will end in a record number
     *      that the implementation should parse and add to a WHERE or HAVING clause, specifying
     *      that _id value.
     * @param projection The list of columns to put into the cursor. If
     *      {@code null} all columns are included.
     * @param selection A selection criteria to apply when filtering rows.
     *      If {@code null} then all rows are included.
     * @param selectionArgs You may include ?s in selection, which will be replaced by
     *      the values from selectionArgs, in order that they appear in the selection.
     *      The values will be bound as Strings.
     * @param sortOrder How the rows in the cursor should be sorted.
     *      If {@code null} then the provider is free to define the sort order.
     * @return a Cursor or {@code null}.
     */
    public abstract @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
            @Nullable String selection, @Nullable String[] selectionArgs,
            @Nullable String sortOrder);
    
    
    /**
     * Implement this to handle requests to insert a new row. 
     *
     * @param uri The content:// URI of the insertion request.
     * @param values A set of column_name/value pairs to add to the database.
     * @return The URI for the newly inserted item.
     */
    public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
    
    
    /**
     * Implement this to handle requests to delete one or more rows. 
     *
     * @param uri The full URI to query, including a row ID (if a specific
     *            record is requested).
     * @param selection An optional restriction to apply to rows when deleting.
     * @return The number of rows affected.
     * @throws SQLException
     */
    public abstract int delete(@NonNull Uri uri, @Nullable String selection,
            @Nullable String[] selectionArgs);
    
    /**
     * Implement this to handle requests to update one or more rows. 
     *
     * @param uri The URI to query. This can potentially have a record ID if
     *            this is an update request for a specific record.
     * @param values A set of column_name/value pairs to update in the database.
     * @param selection An optional filter to match rows to update.
     * @return the number of rows affected.
     */
    public abstract int update(@NonNull Uri uri, @Nullable ContentValues values,
            @Nullable String selection, @Nullable String[] selectionArgs);
    

    public final Cursor query (Uri uri, String[] projection,String selection,String[] selectionArgs, String sortOrder)

    Uri:这个Uri代表要查询的数据库名称加上表的名称。这个Uri一般都直接从MediaStore里取得,

    上面我们提到了Android提供内容的叫Provider,那么在Android中怎么区分各个Provider?有提供联系人的,有提供图片的等等。所以就需要有一个唯一的标识来标识这个Provider,Uri就是这个标识,android.provider.ContactsContract.Contacts.CONTENT_URI就是提供联系人的内容提供者

    projection:代表要从表中选择的列,用一个String数组来表示。告诉Provider要返回的内容(列Column)

    selection:相当于SQL语句中的where子句,就是代表你的查询条件。null表示不进行筛选

    selectArgs:如果你的selection里有?这个符号时,这里可以以实际值代替这个问号。如果Selections这个没有?的话,那么这个String数组可以为null。

    sortOrder:说明查询结果按什么来排序。相当于SQL语句中的Order by,升序 asc /降序 desc,null为默认排序

    MediaStore常用的uri
    MediaStore.Video.Media
    MediaStore.Audio.Media
    MediaStore.Images.Media
    //MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    //MediaStore.Images.Media.INTERNAL_CONTENT_URI
    MediaStore.Downloads.INTERNAL_CONTENT_URI
    MediaStore.Downloads.EXTERNAL_CONTENT_URI  
    可移动存储: MediaStore.Downloads.getContentUri(String volumeName)
        
    不过总有些文件比较特殊,用上面的方法查询不出来,或者说,某些媒体文件扫描不到,就没有添加进上述三个数据源中,导致查询不出来;这种情况下,可以尝试用MediaStore.Files。MediaStore.Files存储了所有应用中共享的文件,包括图片、文件、视频、音乐等多媒体文件,包括非多媒体文件。
    
    //MediaStore.Files没有EXTERNAL_CONTENT_URI,所以只能用getContentUri()自行获取,得出的URI其实是Uri.parse("content://media/external/files")
    MediaStore.Files.getContentUri(String volumeName)
    MediaStore.Files.getContentUri("external")
    
    
    //查找
    例如我想要查询目录为“pic”的所有图片的ID和名称,就这样写:
    Cursor cursor = this.getContentResolver().query(
    //数据源,EXTERNAL_CONTENT_URI是外部存储数据源,相应的INTERNAL_CONTENT_URI是内部存储源
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
    //查询ID和名称   
    new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.TITLE},   
    //条件为目录名      
    MediaStore.Images.Media.BUCKET_DISPLAY_NAME + " = ?", 
    //目录名为pic                                   
    new String[]{"pic"}, 
    //按ID倒序排列                           
    MediaStore.Images.Media._ID+" DESC"); 
    
    换作SQL语句大概是这样的:
    SELECT _id,title FROM images WHERE bucket_display_name = "pic" ORDER BY _id DESC
    
    //查找获取cursor,怎么获取该数据
    Cursor cursor = this.getContentResolver().query(
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
        null, 
        null, 
        null, 
        null);
    //图片路径所在列的索引
    int indexPhotoPath = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    while (cursor.moveToNext()) {
        //打印图片的路径
        Log.i("uri:", cursor.getString(indexPhotoPath));
    }
    cursor.close();
    
    ContentResolver resolver = ctx.getContentResolver();
    //增加
    ContentValues values = new ContentValues();
    values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER,0);
    resolver.insert(_uri, values);
    
    //删除
    resolver.delete(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,where, selectionArgs); 
    
    //查找
    
    //更新
    ContentValues values = new ContentValues();
    values.put(MediaStore.Audio.Media.DATE_MODIFIED, sid);
    resolver.update(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,values, where, selectionArgs); 
    

    相关参考:
    https://blog.csdn.net/ruiqingzheng/article/details/50651495
    https://www.jianshu.com/p/be92dde9598f
    https://blog.csdn.net/ifmylove2011/article/details/51425921

    更多相关内容
  • 如何保存、获取MediaStore内容 如何通过SAF获取文件/文件夹的Uri 如何通过SAF传入Uri对文件进行操作 为什么? 作为Android的开发者,大家应该对早年Android手机被人抱怨卡顿、手机存储空间被应用占用、文件被毒瘤...
  • 【Android 文件管理】分区存储 ( MediaStore 文件操作 ) https://hanshuliang.blog.csdn.net/article/details/116948386 博客源码
  • Android系统提供了MediaScanner,MediaProvider,MediaStore等接口,并且提供了一套数据库表格,通过Content Provider的方式提供给用户。当手机开机或者有SD卡插拔等事件发生时,系统将会自动扫描SD卡和手机内存上的...
  • 通过MediaStore在AWS上进行实时流传输 带有MediaStore的AWS上的实时流媒体会自动配置AWS Elemental MediaLive,AWS Elemental MediaStore和Amazon CloudFront,以通过AWS云提取,编码,打包和交付单个源实时流。 该...
  • android 通过MediaStore 数据库获取本地指定文件夹下的视频文件 可以排序并删除文件
  • MediaStore_Media_System 基于MediaStore的多媒体系统
  • MediaStore数据库分析

    2021-07-18 16:28:01
    图片在文件管理中删除之后MediaStore不更新问题? MediaStore 概述 MediaStore是Android系统提供的一个多媒体数据库,专门用于存放多媒体信息,通过ContentResolver可对数据库进行操作。 本篇文章会讲述一个标准的从...

    MediaStore

    概述

    MediaStore是Android系统提供的一个多媒体数据库,专门用于存放多媒体信息,通过ContentResolver可对数据库进行操作。

    本篇文章会讲述一个标准的从MediaStore数据库获取图片数据并展示到自己使用RecyclerView实现的相册中的过程,并且会带着以下几个问题来解释为什么要这么做。

    • MediaStore、MediaScannerReceiver、MediaScannerService、MediaScanner、ContentResolver、MediaScannerConnection 是如何实现数据库的增删改查操作的?

    • 为什么网络图片下载到手机之后相册里还是没有数据?

    • 如何做到下载图片之后可以立马在相册中显示?

    • 图片在文件管理中删除之后MediaStore不更新问题?(真实工作中自家Rom出现的问题)

    读取MediaStore数据、设置监听、显示数据

    查询数据

    通过ContentResolver提供的查询接口来获取MediaStore数据(对应下述 扩展说明A)

    注册监听

    调用ContentResolver的registerContentObserver方法来设置监听(对应下述 扩展说明B)

        fun loadImages() {
            viewModelScope.launch {
                val imageList = queryImages()  //-> A
                _images.postValue(imageList)
    
                if (contentObserver == null) {  //-> B
                    contentObserver = getApplication<Application>().contentResolver.registerObserver(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                    ) {
                        loadImages()
                    }
                }
            }
        }
    

    代码扩展说明

    注释点 **A ** --> queryImages() 方法使用ContentResolver获取图片列表并赋值给imageList,然后通过LiveDate的postValue发送出去,Activity会监听此LiveData,从而拿到imageList进行ListAdapter的刷新操作。queryImages()具体方法如下:

        private suspend fun queryImages(): List<MediaStoreImage> {
            val images = mutableListOf<MediaStoreImage>()
    
            withContext(Dispatchers.IO) {
    
                val projection = arrayOf(
                    MediaStore.Images.Media._ID,
                    MediaStore.Images.Media.DISPLAY_NAME,
                    MediaStore.Images.Media.DATE_ADDED
                )
                val selection = "${MediaStore.Images.Media.DATE_ADDED} >= ?"
    
                val selectionArgs = arrayOf(
                    dateToTimestamp(day = 22, month = 10, year = 2008).toString()
                )
    
                val sortOrder = "${MediaStore.Images.Media.DATE_ADDED} DESC"
    
                getApplication<Application>().contentResolver.query(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    projection,
                    selection,
                    selectionArgs,
                    sortOrder
                )?.use { cursor ->
                    val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
                    val dateModifiedColumn =
                        cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED)
                    val displayNameColumn =
                        cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)
    
                    Log.i(TAG, "Found ${cursor.count} images")
                    while (cursor.moveToNext()) {
                        val id = cursor.getLong(idColumn)
                        val dateModified =
                            Date(TimeUnit.SECONDS.toMillis(cursor.getLong(dateModifiedColumn)))
                        val displayName = cursor.getString(displayNameColumn)
                        val contentUri = ContentUris.withAppendedId(
                            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                            id
                        )
                        val image = MediaStoreImage(id, displayName, dateModified, contentUri)
                        images += image
                        Log.v(TAG, "Added image: $image")
                    }
                }
            }
            Log.v(TAG, "Found ${images.size} images")
            return images
        }
    
        /**
         *  日期格式化
         */
        private fun dateToTimestamp(day: Int, month: Int, year: Int): Long =
            SimpleDateFormat("dd.MM.yyyy").let { formatter ->
                TimeUnit.MICROSECONDS.toSeconds(formatter.parse("$day.$month.$year")?.time ?: 0)
            }
    
    //上述代码内容有点多,稍微做一下阐述,有以下几步操作:
    
    //1、withContext(Dispatchers.IO) 协程切换到IO线程执行
    //2、创建projection、selection、selectionArgs、sortOrder这几个query需要的参数
    //3、执行query操作并返回Cursor对象
    //4、通过Cursor对象获取图片的参数并创建MediaStoreImage对象
    //5、将MediaStoreImage添加到list并返回
    
    
    //MediaStoreImage是我们定义的bean对象,用于在RecycleView中数据的显示
    data class MediaStoreImage(
        val id: Long,
        val displayName: String,
        val dateAdded: Date,
        val contentUri: Uri
    )
    

    注释点 B --> registerObserver是我定义的ContentResolver的一个扩展方法,他实现了对MediaStore.Images.Media.EXTERNAL_CONTENT_URI的监听,当数据变化会重新调用loadImages()方法–>queryImages()方法,获取MediaStore数据 。ContentResolver的扩展方法如下:

    private fun ContentResolver.registerObserver(
        uri: Uri,
        observer: (selfChange: Boolean) -> Unit
    ): ContentObserver {
        val contentObserver = object : ContentObserver(Handler()) {
            override fun onChange(selfChange: Boolean) {
                observer(selfChange)
            }
        }
        registerContentObserver(uri, true, contentObserver)
        return contentObserver
    }
    
    

    上述两个注释点A|B都会调用queryImages()方法来获取图片列表,A是主动触发,而B是MediaStore数据库更新之后被动触发,所以此时的代码我们已经可是保证images可以跟MediaStore下的图片保持一致了。

    界面显示

    最后是界面显示,我使用的是RecyclerView.Adapter的子类ListAdapter来实现列表显示和更新,并且将点击事件作为参数传入到Adapter(高阶函数方式),这个没什么好说的,不懂的可已看下ListAdapter标准写法

    class GalleryAdapter(private val onClick: (MediaStoreImage) -> Unit) :
        ListAdapter<MediaStoreImage, ImageViewHolder>(DiffCallback) {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
            val layoutInflater = LayoutInflater.from(parent.context)
            val view = layoutInflater.inflate(R.layout.gallery_layout, parent, false)
            return ImageViewHolder(view, onClick)
        }
    
        override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
            val mediaStoreImage = getItem(position)
            holder.rootView.tag = mediaStoreImage
    
            Glide.with(holder.imageView)
                .load(mediaStoreImage.contentUri)
                .thumbnail(0.33f)
                .centerCrop()
                .into(holder.imageView)
        }
    
        companion object {
            val DiffCallback = object : DiffUtil.ItemCallback<MediaStoreImage>() {
                override fun areItemsTheSame(oldItem: MediaStoreImage, newItem: MediaStoreImage) =
                    oldItem.id == newItem.id
    
                override fun areContentsTheSame(oldItem: MediaStoreImage, newItem: MediaStoreImage) =
                    oldItem == newItem
            }
        }
    }
    

    添加点击事件

    // 初始化GalleryAdapter,并通过高阶函数方式传入一个deleteImage方法
    val galleryAdapter = GalleryAdapter { image ->
                deleteImage(image)
            }
    
    
    //界面显示的关键方法,监听了viewModel里的images(是个LiveDate),拿到List<MediaStoreImage>更新ListAdapter
    viewModel.images.observe(this, Observer<List<MediaStoreImage>> { images ->
                galleryAdapter.submitList(images)
            })
    
    
    //deleteImage方法会在点击Adapter中任意一项的时候弹出Dialog,会调用deleteImage
    // 最终调用contentResolver的delete来删除此项Image,篇幅有限删除请查看最终代码
    private fun deleteImage(image: MediaStoreImage) {
            MaterialAlertDialogBuilder(this)
                .setTitle(R.string.delete_dialog_title)
                .setMessage(getString(R.string.delete_dialog_message, image.displayName))
                .setPositiveButton(R.string.delete_dialog_positive) { _: DialogInterface, _: Int ->
                    viewModel.deleteImage(image)
                }
                .setNegativeButton(R.string.delete_dialog_negative) { dialog: DialogInterface, _: Int ->
                    dialog.dismiss()
                }
                .show()
        }
    

    最终代码

    https://github.com/WuMaoQiang/nobo_mediastore

    问题处理

    为什么网络图片下载到手机之后相册里还是没有数据?

    MediaStore的刷新不是实时的,比如开机,U盘挂载等场景会触发刷新,当我们下载一张网路图片,虽然图片下载成功了,在文件管理中可以找到这个图片,但是相册中却看不到,这是MediaStore设计如此。所以如果我们想让相册或者任何关心MediaStore的应用能立马看到这个图片那就要主动触发刷新MediaStore。

    如何做到下载图片之后可以立马在相册中显示?

    有三种方式可以做到:

    1、使用MediaStore.Image.Media.inserImage()方法,直接通过ContentResolver操作数据库

    在这里插入图片描述

    2、发送ACTION_MEDIA_SCANNER_SCAN_FILE广播。查看系统类 广播类MediaScannerReceiver会对此Action做出响应,调用scanFile方法

    在这里插入图片描述

    而ScanFile方法启动了一个Service进行Scan操作

       private void scanFile(Context context, String path) {
    80        Bundle args = new Bundle();
    81        args.putString("filepath", path);
    82        context.startService(
    83                new Intent(context, MediaScannerService.class).putExtras(args));
    84    }
    85}
    

    MediaScannerService创建MediaScanner执行scanSingleFile进行全盘扫描操作

    在这里插入图片描述

    3、使用MediaScannerConnection类进行全盘扫描,通过绑定 MediaScannerService 进行Scan操作,MediaScannerConnection会调用scanFile方法通过 connection.connect();来进行与MediaScannerService 的绑定操作

    233    public static void scanFile(Context context, String[] paths, String[] mimeTypes,
    234            OnScanCompletedListener callback) {
    235        ClientProxy client = new ClientProxy(paths, mimeTypes, callback);
    236        MediaScannerConnection connection = new MediaScannerConnection(context, client);
    237        client.mConnection = connection;
    238        connection.connect();
    239    }
    240
        
    112    public void connect() {
    113        synchronized (this) {
    114            if (!mConnected) {
    115                Intent intent = new Intent(IMediaScannerService.class.getName());
    116                intent.setComponent(
    117                        new ComponentName("com.android.providers.media",
    118                                "com.android.providers.media.MediaScannerService"));
    119                mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
    120                mConnected = true;
    121            }
    122        }
    123    }
    

    绑定MediaScannerService 之后也会调用它的 scanFile方法,之后在调用MediaScanner进行扫描操作

    图片在文件管理中删除之后MediaStore不更新问题?

    此问题是我再实际开发中碰到的问题,文件管理开发工程师在删除相应图片之后未通过上述手段及时通知相册或未触发重新扫描操作,导致图片确实已经删除了,但是我的相册监听的是MediaStore数据库并没有更新。

    后面文件管理工程师在删除图片之后,采用了发送广播的形式来触发MediaStore重新扫描,理论上是可以实现刷新MediaStore数据库的,但是事实上没有奏效,经过排查发现,广播和形式或者MediaScannerService 的形式都无法触发MediaStore数据库的重新扫描,因为源码中如果文件已经被删除了,那么MediaScanner就return了

    在这里插入图片描述

    所以我们只能采用contentResolver操作MediaStore数据库的方式来删除数据

                    getApplication<Application>().contentResolver.delete(
                        image.contentUri,
                        "${MediaStore.Images.Media._ID} = ?",
                        arrayOf(image.id.toString())
                    )
    
    展开全文
  • 该文章是为了检索手机上sd卡中的视频,然后将检索出来的相应视频的缩略图,名称等视频信息显示在ListView上。点击每个item后播放相应的视频。
  • MediaStore

    2019-10-03 13:12:38
    Class Overview  提供的多媒体数据包括内部和扩展的所有... MediaStore.Audio:此类包含了所有音频相关信息。  MediaStore.Files:提供的是多媒体信息的一个列表,包含非媒体文件,如txt,PDF,HTML,etc。  ...

    Class Overview

            提供的多媒体数据包括内部和扩展的所有多媒体元数据。

    Summary

          Nested Classes

            MediaStore.Audio:此类包含了所有音频相关信息。

            MediaStore.Files:提供的是多媒体信息的一个列表,包含非媒体文件,如txt,PDF,HTML,etc。

            MediaStore.Images:提供所有图片的相关信息。

            MediaStore.MediaColumns:多媒体的字段索引。(不是很清楚)

            MediaStore.Video:提供所有视频的相关信息。

          Constants

            ACTION_IMAGE_CAPTURE:标准的调用摄像头,来获取抓拍图片。

            ACTION_IMAGE_CAPTURE_SECURE:用于获得面部解锁时调用。

            ACTION_VIDEO_CAPTURE:标准的调用摄像头,来获取视频。

            AUTHORITY:获得官方的标准名称。

            EXTRA_DURATION_LIMIT:视频录制时,用来指定最大录制时间,以秒为单位。

            EXTRA_FINISH_ON_COMPLETION:对应了一个boolean值,用来表示当视频播放完成后,是否退出视频播放界面。

            EXTRA_FULL_SCREEN:对应了一个boolean值,用来表示图片查看器是否全屏显示。

            EXTRA_MEDIA_ALBUM:用于定义专辑的名字。

            EXTRA_MEDIA_ARTIST:用于定义艺术家的名字。

            EXTRA_MEDIA_FOCUS:设置搜索的关键字,指示搜索是否应该涉及到艺术家,专辑或歌曲所识别的其他额外的东西。

            EXTRA_MEDIA_TITLE:定义歌曲的名名字。

            EXTRA_OUTPUT:用来定义一个指定的路径,用来保存image或是video。

            EXTRA_SCREEN_ORIENTATION:用于设置观看图片和视频屏幕的方向。

            EXTRA_SHOW_ACTION_ICONS:对应了一个boolean值,用来控制imageview是否显示icon。

            EXTRA_SIZE_LIMIT:设置最大大小。

            EXTRA_VIDEO_QUALITY:改变录制视频的品质,0为低品质,1为高品质。

            INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH:通过给定的搜索关键字,来进行搜索,并自动播放。可用语音识别搜索。

            INTENT_ACTION_MEDIA_SEARCH:多媒体搜索,通过query,或是多媒体的其他关键字。

            INTENT_ACTION_MUSIC_PLAYER:启动音乐播放器。

            INTENT_ACTION_STILL_IMAGE_CAMERA:照相后保留在照相机页面。

                          INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE:同上,搜索后保留在照相机页面。

            INTENT_ACTION_TEXT_OPEN_FROM_SEARCH:通过搜索的关键字打开以文件。

            INTENT_ACTION_VIDEO_CAMERA:以摄像机的方式启动camera。

            INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH:通过搜索获得视频并自动播放。

            MEDIA_IGNORE_FILENAME:忽略当前目录及其子目录。

            MEDIA_SCANNER_VOLUME:扫描媒体库的地址。

          Public Methods

            getMediaScannerUri():返回正在扫描的uri地址。

            getVersion(Context context):获得media提供者的当前版本。

    转载于:https://www.cnblogs.com/qinghuaideren/archive/2013/04/17/3025918.html

    展开全文
  • Android中MediaStore的介绍

    千次阅读 2021-12-22 15:02:26
    MediaStore是android系统提供的一个多媒体数据库,专门用于存放多媒体信息的,通过ContentResolver即可对数据库进行操作。 MediaStore.Files: 共享的文件,包括多媒体和非多媒体信息; MediaStore.Audio: 存放音频...

    (1)简介

    MediaStore是android系统提供的一个多媒体数据库,专门用于存放多媒体信息的,通过ContentResolver即可对数据库进行操作。

    • MediaStore.Files: 共享的文件,包括多媒体和非多媒体信息;
    • MediaStore.Audio: 存放音频信息;
    • MediaStore.Image: 存放图片信息;
    • MediaStore.Vedio: 存放视频信息;

    每个内部类中都又包含了Media,Thumbnails和相应的MediaColumns,分别提供了媒体信息,缩略信息和操作字段。

    具体使用可以查看MediaStore Demo

    (2)使用

    都是通过 ContentResolver 和 Cursor 来操作的。

    (A)MediaStore.Files

    //Uri uri1 = MediaStore.Files.getContentUri("external");
    //Uri uri2 = Uri.parse("content://media/external/files");
    
    //获取所有文件
    public static List<FileEntity> getFilesByType(Context context) {
            List<FileEntity> files = new ArrayList<>();
            // 扫描files文件库
            Cursor c = null;
            try {
                mContentResolver = context.getContentResolver();
                c = mContentResolver.query(MediaStore.Files.getContentUri("external"), null, null, null, null);
                
                int columnIndexOrThrow_ID = c.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID);
                int columnIndexOrThrow_MIME_TYPE = c.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MIME_TYPE);
                int columnIndexOrThrow_DATA = c.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA);
                int columnIndexOrThrow_SIZE = c.getColumnIndexOrThrow(MediaStore.Files.FileColumns.SIZE);
                int columnIndexOrThrow_DATE_MODIFIED = c.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATE_MODIFIED); 
     
                //...
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (c != null) {
                    c.close();
                }
            }
            return files;
        }
    
    //获取指定字段
    String[] columns = new String[]{MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.MIME_TYPE, MediaStore.Files.FileColumns
                    .SIZE, MediaStore.Files.FileColumns.DATE_MODIFIED, MediaStore.Files.FileColumns.DATA};
    c = mContentResolver.query(MediaStore.Files.getContentUri("external"), columns, null, null, null);
    

    (B)MediaStore.Audio

    //Uri uri1 = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    //Uri uri2 = MediaStore.Audio.Media.getContentUri("external");
    //Uri uri3 = Uri.parse("content://media/external/audio/media");
    
    //查询音频文件
    c = mContentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
    

    (C)MediaStore.Image

    //Uri uri1 = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    //Uri uri2 = MediaStore.Images.Media.getContentUri("external");
    //Uri uri3 = Uri.parse("content://media/external/images/media");
    
    //查询图片文件
    c = mContentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
    

    (D)MediaStore.Vedio

    //Uri uri1 = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
    //Uri uri2 = MediaStore.Video.Media.getContentUri("external");
    //Uri uri3 = Uri.parse("content://media/external/video/media");
    
    //查询视频文件
        public static List<FileEntity> getFilesByVideo(Context context) {
            List<FileEntity> files = new ArrayList<>();
            // 扫描files文件库
            Cursor c = null;
            try {
                mContentResolver = context.getContentResolver();
                c = mContentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
                
                int columnIndexOrThrow_ID = c.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
                int columnIndexOrThrow_MIME_TYPE = c.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE);
                int columnIndexOrThrow_DATA = c.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
                int columnIndexOrThrow_SIZE = c.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);
                int columnIndexOrThrow_DATE_MODIFIED = c.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_MODIFIED); 
     
                //...
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (c != null) {
                    c.close();
                }
            }
            return files;
        }
    

    (E)MediaStore.Downloads

    //Uri uri1 = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
    //Uri uri2 = MediaStore.Downloads.getContentUri("external");
    
    c = mResolver.query(MediaStore.Downloads.getContentUri("external"), null, null, null, null);
    

    (3)部分注意事项

    (A)query()参数解析

    public final Cursor query(
    	Uri uri,                //数据资源路径
    	String[] projection,    //查询的列
    	String selection,       //查询的条件
    	String[] selectionArgs, //条件填充值
    	String sortOrder){}     //排序依据
    )
    

    (B)数据库字段

    MediaStore 提供了所有数据库中的字段宏定义:

    INTERNAL_CONTENT_URI; //内部库URI
    EXTERNAL_CONTENT_URI;//外部库URI
    CONTENT_TYPE;//内容提供者类型
    DEFAULT_SORT_ORDER;//排序方式
    

    其中MediaStore.Files没有EXTERNAL_CONTENT_URI,所以只能用getContentUri()自行获取,得出的URI其实是:

    Uri.parse("content://media/external/files");
    

    这个不难理解,以MediaStore.Images.Media为例,其URI有三种写法:

    Uri uri1 = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    Uri uri2 = MediaStore.Images.Media.getContentUri("external");
    Uri uri3 = Uri.parse("content://media/external/images/media");
    
    展开全文
  • Android教程之MediaStore

    2021-06-03 10:20:37
    MediaStore这个类是android系统提供的一个多媒体数据库,android中多媒体信息都可以从这里提取。这个MediaStore包括了多媒体数据库的所有信息,包括音频,视频和图像,android把所有的多媒体数据库接口进行了封装,...
  • String [] photoColumns=new String[]{ MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA, MediaStore.Images.Media.TITLE, MediaStore.Images.Media.MIME_TYPE, MediaStore.Images.Media.SIZE, ...
  • MediaStore.zip

    2020-10-28 15:08:07
    MediaStore 自定义相册可以进行读取手机所有图片,视频,音频等文件并展示出来内有动态权限防止权限被拒绝,可适配Android R
  • MediaStore.saveBitmap(activity,ConvertUtils.view2Bitmap(view"需要保存的图片")); 保存drawable资源图片到相册 Bitmap bitmap=BitmapFactory.decodeResource(resources,R.drawable.t1) MediaStore.saveBitmap...
  • 最为节省时间的做法是通过一个ContentProvider:MediaStore进行查询 一、什么是MediaStore 1、概述 MediaStore这个类是android系统提供的一个多媒体数据库,android中多媒体信息都可以从这里提取。 这个数据库中包括...
  • 一、MediaStore简介MediaStore是android系统提供的一个多媒体数据库,专门用于存放多媒体信息的,通过ContentResolver即可对数据库进行操作。MediaStore.Files: 共享的文件,包括多媒体和非多媒体信息MediaStore....
  • android 直接访问相册图片_MediaStore

    千次阅读 2022-03-08 01:58:06
    直接访问相册一张或多张图片_MediaStore_存储访问框架SAF
  • android 文件扫描MediaStore

    千次阅读 2020-09-28 18:51:58
    + " or " + MediaStore.Files.FileColumns.DATA + " LIKE '%.apk'" + " or " + MediaStore.Files.FileColumns.DATA + " LIKE '%.xlsx'" + " or " + MediaStore.Files.FileColumns.DATA + " LIKE '%.zip'" + " or " +...
  • I encountered strange problem, when calling MediaStore.Images.Media.insertImage, it returns null uri sometimes, but I found it can work well one or two times, I can't find it's rule.Please give help, ...
  • //获取专辑的歌手名 MediaStore.Audio.Media.ARTIST //获取歌曲的时长 MediaStore.Audio.Media.DURATION //获取歌曲的大小 MediaStore.Audio.Media.SIZE //获取专辑名 MediaStore.Audio.Media.ALBUM //获取歌曲路径...
  • Android MediaStore的使用

    千次阅读 2021-01-21 16:33:03
    这个MediaStore包括了多媒体数据库的所有信息,包括音频,视频和图像,android把所有的多媒体数据库接口进行了封装,所有的数据库不用自己进行创建,直接调用利用ContentResolver去掉用那些封装好的接口就可以进行...
  • Android通过MediaStore获取缩略图模糊

    千次阅读 2021-09-27 17:11:20
    android中mediastore中MICRO_KIND和MINI_KIND的区别? 问题描述 文件管理器中图片和视频的缩略图很模糊,实际打开图片或视频文件很清晰 问题分析 获取缩略图的方法 Bitmap thumbnail = Images.Thumbnails.get...
  • 所以,采用 MediaStore android手机,系统级别带有一个数据库,保存所有手机上的信息,就是MediaStore,称之为多媒体数据库(ps:先关技术,可自行学习) MediaStore获取文件信息,是通过文件的mime-type来获取的。...
  • Android之MediaStore使用的点点滴滴

    千次阅读 2019-06-15 08:04:15
    在日常开发中,我们经常会使用MediaStore来获取手机的音频、图片、视频等相关信息。下面3个是常见的内部类: MediaStore.Audio 获取音频信息的类 MediaStore.Images 获取图片信息 MediaStore.Video 获取视频信息 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,171
精华内容 10,468
关键字:

mediastore

友情链接: XML.zip