获取手机音乐的信息
1. 先在布局文件中添加一个ListView
2. 在fragment中初始化这个ListView
private ListView listView;
listView = (ListView) view.findViewById(R.id.listview);
3. 创建一个用于设置数据的adapter
public class AudioListAdapter extends CursorAdapter{
public AudioListAdapter(Context context, Cursor c) {
super(context, c);
}
//设置需要显示的布局文件
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return null;
}
//设置相关的数据的显示
@Override
public void bindView(View view, Context context, Cursor cursor) {
}
}
4. 优化adapter并为其设置数据的显示
4.1 创建一个viewHolder
class ViewHolder{
//这里是用于显示相关歌曲的名称与艺术家名称的控件,
TextView mTitleTextView,mArtistTextView;
public ViewHolder(View view)
{
mTitleTextView = (TextView) view.findViewById(R.id.tv_title);
mArtistTextView = (TextView) view.findViewById(R.id.tv_artist);
}
4.2 创建一个方法用于获取上面的viewHolder
private ViewHolder getHolder(View view)
{
ViewHolder viewHolder = (ViewHolder) view.getTag();
if(viewHolder==null)
{
viewHolder = new ViewHolder(view);
view.setTag(viewHolder);
}
return viewHolder;
}
4.3 在adapter中使用viewHolder
public class AudioListAdapter extends CursorAdapter
{
public AudioListAdapter(Context context, Cursor c) {
super(context, c);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
//设置显示音乐信息的列表内容
return View.inflate(context, R.layout.adapter_audio_list, null);
}
ViewHolder holder;
@Override
public void bindView(View view, Context context, Cursor cursor)
{
holder = getHolder(view);
//这里是通过对象保存数据的方式将cursor中的数据取出并设置相关显示
AudioItem audioItem = AudioItem.fromCursor(cursor);
holder.mTitleTextView.setText(StringUtil.formatAudioName(audioItem.getTitle()));
holder.mArtistTextView.setText(audioItem.getArtist());
}
}
4.4 这里是使用的对象保存数据的方法
public class AudioItem implements Serializable
{
private String title;
private String artist;
private String path;
private long duration;
//将cursor的数据封装于对象
public static AudioItem fromCursor(Cursor cursor){
AudioItem audioItem = new AudioItem();
audioItem.setArtist(cursor.getString(cursor.getColumnIndex(Media.ARTIST)));
audioItem.setDuration(cursor.getLong(cursor.getColumnIndex(Media.DURATION)));
audioItem.setPath(cursor.getString(cursor.getColumnIndex(Media.DATA)));
audioItem.setTitle(cursor.getString(cursor.getColumnIndex(Media.DISPLAY_NAME)));
return audioItem;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
}
5 在fragment中初使化adapter并使用这个adapter
private AudioListAdapter mAudioAdapter;
mAudioAdapter = new AudioListAdapter(getActivity(), null);
6 将adapter设置给ListView
listView.setAdapter(adapter);
7 查询数据并将数据传输给mAudioAdapter
private SimpleQueryHandler queryHandler;
queryHandler = new SimpleQueryHandler(getActivity().getContentResolver());
//查询的音乐相关的信息
String[] projection = {Media._ID,Media.DISPLAY_NAME,Media.ARTIST,Media.DATA,Media.DURATION};
//数据查询
queryHandler.startQuery(0, adapter, Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
8 使用到的相关查询辅助类
public class SimpleQueryHandler extends AsyncQueryHandler{
public SimpleQueryHandler(ContentResolver cr) {
super(cr);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
super.onQueryComplete(token, cookie, cursor);
if(cookie!=null && cookie instanceof CursorAdapter){
CursorAdapter adapter = (CursorAdapter) cookie;
adapter.changeCursor(cursor);//相当于notify
}
}
}
走到这里,我们就可以将手机中的音乐相关信息显示加载出来了
2 播放音乐的操作
9 创建用于播放音乐的显示页面(这里使用一个activity来显示)
public class AudioPlayerActivity extends Activity{
}
在这里设置自定的播放音乐的显示页面
10 在AudioPlayerActivity的onCreate方法中获取传递的数据
//当前点击要播放的位置
int currentPosition = getIntent().getExtras().getInt("currentPosition");
//所有音乐信息的集合
ArrayList audioList = (ArrayList) getIntent().getExtras().getSerializable("audioList");
11 这里使用的是后台可以进行音乐播放,那么就需要使用到与服务的交互
创建用于播放音乐的服务并进行清单文件中的注册
public class AudioPlayService extends Service{
private AudioServiceBinder audioServiceBinder;
@Override
public IBinder onBind(Intent intent) {
return audioServiceBinder;
}
}
@Override
public void onCreate() {
super.onCreate();
audioServiceBinder = new AudioServiceBinder();
}
//数据相关的绑定操作
public class AudioServiceBinder extends Binder{
}
}
12 在播放音乐的activity中开启服务
AudioPlayerActivity的onCreate方法中
Intent intent = new Intent(this,AudioPlayService.class);
Bundle bundle = new Bundle();
//传输的数据
int currentPosition = getIntent().getExtras().getInt("currentPosition");
ArrayList audioList = (ArrayList) getIntent().getExtras().getSerializable("audioList");
//数据封装
bundle.putInt("currentPosition", currentPosition);
bundle.putSerializable("audioList", audioList);
intent.putExtras(bundle);
//服务绑定
serviceConnection = new AudioServiceConnection();
bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE);
startService(intent);//为了给service传递数据
使用到对象 serviceConnection,类似一个中间人对象,是实现ServiceConnection接口的
class AudioServiceConnection implements ServiceConnection{
//当服务连接的时候会调用这个方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
//当服务断开时候会调用这个方法
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
13 activity 与 service方法的交互
在activity中 通过 serviceConnection 来获取 服务 AudioPlayService 中的AudioServiceBinder
这样我们就可以通过AudioServiceBinder这个对象来进行activity与service中方法的交互
private AudioServiceBinder audioServiceBinder;
class AudioServiceConnection implements ServiceConnection{
//当服务连接的时候会调用这个方法,那么可以在这个方法中获取binder的对象(通过它来操作服务中的相关方法)
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
audioServiceBinder = (AudioServiceBinder) service;
}
//当服务断开时候会调用这个方法
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
14 在service中进行播放音乐的操作
首先获取传递的数据
复写service的方法 onStartCommand 来获取传递的数据
private int currentPosition;
private ArrayList audioList;
private AudioServiceBinder audioServiceBinder ;
@Override
public void onCreate() {
super.onCreate();
audioServiceBinder = new AudioServiceBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//获取数据
currentPosition = intent.getExtras().getInt("currentPosition");
audioList = (ArrayList) intent.getExtras().getSerializable("audioList");
//设置音乐播放
audioServiceBinder.playAudio();
return START_STICKY;//如果服务被杀死,会自动重启
}
在AudioServiceBinder 中设置与播放音乐相关的操作逻辑
设置播放音乐的操作方法
public class AudioServiceBinder extends Binder{
/**
* 播放音乐
*/
public void playAudio(){
//判断一下是否有音乐资源
if(audioList==null || audioList.size()==0)return;
if(mediaPlayer!=null){
mediaPlayer.release();
mediaPlayer = null;
}
AudioItem audioItem = audioList.get(currentPosition);
//创建mediaPlayer对象
mediaPlayer = new MediaPlayer();
//设置相关的监听
mediaPlayer.setOnPreparedListener(mOnPreparedListener);
mediaPlayer.setOnCompletionListener(mOnCompletionListener);
//设置数据源
try {
mediaPlayer.setDataSource(audioItem.getPath());
mediaPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//创建相关的加载播放监听 并设置音乐的播放
private OnPreparedListener mOnPreparedListener = new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
};
private OnCompletionListener mOnCompletionListener = new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
}
};
}
15 在服务中通过发送广播通知Activity中更新页面显示数据
定义我们用到的广播接收者
class AudioServiceReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
}
}
在activity的OnCreate方法中进行注册
/**
* 注册AudioService中的广播接受者
*/
private void registerAudioServiceReceiver() {
receiver = new AudioServiceReceiver();
IntentFilter filter = new IntentFilter(AudioPlayService.ACTION_NOTIFY_PREPARED);//参数是广播接收的标识
//filter.addAction(AudioPlayService.ACTION_COMPLATION); 这里可以添加多个活动
registerReceiver(receiver, filter);
}
在服务中,当音乐开始进行播放的时候,发送广播,并将音乐的信息发给activity中
private void notifyPrepared(){
Intent intent = new Intent(ACTION_NOTIFY_PREPARED);
intent.putExtra("audioItem", audioList.get(currentPosition));//这里面就是携带的数据
sendBroadcast(intent);
}
当广播发送后,我们在对应的广播接收者中进行消息的接收
class AudioServiceReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (AudioPlayService.ACTION_NOTIFY_PREPARED.equarrayLists(intent.getAction())) {
AudioItem audioItem = (AudioItem) intent.getSeriarrayListizableExtra("audioItem");
} else if (AudioPlayService.ACTION_COMPLATION.equarrayLists(intent.getAction())) {
}
}
}