sunplusedu的个人空间 https://blog.eetop.cn/sunplusedu [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

【凌阳教育学堂】Android开发获得多媒体信息

已有 911 次阅读| 2011-12-28 19:37 |个人分类:嵌入式培训

来源: 凌阳教育嵌入式培训
  凌阳教育是全国唯一 “学员就业双100%品牌”,保证“学员100%就业”,保证“学员100%满意就业”。凌阳教育也是全国唯一“按班公布学员就业去向诚信机构”,每个班 所有学员来自哪个学校就业后签约哪家企业都真实发布。截止2011年9月,凌阳教育学员已连续27期“双100%就业”。凌阳教育是全国唯一“原厂嵌入式 培训机构”,以凌阳科技产业链企业的人才需求为契机,先后与2500多家企业建立学员就业合作关系。

  通过调用Android的API,可以实现相册,播放器,录音和摄像等功能。这一章需要掌握如下功能:
  多媒体的ContentProvider的调用
  Camera
  AudioRecord和AudioTrack
  MediaPlayer

  1.1  获取多媒体信息
  多媒体信息?在pc中的音乐播放器总是很容易的显示歌手名、歌曲名、专辑名、年代。在Android中应该如何获取这些信息呢?

  1.1.1  查看多媒体ContentProvider
  前面我们学习了ContentProvider来保存和检索数据,Android为常用的数据类型(如:音视频、图片和联系方式等)提供了大量的 ContentProvider,它们被定义在android.provider包下。那么我们如何获取多媒体的ContentProvider呢。

  (1)在Eclipse中添加Android自带的FileExplorer视图:
  菜单栏->window->show view->other->Android->FileExplorer
  (2)开启模拟器,在FileExplorer中查看data/data/com.android.providers.media/databases/

嵌入式培训

  (3)将external.db文件 pull到pc上,用sqlite工具(可以使用火狐插件SQliteManager)查看:

嵌入式培训 

  (4)查看表结构:
  audio_meta.:管理sd卡中的音频资源。
  video:管理sd卡中的视频资源。

嵌入式培训 

  images:管理sd卡中的图片。

  可能大家看到这里会不明白为什么讲多媒体先要介绍这些。笔者这里给大家列举一个音乐播放器的需求:
  1)      获得音乐文件列表及路径
  2)      获得音乐文件属性(歌曲名、歌手名、专辑、年代。。)
  3)      手动删除内存卡中音乐文件,如何能同步更新文件列表

  如果是没有Android经验,大家可能会这样分析:
  文件路径嘛,我调用file.listFile()就可以得到音乐文件列表。如果内存卡里有很多文件,那么这个将会特别的耗时,如果让用户等上10秒去扫描存储卡,用户很有可能将你的应用卸载掉。
  音乐文件属性一般保存在音乐文件中,有的放在文件头,有的放在文件尾,必须读出该文件相关字节中的内容才可以获取音乐文件信息。OK,有个开源的项目,可以解析MP3文件中的文件信息。但是它同样也是耗时的操作。而且学会调用这个开源项目还需要一周的时间。
  在文件管理器中手动删除或添加一个音乐文件,这个时候如何把它更新到音乐列表中呢,当你选择一首歌播放的时候,很有可能已经被删掉了。总不能让它时刻去调用file.listFile()去维护吧?

  那么我们到底应该怎么做呢?你要始终相信Android是强大的,它早已为我们提供了这些功能,我们只需要调用Android提供的API,就可以解决上述的需求。
  现在我们先看个图,图1.6为模拟器开机时,在log中打印的日志。
  开机时的log

嵌入式培训 

  大家会看到,系统会调用MediaScanner去扫描Internal和External Volume。原来,在开机时,系统会在后台扫描内存和外存设备,将多媒体数据更新到数据库中。同时也会扫描文件信息,这样,我们不费吹灰之力就解决了问题。
  小插曲:之前由于笔者还不知道这个方法,在摸索中让同事去研究解析MP3文件信息,花了他一个星期时间,当他做出来了,我花了十分钟找到了这个方法。真是罪过罪过。

  那么我们如何得到多媒体数据呢,请看下面的例子:

  /**
        * 读取sd卡中的音乐文件
        * @return
        * @throws Exception
        */
       public static ArrayList readDataFromSD(Context context,int component){
  //       Log.i(TAG, "scanFile");
           Cursor cursor = context.getContentResolver().query(
                     MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                     new String[] { MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DURATION, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM, MediaStore.Audio.Media.YEAR, MediaStore.Audio.Media.MIME_TYPE, MediaStore.Audio.Media.SIZE, MediaStore.Audio.Media.DATA}, MediaStore.Audio.Media.MIME_TYPE+"=? or " + MediaStore.Audio.Media.MIME_TYPE+"=?", new String[]{"audio/mpeg","audio/x-ms-wma"},null);
           ArrayList songs = null;
           if (cursor.moveToFirst()) {
                songs = SongInfoUtil.getList(cursor, context, component);
           }
           return songs;
       }

  /**
   * @author stayzhang 封装信息至Song
   */
  public class SongInfoUtil {
  //   private static final String TAG = "ListUtils";
       public static ArrayList getList(Cursor cursor, Context mContext, int component) {
           Song song = null;
           do {
  //            Log.i(TAG, "getList");
                song = new Song();
                song.setFilename(cursor.getString(1));//文件名
                song.setTitle(cursor.getString(2));//歌曲名
                song.setDuration(cursor.getInt(3));//时长
                song.setSinger(cursor.getString(4));//歌手名
                song.setAlbum(cursor.getString(5));//专辑名
                if (cursor.getString(6) != null) {//年代
                     song.setYear(cursor.getString(6));
                } else {
                     song.setYear("未知");
                }
                if ("audio/mpeg".equals(cursor.getString(7).trim())) {//歌曲格式
                     song.setType("mp3");
                } else if ("audio/x-ms-wma".equals(cursor.getString(7).trim())) {
                     song.setType("wma");
                }
                if (cursor.getString(8) != null) {//文件大小
                     float temp = cursor.getInt(8) / 1024f / 1024f;
                     String sizeStr = (temp + "").substring(0, 4);
                     song.setSize(sizeStr + "M");
                } else {
                     song.setSize("未知");
                }
                if (cursor.getString(9) != null) {//文件路径
                     song.setFileUrl(cursor.getString(9));
                }
           } while (cursor.moveToNext());
           cursor.close();
           return dbService.query(component, null, null);
       }
  }
  同理,图片还有视频文件也可以这样获得,不再赘述。
  这样第一个和第二个需求我们已经解决,那第三个需求呢。
  当我们手动的删除或添加多媒体文件到存储卡中时,Android会自动扫描这些文件并将其更新到数据库吗?
  答案是不会,那么我们如何将数据实时更新到数据库中呢。还记得logcat中打印出来的MediaScanner吗?我们也可以调用 MediaScanner这个类去扫描存储卡。但是不能直接调用这个类,只能以广播的形式通知系统,让系统去扫描存储卡指定的URI,扫描完后,再通过 ContentProvider查询数据库。
  方法如下:

  /**
            * 调用系统api扫描sd卡
            */
           private void scanSdCard() {
                     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://" + getExternalStorageDirectory().getAbsolutePath)));
           }
   
           /**
            * @author stayzhang 注册扫描开始/完成的广播
            */
           private class ScanSdFilesReceiver extends BroadcastReceiver {
                     public void onReceive(Context context, Intent intent) {
                              String action = intent.getAction();
                              if (Intent.ACTION_MEDIA_SCANNER_STARTED.equals(action)) {
  //当系统开始扫描sd卡时,为了用户体验,可以加上一个等待框
                                       scanHandler.sendEmptyMessage(STARTED);
                              }
                              if (Intent.ACTION_MEDIA_SCANNER_FINISHED.equals(action)) {
                              //当系统扫描完毕时,停止显示等待框,并重新查询ContentProvider
                                       scanHandler.sendEmptyMessage(FINISHED);
                              }
                     }
           }

  凌阳教育“学员就业 双100%”的诚信获得了社会的广泛认可,2008年、2009年、2010年,凌阳教育连续三年荣膺新浪“中国十大品牌IT教育机构”、新浪“最具就业 竞争力IT教育机构”、搜狐“中国十大品牌IT培训机构”、网易“中国十大IT教育品牌”荣誉称号。凌阳教育是嵌入式培训领域,唯一全部获得三大门户网站 “十大IT品牌”表彰的机构。

嵌入式培训

凌阳教育嵌入式培训,值得信赖的嵌入式教育品牌!
http://www.sunplusedu.com/content3553.shtml

点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 1

    粉丝
  • 0

    好友
  • 0

    获赞
  • 2

    评论
  • 1928

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-6-5 19:04 , Processed in 0.018342 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部