Activity代码
package com.siyehuazhilian.musicplay; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.app.AlertDialog; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.graphics.Color; import android.os.Bundle; import android.provider.MediaStore; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageButton; import android.widget.ListView; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.SimpleAdapter; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { // ListView private ListView listView; // 适配器 private SimpleAdapter adapter; // 数据源 private ArrayList<HashMap<String, String>> list; // 当前播放的曲目 private int currentPositionMusic = -1; // 上一首 private ImageButton lastImageButton; // 播放 private ImageButton playImageButton; // 下一首 private ImageButton nextImageButton; // 循环 private ImageButton loopImageButton; // 播放进度 private SeekBar playSeekBar; // 当前播放曲目 private TextView currentPlayingSong; // 是否是第一次进来 private boolean ifFirstIn = true; private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listview); lastImageButton = (ImageButton) findViewById(R.id.imagebutton_previous); playImageButton = (ImageButton) findViewById(R.id.imagebutton_play); nextImageButton = (ImageButton) findViewById(R.id.imagebutton_next); loopImageButton = (ImageButton) findViewById(R.id.imagebutton_loops); playSeekBar = (SeekBar) findViewById(R.id.seekbar_play); currentPlayingSong = (TextView) findViewById(R.id.textview_songinformation); list = new ArrayList<HashMap<String, String>>(); adapter = new SimpleAdapter(this, list, R.layout.list_item, new String[] { "title" }, new int[] { R.id.textview_item }); listView.setAdapter(adapter); // 为listView设置监听器 listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { try { currentPositionMusic = position; playMusic(); } catch (Exception e) { e.printStackTrace(); } } }); lastImageButton.setOnClickListener(this); playImageButton.setOnClickListener(this); nextImageButton.setOnClickListener(this); loopImageButton.setOnClickListener(this); playSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) { // 改变进度条 intent = new Intent("changed"); intent.putExtra("seekbarprogress", progress); startService(intent); } } }); } private void playMusic() { // 启动播放音乐的服务 intent = new Intent("play"); intent.putExtra("uri", ((HashMap<String, String>) list .get(currentPositionMusic)).get("path")); intent.putExtra("title", ((HashMap<String, String>) list .get(currentPositionMusic)).get("title")); startService(intent); // 把图片改为播放的图片 playImageButton.setImageResource(R.drawable.play); // 同时更改SeekBar的进度,因为进度是不断变化的,所以需要一个子线程来刷新下 // playSeekBar.setMax(mp.getDuration()); // 设置当前播放曲目信息 currentPlayingSong.setTextColor(Color.GREEN); currentPlayingSong.setText(list.get(currentPositionMusic).get("title")); } @Override protected void onResume() { super.onResume(); // 得到所有音频 if (ifFirstIn) { ifFirstIn = false; scanMusic(); } // 动态注册广播 IntentFilter filter = new IntentFilter(); filter.addAction("seekbarmaxprogress"); filter.addAction("seekbarprogress"); filter.addAction("playNextSong"); filter.addAction("pause"); filter.addAction("setplay"); filter.addAction("stoploop"); filter.addAction("startloop"); registerReceiver(broadcastReceiver, filter); } @Override protected void onDestroy() { super.onDestroy(); // 关闭通知 intent = new Intent("stopnotification"); startService(intent); // 停止服务 stopService(intent); // 取消广播的注册 unregisterReceiver(broadcastReceiver); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("你确定要退出吗?"); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); builder.show(); return true; } else { return super.onKeyDown(keyCode, event); } } /** * 得多所有的音频 */ private void scanMusic() { // 置空list集合中的所有元素,放置反复启动导致的数据重复,其实这个部分是因为每次进来都会重新获得焦点,执行onResume造成的 // 这个修改虽然可以,但是每次进来都有重新加载,增加了手机的符合,所以可以设置一个标志,只有在第一进来的时候才会加载数据 // list.clear(); new Thread() { public void run() { Cursor cursor = getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); while (cursor.moveToNext()) { String title = cursor .getString(cursor .getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)); String path = cursor .getString(cursor .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)); String size = cursor .getString(cursor .getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE)); if (Long.parseLong(size) > 1024 * 1024) { HashMap<String, String> hashMap1 = new HashMap<String, String>(); hashMap1.put("title", title); hashMap1.put("path", path); list.add(hashMap1); } } cursor.close(); }; }.start(); } /** * 监听 */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.imagebutton_previous: playLastSong(); break; case R.id.imagebutton_play: intent = new Intent("clickplay"); startService(intent); break; case R.id.imagebutton_next: playNextSong(); break; case R.id.imagebutton_loops: intent = new Intent("loops"); startService(intent); break; default: break; } } /** * 播放下一曲 */ private void playNextSong() { // 只有当有音乐在播放的时候才可以点击下一首 if (currentPositionMusic != -1) { // 如果当前歌曲为最后一首,就播放第一首歌曲 if (currentPositionMusic == list.size() - 1) { // 设置当前歌曲为第一首 currentPositionMusic = 0; try { // 播放第一首歌曲 playMusic(); } catch (Exception e) { e.printStackTrace(); } }// 否则就播放下一首歌曲 else { // 设置当前歌曲为下一首 currentPositionMusic++; try { // 播放下一首歌曲 playMusic(); } catch (Exception e) { e.printStackTrace(); } } } } /** * 播放上一曲 */ private void playLastSong() { // 只有当有音乐在播放的时候才可以点击上一首 if (currentPositionMusic != -1) { // 如果当前歌曲为第一首,就播放最后一首歌曲 if (currentPositionMusic == 0) { // 设置当前歌曲为最后一首 currentPositionMusic = list.size() - 1; try { // 播放最后一首歌曲 playMusic(); } catch (Exception e) { e.printStackTrace(); } }// 否则就播放上一首歌曲 else { // 设置当前歌曲为前一首 currentPositionMusic--; try { // 播放前一首歌曲 playMusic(); } catch (Exception e) { e.printStackTrace(); } } } } /** * 广播对象,动态注册,用来接收从Service传过来的消息,根据不同的消息做不同的事情 */ private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("seekbarmaxprogress")) { playSeekBar.setMax(intent .getIntExtra("seekbarmaxprogress", 100)); } else if (intent.getAction().equals("seekbarprogress")) { playSeekBar.setProgress(intent .getIntExtra("seekbarprogress", 0)); } else if (intent.getAction().equals("playNextSong")) { playNextSong(); } else if (intent.getAction().equals("pause")) { // 还要把图片改为暂停的图片 playImageButton.setImageResource(R.drawable.pause); } else if (intent.getAction().equals("setplay")) { // 把图片设置成播放的图片 playImageButton.setImageResource(R.drawable.play); } else if (intent.getAction().equals("stoploop")) { // 还要把图片改为不循环的图片 loopImageButton.setImageResource(R.drawable.loop_false); } else if (intent.getAction().equals("startloop")) { // 把图片设置成循环播放的图片 loopImageButton.setImageResource(R.drawable.loop_true); } } }; }
Service代码
package com.siyehuazhilian.service; import java.util.HashMap; import com.siyehuazhilian.musicplay.MainActivity; import com.siyehuazhilian.musicplay.R; import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnPreparedListener; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.widget.Toast; public class PlayMusicService extends Service { private MediaPlayer mediaPlayer; // 设置Seebar最大进度 private static final int SET_SEEKBAR_MAX = 3; // 刷新SeekBar进度 private static final int UPDATE_PROGRESS = 1; // 加载数据 private static final int LOADING_DATA = 2; // 通知管理 private NotificationManager notificationManager; // 通知 private Notification notification; private Intent intent; @Override public IBinder onBind(Intent intent) { return null; } @SuppressLint("ShowToast") @Override public int onStartCommand(Intent intent, int flags, int startId) { notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); if (intent.getAction().equals("play")) {// 如果是播放Action,就播放音乐 try { Toast.makeText(getApplicationContext(), "开始播放", 1000).show(); playMusic(intent.getStringExtra("uri")); showNotification(intent.getStringExtra("title")); } catch (Exception e) { e.printStackTrace(); } } else if (intent.getAction().equals("changed")) {// 如果是拖动的Action,就跳至拖动的进度 if (mediaPlayer != null) { mediaPlayer.seekTo(intent.getIntExtra("seekbarprogress", 0)); } } else if (intent.getAction().equals("clickplay")) {// 如果是播放/暂停Action,就执行相应的播放或者暂停 Toast.makeText(getApplicationContext(), "播放被点击了", 1000).show(); if (mediaPlayer != null) { // 如果音乐播放器正在播放 if (mediaPlayer.isPlaying()) { // 那就暂停它 mediaPlayer.pause(); // 发送暂停广播给程序 this.intent = new Intent("pause"); sendBroadcast(this.intent); } else { // 否则就播放它 mediaPlayer.start(); // 发送播放广播 this.intent = new Intent("setplay"); sendBroadcast(this.intent); } } } else if (intent.getAction().equals("loops")) {// 如果是loop循环Action,就把歌曲设置为循环播放 Toast.makeText(getApplicationContext(), "循环被点击了", 1000).show(); if (mediaPlayer != null) { // 如果音乐播放器正在循环 if (mediaPlayer.isLooping()) { // 那就终止循环它 mediaPlayer.setLooping(false); // 发送终止循环广播 this.intent = new Intent("stoploop"); sendBroadcast(this.intent); } else { // 否则就循环播放它 mediaPlayer.setLooping(true); // 发送开始循环广播 this.intent = new Intent("startloop"); sendBroadcast(this.intent); } } } else if (intent.getAction().equals("stopnotification")) { notificationManager.cancelAll(); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); handler.removeMessages(UPDATE_PROGRESS); mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } /** * 播放音乐 * * @param path * @throws Exception */ private void playMusic(String path) throws Exception { if (mediaPlayer == null) { // 新建一个mediaPalyer对象 mediaPlayer = new MediaPlayer(); } // 使mediaPalyer进入Idle状态 mediaPlayer.reset(); // 设置数据源,使mediaPlayer进入Intialized状态 mediaPlayer.setDataSource(path); // 准备播放 mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // 开始播放音乐 mp.start(); handler.sendEmptyMessage(SET_SEEKBAR_MAX); handler.sendEmptyMessage(UPDATE_PROGRESS); } }); mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { if (mp.isLooping()) { mp.start(); } else { intent = new Intent("playNextSong"); sendBroadcast(intent); } } }); } private Handler handler = new Handler() { @SuppressLint("HandlerLeak") public void handleMessage(Message msg) { switch (msg.what) { case UPDATE_PROGRESS: // 设置最大当前播放进度 intent = new Intent("seekbarprogress"); intent.putExtra("seekbarprogress", mediaPlayer.getCurrentPosition()); sendBroadcast(intent); // 需要随着播放设置 handler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 1000); break; case LOADING_DATA: // adapter.notifyDataSetInvalidated(); break; case SET_SEEKBAR_MAX: intent = new Intent("seekbarmaxprogress"); intent.putExtra("seekbarmaxprogress", mediaPlayer.getDuration()); sendBroadcast(intent); // 因为进度条只需要设置一次就够了,所以不需要反复发送Message; break; default: break; } }; }; /** * 显示通知 * */ private void showNotification(String title) { notification = new Notification(R.drawable.app_icon, "百度音乐", System.currentTimeMillis()); notification.flags |= Notification.FLAG_NO_CLEAR; notification.flags |= Notification.FLAG_ONGOING_EVENT; Intent intent = new Intent(this, MainActivity.class); intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); notification.setLatestEventInfo(this, "正在播放", title, pendingIntent); notificationManager.notify(1, notification); } }
AndroidManifest.xml代码
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.siyehuazhilian.musicplay" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <uses-permission android:name="android.permission.VIBRATE" /> <application android:allowBackup="true" android:icon="@drawable/app_icon" android:label="@string/app_name" android:theme="@android:style/Theme.Light.NoTitleBar" > <activity android:name="com.siyehuazhilian.musicplay.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="audio/*" /> </intent-filter> </activity> <service android:name="com.siyehuazhilian.service.PlayMusicService" > <intent-filter> <action android:name="play" /> <action android:name="changed" /> <action android:name="clickplay" /> <action android:name="loops" /> <action android:name="stopnotification" /> </intent-filter> </service> </application> </manifest>