android操作sdcard中的多媒体文件(一)——音乐列表的制作

原文地址

最近做了一个android音乐播放器,个人感觉最难的就是“后台播放”以及有关“播放列表”的部分,但是总算是找到了实现的方式。不同的人实现的方式可能不一样,这里我就分享一下自己对“播放列表”这个模块的一些实现方法,“后台播放”会在下一篇博文中进行介绍,希望大家也能分享一下自己的一些思路。

android使用ContentProvider来支持不同应用程序的数据共享,为了方便其他应用程序对sdcard中的数据进行操作,sdcard也提供了ContentProvider接口,这里就以访问音频文件为例,视频以及图片的操作也类似,这里就不在赘述。

  访问sdcard中的音频文件的URI为MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,为了使播放列表显示所以音乐文件的信息,这里需要查询sdcard里的音频文件,并把查询到的信息保存在Cursor中,具体代码如下:  

<pre>Cursor c = this.getContentResolver().</pre>
<pre>query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,</pre>
/*这个字符串数组表示要查询的列*/
new String[]{MediaStore.Video.Media.TITLE, //音乐名
MediaStore.Audio.Media.DURATION, //音乐的总时间
MediaStore.Audio.Media.ARTIST, //艺术家
MediaStore.Audio.Media._ID, //id号
MediaStore.Audio.Media.DISPLAY_NAME, //音乐文件名
MediaStore.Audio.Media.DATA         //音乐文件的路径
},
null,                      //查询条件,相当于sql中的where语句
null,                       //查询条件中使用到的数据
null);                     //查询结果的排序方式
  1.   通过MediaStore.Audio.Media.XXX来访问音乐文件的一些信息,这里只列出了一部分,可以根据需要进行增添和删除。
  1. 至此,Cursor c就已经保存了sdcard内所以音频文件的信息,下面的操作就是围绕这个Cursor展开的。
  1. 首先定义三个数组:
private int[] _ids;    //存放音乐文件的id数组
private String[] _titles; //存放音乐文件的标题数组
private String[] _path; //存放音乐文件的路径
  1. _ids保存了所有音乐文件的_ID,用来确定到底要播放哪一首歌曲,_titles存放音乐名,用来显示在播放界面,而_path
  1. 放音乐文件的路径(删除文件时会用到)。
  1.   接下来再定义一个变量,用来定位选择的是哪一首音乐:
  1. private int pos;
  1.   接下来将音乐文件的信息存放在相应的数组中:  
c.moveToFirst();
_ids = new int[c.getCount()];
_titles = new String[c.getCount()];
_path = new String[c.getCount()];
for(int i=0;i<c.getCount();i++){
_ids[i] = c.getInt(3);          
_titles[i] = c.getString(0);
_path[i] = c.getString(5).substring(4);
c.moveToNext();
}        
  1. 有人可能会问为什么获取路径的格式是_path[i]=c.geString(5).substring(4)?因为MediaStore.Audio.Media.DATA
  1. 得到的内容格式为/mnt/sdcard/[子文件夹名/]音乐文件名,而我们想要得到的是/sdcard/[子文件夹名]音乐文件名,
  1. 所以要做相应的裁剪操作。
  1.   接下来把Cursor中的信息显示到listview中:
MusicListAdapter adapter = new MusicListAdapter(this, c);
listview.setAdapter(adapter);
  1. MusicListAdapter是一个自定义的Adapter,继承自BaseAdapter,这里只贴出代码,不做讲解。
package com.alex.video;
 
import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
 
public class MusicListAdapter extends BaseAdapter{
private Context myCon;
private Cursor myCur;
private int pos=-1;
 
public MusicListAdapter(Context con,Cursor cur){
this.myCon = con;
this.myCur = cur;
}
 
@Override
public int getCount() {
 
return this.myCur.getCount();
}
 
@Override
public Object getItem(int position) {
 
return position;
}
 
@Override
public long getItemId(int position) {
 
return position;
}
 
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(myCon).inflate(R.layout.musiclist,
null);
myCur.moveToPosition(position);
TextView videoTitle = (TextView)convertView.findViewById(R.id.musictitle);
if (myCur.getString(0).length()>24){
try {
String musicTitle = bSubstring(myCur.getString(0).trim(),24);
videoTitle.setText(musicTitle);
} catch (Exception e) {
 
e.printStackTrace();
}
}else {
videoTitle.setText(myCur.getString(0).trim());
}
TextView videoArtist = (TextView)convertView.findViewById(R.id.musicartist);
if (myCur.getString(2).equals("<unknown>")){
videoArtist.setText("未知艺术家");
}else{
videoArtist.setText(myCur.getString(2));
}
TextView videoTime = (TextView)convertView.findViewById(R.id.musictime);
videoTime.setText(toTime(myCur.getInt(1)));
ImageView videoItem = (ImageView)convertView.findViewById(R.id.musicitem);
videoItem.setImageResource(R.drawable.item);
return convertView;
}
 
/*时间格式转换*/
public String toTime(int time) {
 
time /= 1000;
int minute = time / 60;
int hour = minute / 60;
int second = time % 60;
minute %= 60;
return String.format("%02d:%02d", minute, second);
}
 
/*字符串裁剪*/
public static String bSubstring(String s, int length) throws Exception
{
 
byte[] bytes = s.getBytes("Unicode");
int n = 0; // 表示当前的字节数
int i = 2; // 要截取的字节数,从第3个字节开始
for (; i < bytes.length && n < length; i++)
{
// 奇数位置,如3、5、7等,为UCS2编码中两个字节的第二个字节
if (i % 2 == 1)
{
n++; // 在UCS2第二个字节时n加1
}
else
{
// 当UCS2编码的第一个字节不等于0时,该UCS2字符为汉字,一个汉字算两个字节
if (bytes[i] != 0)
{
n++;
}
}
}
// 如果i为奇数时,处理成偶数
if (i % 2 == 1)
 
{
// 该UCS2字符是汉字时,去掉这个截一半的汉字
if (bytes[i - 1] != 0)
i = i - 1;
// 该UCS2字符是字母或数字,则保留该字符
else
i = i + 1;
}
 
return new String(bytes, 0, i, "Unicode");
}
}
  1.  
  1. 这样,音乐的信息就显示在了列表中了
  1.  
  1. 下一节将讲解更新列表的操作。

android操作sdcard中的多媒体文件(一)——音乐列表的制作的更多相关文章

  1. android操作sdcard中的多媒体文件(二)——音乐列表的更新

    android操作sdcard中的多媒体文件(二)——音乐列表的更新 原文地址 在上一篇随笔中,我介绍了如何在程序中查询sdcard内的多媒体文件,并且显示到播放列表中,但是,如果在sdcard内删除 ...

  2. Android 获取SDCard中某个目录下图片

    本文介绍Android开发中如何获取SDCard中某目录下的所有图片并显示出来,下面的我们提供的这个函数是通用的,只要提供路径就可以查询出该目录下所有图片的路径信息,并保存到一个List<Str ...

  3. Android 遍历sdcard中指定文件夹下的图片(jpg,jpeg,png)

    File scanner5Directory = new File(Environment.getExternalStorageDirectory().getPath() + "/scann ...

  4. android从sdcard中读取bitmap

    String sdcard_path=Environment.getExternalStorageDirectory().getCanonicalPath(); String file_path=sd ...

  5. 如何在Android的ListView中构建CheckBox和RadioButton列表(支持单选和多选的投票项目示例)

    引言 我们在android的APP开发中有时候会碰到提供一个选项列表供用户选择的需求,如在投票类型的项目中,我们提供一些主题给用户选择,每个主题有若干选项,用户对这些主题的选项进行选择,然后提交. 本 ...

  6. android操作sqlite数据库及心得

    写这篇文章主要是网上的对sqlite的操作太多且太杂,非常多时候都不能非常好的运用到自己的项目中,结构不清晰,我自己写了一篇适合刚刚接触的人看的操作方法. 近来用android时要将一些数据保存起来, ...

  7. 用Vue来实现音乐播放器(二十三):音乐列表

    当我们将音乐列表往上滑的时候   我们上面的歌手图片部分也会变小 当我们将音乐列表向下拉的时候   我们的图片会放大 当我们将音乐列表向上滑的时候   我们的图片有一个高斯模糊的效果 并且随着我们的列 ...

  8. Android 4.3实现类似iOS在音乐播放过程中如果有来电则音乐声音渐小铃声渐大的效果

    目前Android的实现是:有来电时,音乐声音直接停止,铃声直接直接使用设置的铃声音量进行铃声播放. Android 4.3实现类似iOS在音乐播放过程中如果有来电则音乐声音渐小铃声渐大的效果. 如果 ...

  9. Android学习笔记之数据的Sdcard存储方法及操作sdcard的工具类

    FileService.java也就是操作sdcard的工具类: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ...

随机推荐

  1. M2: XAML Controls

    本小节介绍如何在界面上添加简单的XAML Controls, 本例中我们用到了Grid, TextBlock, Button, 和StackPanel控件.XAML自身所有的控件都声明在Windows ...

  2. Magento在IE下登陆不了后台,在Firefox下正常

    目前的解决办法如下: 方法一,用FF登陆后台,在 System—Configuration-Web-Session Cookie management....timeout 改为:86400 方法二: ...

  3. 第一个sprint与第二个sprint 阶段总结

    总体来说: 1.团队合作情况: 整个队伍配合得还算是不错的了,有些队员比较积极与主动,这是比较好的现象,因为一个队伍最终要的是活力与团结,至少我是这样认为的,如果一个队伍每个人都不干活,我想后果是不堪 ...

  4. Flume NG 简介及配置实战

    Flume 作为 cloudera 开发的实时日志收集系统,受到了业界的认可与广泛应用.Flume 初始的发行版本目前被统称为 Flume OG(original generation),属于 clo ...

  5. spark+hcatalog操作hive表及其数据

    package iie.hadoop.hcatalog.spark; import iie.udps.common.hcatalog.SerHCatInputFormat; import iie.ud ...

  6. 创建交互式shell脚本对话框

    当你在终端环境下安装新的软件时,你可以经常看到信息对话框弹出,需要你的输入,比如:RHEL/CentOS自带的setup,对话框的类型有密码箱.检查表.菜单等等.他们可以引导你以一种直观的方式输入必要 ...

  7. leetcode 99 Recover Binary Search Tree ----- java

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  8. JavaWeb学习记录(十三)——商城购物之添加订单的数据库级联操作

    一.方法实现 private JdbcTemplate jdbcTemplate = new JdbcTemplate(DBConn.getDataSource()); @SuppressWarnin ...

  9. some knowledge of maven {maven实战}

    maven是跨平台的,不仅是一个构建工具,也是一个可以管理依赖的工具.它最大化的消除了构件的重复,并且提供了中央仓库,能帮我们自动下载构件.------------------------------ ...

  10. C++ code: 将程序的输出,保存到txt文档中,且每35个数,自动换行

    // write the predicted score into txt files       ofstream file("/home/wangxiao/Downloads/caffe ...