Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)

2013年7月3日简、美音乐播放器开发

第二阶段已增加功能:

1、歌词滚动显示

2、来电监听

3、音量控制

4、左右滑动切换歌词与专辑界面

今天要介绍的功能是获取音乐专辑封面并显示到界面上,小巫改变了音乐列表的布局,为了显示专辑封面。之前没有意识到SimpleAdapter已经不能满足自己的需求了,后来只能参考了别人的代码,修改了原来代码,最终实现获取专辑图片。题外话,最近都一直复习大学的考试,所以断断续续地实现功能,不过也快要学期末了,也没剩多少时间,科目考试也只剩下一科,所以接下来的一周,可能会加快开发速度。争取在小巫这个学期结束前,提供完整的应用原型。由于还不专业,肯定会有很bug存在,希望想参考本人的开发能见谅。

照惯例,我会先让朋友们先看一下效果图(现在是不是简、美很多):

首先介绍布局吧:

列表布局有稍微的改变,也没什么好说的,看代码吧

/SimpleBeautyMusicPlayer/res/layout/music_list_item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical" > <ImageView
android:id="@+id/albumImage"
android:layout_width="64.0dip"
android:layout_height="64.0dip"
android:layout_alignParentLeft="true"
android:layout_centerInParent="true"
android:src="@drawable/music" /> <TextView
android:id="@+id/music_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="5.0dp"
android:textColor="@android:color/white"
android:text="@string/time" />
<TextView
android:id="@+id/music_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="5dp"
android:layout_toRightOf="@+id/albumImage"
android:focusable="true"
android:text="@string/siger"
android:textColor="@android:color/white"
android:textSize="18sp"
/>
<TextView
android:id="@+id/music_Artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/music_title"
android:layout_marginTop="5.0dip"
android:layout_below="@id/music_title"
android:textColor="@android:color/white"
android:text="@string/artist" /> </RelativeLayout>

自定义ListView适配器

/SimpleBeautyMusicPlayer/src/com/wwj/sb/adapter/MusicListAdapter.java

package com.wwj.sb.adapter;

import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; import com.wwj.sb.activity.R;
import com.wwj.sb.domain.Mp3Info;
import com.wwj.sb.utils.MediaUtil; /**
* 自定义的音乐列表适配器
* 为了方便扩展,因为之前没有考虑到显示专辑封面
* @author wwj
*
*/
public class MusicListAdapter extends BaseAdapter{
private Context context; //上下文对象引用
private List<Mp3Info> mp3Infos; //存放Mp3Info引用的集合
private Mp3Info mp3Info; //Mp3Info对象引用
private int pos = -1; //列表位置 /**
* 构造函数
* @param context 上下文
* @param mp3Infos 集合对象
*/
public MusicListAdapter(Context context, List<Mp3Info> mp3Infos) {
this.context = context;
this.mp3Infos = mp3Infos;
} @Override
public int getCount() {
return mp3Infos.size();
} @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) {
ViewHolder viewHolder = null;
if(convertView == null)
{
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.music_list_item_layout, null);
viewHolder.albumImage = (ImageView) convertView.findViewById(R.id.albumImage);
viewHolder.musicTitle = (TextView) convertView.findViewById(R.id.music_title);
viewHolder.musicArtist = (TextView) convertView.findViewById(R.id.music_Artist);
viewHolder.musicDuration = (TextView) convertView.findViewById(R.id.music_duration);
convertView.setTag(viewHolder); //表示给View添加一个格外的数据,
} else {
viewHolder = (ViewHolder)convertView.getTag();//通过getTag的方法将数据取出来
}
mp3Info = mp3Infos.get(position);
if(position == pos) {
viewHolder.albumImage.setImageResource(R.drawable.item);
} else {
Bitmap bitmap = MediaUtil.getArtwork(context, mp3Info.getId(),mp3Info.getAlbumId(), true, true);
viewHolder.albumImage.setImageBitmap(bitmap);
}
viewHolder.musicTitle.setText(mp3Info.getTitle()); //显示标题
viewHolder.musicArtist.setText(mp3Info.getArtist()); //显示艺术家
viewHolder.musicDuration.setText(MediaUtil.formatTime(mp3Info.getDuration()));//显示时长 return convertView;
} /**
* 定义一个内部类
* 声明相应的控件引用
* @author wwj
*
*/
public class ViewHolder {
//所有控件对象引用
public ImageView albumImage; //专辑图片
public TextView musicTitle; //音乐标题
public TextView musicDuration; //音乐时长
public TextView musicArtist; //音乐艺术家
}
}

自定义适配器需要继承BaseAdapter类,主要是为了实现图片显示的显示,而不是单纯的字符串。

增加代码的MediaUtil类,主要包含获取专辑封面图片的方法,需要对图片做稍微的处理

/SimpleBeautyMusicPlayer/src/com/wwj/sb/utils/MediaUtil.java

package com.wwj.sb.utils;

import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore; import com.wwj.sb.activity.R;
import com.wwj.sb.domain.Mp3Info; public class MediaUtil { //获取专辑封面的Uri
private static final Uri albumArtUri = Uri.parse("content://media/external/audio/albumart"); /**
* 用于从数据库中查询歌曲的信息,保存在List当中
*
* @return
*/
public static List<Mp3Info> getMp3Infos(Context context) {
Cursor cursor = context.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
MediaStore.Audio.Media.DEFAULT_SORT_ORDER); List<Mp3Info> mp3Infos = new ArrayList<Mp3Info>();
for (int i = 0; i < cursor.getCount(); i++) {
cursor.moveToNext();
Mp3Info mp3Info = new Mp3Info();
long id = cursor.getLong(cursor
.getColumnIndex(MediaStore.Audio.Media._ID)); //音乐id
String title = cursor.getString((cursor
.getColumnIndex(MediaStore.Audio.Media.TITLE))); // 音乐标题
String artist = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ARTIST)); // 艺术家
String album = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ALBUM)); //专辑
long albumId = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
long duration = cursor.getLong(cursor
.getColumnIndex(MediaStore.Audio.Media.DURATION)); // 时长
long size = cursor.getLong(cursor
.getColumnIndex(MediaStore.Audio.Media.SIZE)); // 文件大小
String url = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DATA)); // 文件路径
int isMusic = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC)); // 是否为音乐
if (isMusic != 0) { // 只把音乐添加到集合当中
mp3Info.setId(id);
mp3Info.setTitle(title);
mp3Info.setArtist(artist);
mp3Info.setAlbum(album);
mp3Info.setAlbumId(albumId);
mp3Info.setDuration(duration);
mp3Info.setSize(size);
mp3Info.setUrl(url);
mp3Infos.add(mp3Info);
}
}
return mp3Infos;
} /**
* 往List集合中添加Map对象数据,每一个Map对象存放一首音乐的所有属性
* @param mp3Infos
* @return
*/
public static List<HashMap<String, String>> getMusicMaps(
List<Mp3Info> mp3Infos) {
List<HashMap<String, String>> mp3list = new ArrayList<HashMap<String, String>>();
for (Iterator iterator = mp3Infos.iterator(); iterator.hasNext();) {
Mp3Info mp3Info = (Mp3Info) iterator.next();
HashMap<String, String> map = new HashMap<String, String>();
map.put("title", mp3Info.getTitle());
map.put("Artist", mp3Info.getArtist());
map.put("album", mp3Info.getAlbum());
map.put("albumId", String.valueOf(mp3Info.getAlbumId()));
map.put("duration", formatTime(mp3Info.getDuration()));
map.put("size", String.valueOf(mp3Info.getSize()));
map.put("url", mp3Info.getUrl());
mp3list.add(map);
}
return mp3list;
} /**
* 格式化时间,将毫秒转换为分:秒格式
* @param time
* @return
*/
public static String formatTime(long time) {
String min = time / (1000 * 60) + "";
String sec = time % (1000 * 60) + "";
if (min.length() < 2) {
min = "0" + time / (1000 * 60) + "";
} else {
min = time / (1000 * 60) + "";
}
if (sec.length() == 4) {
sec = "0" + (time % (1000 * 60)) + "";
} else if (sec.length() == 3) {
sec = "00" + (time % (1000 * 60)) + "";
} else if (sec.length() == 2) {
sec = "000" + (time % (1000 * 60)) + "";
} else if (sec.length() == 1) {
sec = "0000" + (time % (1000 * 60)) + "";
}
return min + ":" + sec.trim().substring(0, 2);
} /**
* 获取默认专辑图片
* @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);
} /**
* 从文件当中获取专辑封面位图
* @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
* @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 options
* @param target
* @return
*/
public static int computeSampleSize(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;
}
}

如何在界面显示专辑图片?

看代码就可以看出,通过调用MediaUtil里的getArtwork()方法,就可以返回一个Bitmap对象,在通过imageView控件调用setImageBitmap方法把图片显示出来就行了。很简单对吧。

Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)的更多相关文章

  1. Android应用--简、美音乐播放器增加音量控制

    Android应用--简.美音乐播放器增加音量控制 2013年6月26日简.美音乐播放器继续完善中.. 题外话:上一篇博客是在6月11号发的,那篇博客似乎有点问题,可能是因为代码结构有点乱的原因,很难 ...

  2. Android基于发展Service音乐播放器

    这是一个基于Service组件的音乐播放器,程序的音乐将会由后台的Service组件负责播放,当后台的播放状态改变时,程序将会通过发送广播通知前台Activity更新界面:当用户单击前台Activit ...

  3. 项目源码--Android类似酷狗音乐播放器

    下载源码 知识技能概要: 1.音乐文件的扫描与管理 2.音频流的解码 3. UI控件的综合使用 4.播放列表方式管理 5.随机播放方式 6.源码带详细的中文注释 ...... 详细介绍 1. 音乐文件 ...

  4. Android 仿百度网页音乐播放器圆形图片转圈播放效果

    百度网页音乐播放器的效果  如下 : http://www.baidu.com/baidu?word=%E4%B8%80%E7%9B%B4%E5%BE%88%E5%AE%89%E9%9D%99& ...

  5. android音乐播放器开发 SweetMusicPlayer 载入歌曲列表

    上一篇写了播放器的总体实现思路,http://blog.csdn.net/huweigoodboy/article/details/39855653,如今来总结下载入歌曲列表. 代码地址:https: ...

  6. Android课程---简单的音乐播放器

    第一个:用Activity实现 activity_music_play1.xml <?xml version="1.0" encoding="utf-8" ...

  7. Android应用开发--MP3音乐播放器代码实现(一)

    需求1:将内存卡中的MP3音乐读取出来并显示到列表当中 1.   从数据库中查询所有音乐数据,保存到List集合当中,List当中存放的是Mp3Info对象 2.   迭代List集合,把每一个Mp3 ...

  8. iOS商城demo、音乐播放器、视频通话、自定义搜索、转场动画等源码

    iOS精选源码 微信自定义搜索框实现 一个商城Demo,持续更新中 在Object-C中学习数据结构与算法之排序算法 iOS 音乐播放器之锁屏歌词+歌词解析+锁屏效果 XLsn0wPushTimePi ...

  9. Android多媒体框架对音乐播放器的支持

    下面介绍一下Andriod多媒体框架对开发者提供的支持有哪些.               1. MediaScannerReceiver                   这个广播接收者在接收到A ...

随机推荐

  1. openSUSE13.2安装Nodejs并更新到最新版

    软件源中直接安装Nodejs即可 sudo zypper in nodejs 查看nodejs版本 sincerefly@linux-utem:~> node --version v0.10.5 ...

  2. LibVLC video controls

    原文 http://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc__video.html VLC  3.0.0-git ...

  3. Add GUI to connect to SQL

    (*********************************************************************************) (* *) (* Below i ...

  4. 《互联网初创企业password》书评

    今天试用了一下<互联网初创企业password>这本书.我觉得这本书开始的很真实,从学校刚毕业那会儿.它是生命,他们的牛b时间,一直想做点什么来证明自己.具体地,并且现在是在最好的时候.互 ...

  5. Mysql个人语句笔记

    --一些简单语句记录: /*mysql*/SHOW DATABASES CREATE DATABASE guoDROP DATABASE guo /*查看创建的数据库*/SHOW CREATE DAT ...

  6. AppCompat v21 — Android 5.0之前版本设备的Material Design实现

    博客原文地址:http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html,要想打 ...

  7. How feedback work for your improvement

    Why generally feedback is the perspective from others for some event. In China there is story,some k ...

  8. How To Configure Logging And Log Rotation In Apache On An Ubuntu VPS

    Introduction The Apache web server can be configured to give the server administrator important info ...

  9. nhibernate+autofac+mvc的demo

    想自己做一个小的demo.目的是能够提供一个系统架构,在这个基础上,可以快速开发一些小型的系统.

  10. [转]Even when one byte matters

    Source:http://kernelbof.blogspot.jp/2009/07/even-when-one-byte-matters.html Common Vulnerabilities a ...