|
楼主 |
发表于 2010-11-17 15:14:02
|
显示全部楼层
本帖最后由 demo 于 2010-11-18 07:16 编辑
Note that this is almost identical to the playSong function from Part 1. However, those really paying attention will notice a difference on lines 47-49. As you see we are now going to create a notification each time a song plays.
To do this we will need to add 2 files to the res/drawable folder, playbackstart.png and playbackpause.png. Once they are added to the "res/drawable" folder they will be referenced by their int value for their id. The first argument for the Notification constructor in the top status bar icon to use. Since this is the playSong() function we want to use the playbackstart.png, which can be referred to as "R.drawable.playbackstart". For the second and fourth parameter we are passing in the filename, this is the text that will be displayed on the status bar animation.
After we create out Notification object we will use our NotificationManager to initiate the notification. this is done on line 49, with nm.notify(int,Notification). We pass in an int, NOTIFY_ID that we will use refer to this notification icon when we need to modify or remove it, along with the Notification that we created.
The NotificationManager is initialized in our onCreate() function, and we make sure to remove the icon with nm.cancel(int) when the service is destroyed in the onDestroy() function:
25. @Override
26. protected void onCreate() {
27. super.onCreate();
28. nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
29.
30. }
31.
32. @Override
33. protected void onDestroy() {
34. mp.stop();
35. mp.release();
36. nm.cancel(NOTIFY_ID);
37. }
38.
39. @Override
40. public IBinder getBinder() {
41. return mBinder;
42. }
We must also cancel the notification after playing the last song on the playlist in our very familiar nextSong() function that is moved into our new Service:
68. private void nextSong() {
69. // Check if last song or not
70. if (++currentPosition >= songs.size()) {
71. currentPosition = 0;
72. nm.cancel(NOTIFY_ID);
73. } else {
74. playSong(MusicDroid.MEDIA_PATH + songs.get(currentPosition));
75. }
76. }
One last function that we have created is prevSong(). We saw it called above on line 107 to handle the work in skipBack() from the interface. Here is prevSong():
78. private void prevSong() {
79. if (mp.getCurrentPosition() < 3000 && currentPosition >= 1) {
80. playSong(MusicDroid.MEDIA_PATH + songs.get(--currentPosition));
81. } else {
82. playSong(MusicDroid.MEDIA_PATH + songs.get(currentPosition));
83. }
84. }
This function is designed to for the skip back functionality that will be shown in Part 3. The idea here is that if you hit the skip back button in the controls then your song will restart, and if you hit it again then it will go the previous song. So here we go to the previous song if we are less than 3 seconds into the song, and we are not listening to the first song on the list (position 0).
So there you have it, a service to handle everything. On the next page we will look at how to bind to this service, and the changes that we need to make to the MusicDroid class to use the new service...
Using Services
In order to use a remote service first we must add a line to our AndroidManifest.xml file inside our application tag to define our service, here is that line:
<service class=".MDService" android:process=":remote" />
Now we can use this service in our MusicDroid ListActivity class that we created in the previous tutorial. We will now try to bind to our newly created service in the onCreate(Bundle) function of our ListActivity:
27. public class MusicDroid extends ListActivity {
28.
29. public static final String MEDIA_PATH = new String("/sdcard/");
30. private List<String> songs = new ArrayList<String>();
31. private MDSInterface mpInterface;
32.
33. @Override
34. public void onCreate(Bundle icicle) {
35. super.onCreate(icicle);
36. setContentView(R.layout.songlist);
37. this.bindService(new Intent(MusicDroid.this,MDService.class),
38. null, mConnection, Context.BIND_AUTO_CREATE);
39. }
40. }
We are binding to our service using a new Intent object, and we are creating the Intent object using the direct reference to a class. You could use a Action and Category to bind to a service also, but for this we can just refer to it directly. We pass in the mConnection variable, this is a ServiceConnection object, and when the service is connected it will call the mConnection.onServiceConnected method, and when disconnected it will call mConnection.onServiceDisconnected. Here is how we define mConnection:
71. private ServiceConnection mConnection = new ServiceConnection()
72. {
73. public void onServiceConnected(ComponentName className, IBinder service) {
74. mpInterface = MDSInterface.Stub.asInterface((IBinder)service);
75. updateSongList();
76. }
77.
78. public void onServiceDisconnected(ComponentName className) {
79. mpInterface = null;
80. }
81. };
So, when the service is connected we can initialize our mpInterface class on line 74. Now that we have this mpInterface class we need to populate the playlist by adding each song using mpInterface.addSongPlaylist(String), we do this in the updateSongList() function:
41. public void updateSongList() {
42. try {
43. File home = new File(MEDIA_PATH);
44. File fileList[] = home.listFiles(new Mp3Filter());
45. mpInterface.clearPlaylist();
46. if (fileList != null) {
47. for (File file : fileList ) {
48. songs.add(file.getName());
49. mpInterface.addSongPlaylist(file.getName());
50. }
51.
52. ArrayAdapter<String> songList = new ArrayAdapter<String>(this,
53. R.layout.song_item, songs);
54. setListAdapter(songList);
55. }
56. } catch(DeadObjectException e) {
57. Log.e(getString(R.string.app_name), e.getMessage());
58. }
59. }
This function is pretty much identical to it's first incarnation in the previous tutorial. The only thing we needed to add is the mpInterface.addSongPlaylist(String) call on line 49 so that our Service is aware of the entire playlist, so that it can play the next song without having help from another Activity.
And lastly, we must play a song when a user clicks on a song, so here is that method:
61. @Override
62. protected void onListItemClick(ListView l, View v, int position, long id) {
63. try {
64. mpInterface.playFile(position);
65. } catch(DeadObjectException e) {
66. Log.e(getString(R.string.app_name), e.getMessage());
67. }
68. }
We simply use the mpInterface.playFile(int) method that we designed earlier in this tutorial.
So now we have a playlist ListActivity and a Service to handle playing the music, but we still have no way to control the music. In the next section we will create a graphical user interface for the controls, introducing ImageViews and Animation...
|
|