Android 获取本地音乐

获取到Android设备的本地音乐,并显示音乐的时长,专辑图片,音乐名字以及歌手姓名等。当设备从播放器中下载音乐的时候,这些信息都会存储到设备中。我们获取的时候可以通过设备暴露给我们的ContentProvider接口去查询这些信息。ok,话不多说,上代码。
首先我们要定义一个名字叫Song的bean文件,用来保存歌曲的信息。

public class Song {
    public String name;//歌曲名
    public String singer;//歌手
    public long size;//歌曲所占空间大小
    public int duration;//歌曲时间长度
    public String path;//歌曲地址
    public long  albumId;//图片id
    public long id;//歌曲id

    public long getAlbumId()
    {
        return albumId;
    }

    public void setAlbumId(long albumId)
    {
        this.albumId = albumId;
    }

    public long getId()
    {
        return id;
    }

    public void setId(long id)
    {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSinger() {
        return singer;
    }

    public void setSinger(String singer) {
        this.singer = singer;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

代码中的解释很详细了。
接下来我们要创建一个LocalMusicUtils来获取我们设备本地的音乐。首先通过getContentResolver()获取到contentPervider的cursor对象。

Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
            , null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);

然后遍历cursor中的数据

if (cursor != null) {
        while (cursor.moveToNext()) {
            song = new Song();
            name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
            id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
            singer = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
            path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
            duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
            size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
            albumId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
        }
   }

ok,来看一下完整的代码

public class LocalMusicUtils {
//定义一个集合,存放从本地读取到的内容
    public static List<Song> list;

    public static Song song;
    private static String name;
    private static String singer;
    private static String path;
    private static int duration;
    private static long size;
    private static long albumId;
    private static long id;
    //获取专辑封面的Uri
    private static final Uri albumArtUri = Uri.parse("content://media/external/audio/albumart");

    public static List<Song> getmusic(Context context) {

         list = new ArrayList<>();


         Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
            , null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);

         if (cursor != null) {
              while (cursor.moveToNext()) {
              song = new Song();
              name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
              id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
              singer = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
              path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
              duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
              size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
              albumId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
              //list.add(song);
              //把歌曲名字和歌手切割开
              //song.setName(name);
              song.setSinger(singer);
              song.setPath(path);
              song.setDuration(duration);
              song.setSize(size);
              song.setId(id);
              song.setAlbumId(albumId);
              if (size > 1000 * 800) {
                  if (name.contains("-")) {
                      String[] str = name.split("-");
                      singer = str[0];
                      song.setSinger(singer);
                      name = str[1];
                      song.setName(name);
                  } else {
                      song.setName(name);
                  }
                  list.add(song);
              }
          }
      }
      cursor.close();
      return list;
  }

  //    转换歌曲时间的格式
  public static String formatTime(int time) {
      if (time / 1000 % 60 < 10) {
          String tt = time / 1000 / 60 + ":0" + time / 1000 % 60;
          return tt;
      } else {
          String tt = time / 1000 / 60 + ":" + time / 1000 % 60;
          return tt;
      }
  }

/**
 * 获取专辑封面位图对象
 * @param context
 * @param song_id
 * @param album_id
 * @param allowdefalut
 * @return
 */
  public static Bitmap getArtwork(Context context, long song_id, long album_id, boolean allowdefalut, boolean small){
      if(album_id < 0) {
          if(song_id < 0) {
              Bitmap bm = getArtworkFromFile(context, song_id, -1);
              if(bm != null) {
                  return bm;
              }
          }
          if(allowdefalut) {
              return getDefaultArtwork(context, small);
          }
          return null;
      }
      ContentResolver res = context.getContentResolver();
      Uri uri = ContentUris.withAppendedId(albumArtUri, album_id);
      if(uri != null) {
          InputStream in = null;
          try {
              in = res.openInputStream(uri);
              BitmapFactory.Options options = new BitmapFactory.Options();
              //先制定原始大小
              options.inSampleSize = 1;
              //只进行大小判断
              options.inJustDecodeBounds = true;
              //调用此方法得到options得到图片的大小
              BitmapFactory.decodeStream(in, null, options);
              /** 我们的目标是在你N pixel的画面上显示。 所以需要调用computeSampleSize得到图片缩放的比例 **/
              /** 这里的target为800是根据默认专辑图片大小决定的,800只是测试数字但是试验后发现完美的结合 **/
              if(small){
                  options.inSampleSize = computeSampleSize(options, 40);
              } else{
                  options.inSampleSize = computeSampleSize(options, 600);
              }
              // 我们得到了缩放比例,现在开始正式读入Bitmap数据
              options.inJustDecodeBounds = false;
              options.inDither = false;
              options.inPreferredConfig = Bitmap.Config.ARGB_8888;
              in = res.openInputStream(uri);
              return BitmapFactory.decodeStream(in, null, options);
          } catch (FileNotFoundException e) {
              Bitmap bm = getArtworkFromFile(context, song_id, album_id);
              if(bm != null) {
                  if(bm.getConfig() == null) {
                      bm = bm.copy(Bitmap.Config.RGB_565, false);
                      if(bm == null && allowdefalut) {
                          return getDefaultArtwork(context, small);
                      }
                  }
              } else if(allowdefalut) {
                  bm = getDefaultArtwork(context, small);
              }
              return bm;
          } finally {
              try {
                  if(in != null) {
                      in.close();
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      return null;
  }

/**
 * 从文件当中获取专辑封面位图
 * @param context
 * @param songid
 * @param albumid
 * @return
 */
  private static Bitmap getArtworkFromFile(Context context, long songid, long albumid){
      Bitmap bm = null;
      if(albumid < 0 && songid < 0) {
          throw new IllegalArgumentException("Must specify an album or a song id");
      }
      try {
          BitmapFactory.Options options = new BitmapFactory.Options();
          FileDescriptor fd = null;
          if(albumid < 0){
              Uri uri = Uri.parse("content://media/external/audio/media/"
                    + songid + "/albumart");
              ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
              if(pfd != null) {
                  fd = pfd.getFileDescriptor();
              }
          } else {
              Uri uri = ContentUris.withAppendedId(albumArtUri, albumid);
              ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
              if(pfd != null) {
                  fd = pfd.getFileDescriptor();
              }
          }
          options.inSampleSize = 1;
          // 只进行大小判断
          options.inJustDecodeBounds = true;
          // 调用此方法得到options得到图片大小
          BitmapFactory.decodeFileDescriptor(fd, null, options);
          // 我们的目标是在800pixel的画面上显示
          // 所以需要调用computeSampleSize得到图片缩放的比例
          options.inSampleSize = 100;
          // 我们得到了缩放的比例,现在开始正式读入Bitmap数据
          options.inJustDecodeBounds = false;
          options.inDither = false;
          options.inPreferredConfig = Bitmap.Config.ARGB_8888;

          //根据options参数,减少所需要的内存
          bm = BitmapFactory.decodeFileDescriptor(fd, null, options);
      } catch (FileNotFoundException e) {
          e.printStackTrace();
      }
      return bm;
  }

/**
 * 获取默认专辑图片
 * @param context
 * @return
 */
  public static Bitmap getDefaultArtwork(Context context,boolean small) {
      BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inPreferredConfig = Bitmap.Config.RGB_565;
      if(small){    //返回小图片
          //return
          BitmapFactory.decodeStream(context.getResources().openRawResource(R.drawable.music5), null, opts);
    }
    //return BitmapFactory.decodeStream(context.getResources().openRawResource(R.drawable.defaultalbum), null, opts);
      return null;
  }

/**
 * 对图片进行合适的缩放
 * @param options
 * @param target
 * @return
 */
  public static int computeSampleSize(BitmapFactory.Options options, int target) {
      int w = options.outWidth;
      int h = options.outHeight;
      int candidateW = w / target;
      int candidateH = h / target;
      int candidate = Math.max(candidateW, candidateH);
      if(candidate == 0) {
          return 1;
      }
      if(candidate > 1) {
          if((w > target) && (w / candidate) < target) {
              candidate -= 1;
          }
      }
      if(candidate > 1) {
          if((h > target) && (h / candidate) < target) {
              candidate -= 1;
          }
      }
      return candidate;
  }

/**
 * 根据专辑ID获取专辑封面图
 * @param album_id 专辑ID
 * @return
 */
  public static String getAlbumArt(Context context,long album_id) {
      String mUriAlbums = "content://media/external/audio/albums";
      String[] projection = new String[]{"album_art"};
      Cursor cur = context.getContentResolver().query(Uri.parse(mUriAlbums + "/" + Long.toString(album_id)), projection, null, null, null);
      String album_art = null;
      if (cur.getCount() > 0 && cur.getColumnCount() > 0) {
          cur.moveToNext();
          album_art = cur.getString(0);
     }
      cur.close();
      String path = null;
      if (album_art != null) {
          path = album_art;
      } else {
          //path = "drawable/music_no_icon.png";
          //bm = BitmapFactory.decodeResource(getResources(), R.drawable.default_cover);
      }
      return path;
  }
 }

ok,这样就把歌曲的信息通过list的方式获取到了,下面的方法是获取专辑图片的fang'f

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,357评论 0 17
  • 本人初学Android,最近做了一个实现安卓简单音乐播放功能的播放器,收获不少,于是便记录下来自己的思路与知识总结...
    落日柳风阅读 19,078评论 2 41
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,442评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,691评论 2 59
  • 文 | 柒筱胭 去年,远方闺蜜的的宝贝出生了,身为好朋友的我想,送给小宝贝什么样的礼物才有意义呢?后来在万能的淘宝...
    柒筱胭阅读 6,856评论 4 7