ctivity代码
view sourceprint?001.
package
com.siyehuazhilian.musicplay;
002.
003.
import
java.util.ArrayList;
004.
import
java.util.HashMap;
005.
006.
import
android.app.Activity;
007.
import
android.app.AlertDialog;
008.
import
android.app.Notification;
009.
import
android.app.NotificationManager;
010.
import
android.app.PendingIntent;
011.
import
android.content.BroadcastReceiver;
012.
import
android.content.Context;
013.
import
android.content.DialogInterface;
014.
import
android.content.Intent;
015.
import
android.content.IntentFilter;
016.
import
android.database.Cursor;
017.
import
android.graphics.Color;
018.
import
android.os.Bundle;
019.
import
android.provider.MediaStore;
020.
import
android.view.KeyEvent;
021.
import
android.view.View;
022.
import
android.view.View.OnClickListener;
023.
import
android.widget.AdapterView;
024.
import
android.widget.AdapterView.OnItemClickListener;
025.
import
android.widget.ImageButton;
026.
import
android.widget.ListView;
027.
import
android.widget.SeekBar;
028.
import
android.widget.SeekBar.OnSeekBarChangeListener;
029.
import
android.widget.SimpleAdapter;
030.
import
android.widget.TextView;
031.
032.
public
class
MainActivity
extends
Activity
implements
OnClickListener {
033.
// ListView
034.
private
ListView listView;
035.
// 适配器
036.
private
SimpleAdapter adapter;
037.
// 数据源
038.
private
ArrayList<hashmap<string, string=
""
>> list;
039.
// 当前播放的曲目
040.
private
int
currentPositionMusic = -
1
;
041.
042.
// 上一首
043.
private
ImageButton lastImageButton;
044.
// 播放
045.
private
ImageButton playImageButton;
046.
// 下一首
047.
private
ImageButton nextImageButton;
048.
// 循环
049.
private
ImageButton loopImageButton;
050.
// 播放进度
051.
private
SeekBar playSeekBar;
052.
// 当前播放曲目
053.
private
TextView currentPlayingSong;
054.
// 是否是第一次进来
055.
private
boolean
ifFirstIn =
true
;
056.
057.
private
Intent intent;
058.
059.
@Override
060.
protected
void
onCreate(Bundle savedInstanceState) {
061.
super
.onCreate(savedInstanceState);
062.
setContentView(R.layout.activity_main);
063.
listView = (ListView) findViewById(R.id.listview);
064.
lastImageButton = (ImageButton) findViewById(R.id.imagebutton_previous);
065.
playImageButton = (ImageButton) findViewById(R.id.imagebutton_play);
066.
nextImageButton = (ImageButton) findViewById(R.id.imagebutton_next);
067.
loopImageButton = (ImageButton) findViewById(R.id.imagebutton_loops);
068.
playSeekBar = (SeekBar) findViewById(R.id.seekbar_play);
069.
currentPlayingSong = (TextView) findViewById(R.id.textview_songinformation);
070.
list =
new
ArrayList<hashmap<string, string=
""
>>();
071.
072.
adapter =
new
SimpleAdapter(
this
, list, R.layout.list_item,
073.
new
String[] {
"title"
},
new
int
[] { R.id.textview_item });
074.
listView.setAdapter(adapter);
075.
076.
// 为listView设置监听器
077.
listView.setOnItemClickListener(
new
OnItemClickListener() {
078.
079.
@Override
080.
public
void
onItemClick(AdapterView<!--?--> arg0, View arg1,
081.
int
position,
long
arg3) {
082.
try
{
083.
currentPositionMusic = position;
084.
playMusic();
085.
}
catch
(Exception e) {
086.
e.printStackTrace();
087.
}
088.
}
089.
});
090.
091.
lastImageButton.setOnClickListener(
this
);
092.
playImageButton.setOnClickListener(
this
);
093.
nextImageButton.setOnClickListener(
this
);
094.
loopImageButton.setOnClickListener(
this
);
095.
playSeekBar.setOnSeekBarChangeListener(
new
OnSeekBarChangeListener() {
096.
097.
@Override
098.
public
void
onStopTrackingTouch(SeekBar seekBar) {
099.
100.
}
101.
102.
@Override
103.
public
void
onStartTrackingTouch(SeekBar seekBar) {
104.
105.
}
106.
107.
@Override
108.
public
void
onProgressChanged(SeekBar seekBar,
int
progress,
109.
boolean
fromUser) {
110.
if
(fromUser) {
111.
// 改变进度条
112.
intent =
new
Intent(
"changed"
);
113.
intent.putExtra(
"seekbarprogress"
, progress);
114.
startService(intent);
115.
}
116.
}
117.
});
118.
}
119.
120.
private
void
playMusic() {
121.
// 启动播放音乐的服务
122.
intent =
new
Intent(
"play"
);
123.
intent.putExtra(
"uri"
, ((HashMap<string, string=
""
>) list
124.
.get(currentPositionMusic)).get(
"path"
));
125.
intent.putExtra(
"title"
, ((HashMap<string, string=
""
>) list
126.
.get(currentPositionMusic)).get(
"title"
));
127.
startService(intent);
128.
// 把图片改为播放的图片
129.
playImageButton.setImageResource(R.drawable.play);
130.
// 同时更改SeekBar的进度,因为进度是不断变化的,所以需要一个子线程来刷新下
131.
// playSeekBar.setMax(mp.getDuration());
132.
// 设置当前播放曲目信息
133.
currentPlayingSong.setTextColor(Color.GREEN);
134.
currentPlayingSong.setText(list.get(currentPositionMusic).get(
"title"
));
135.
}
136.
137.
@Override
138.
protected
void
onResume() {
139.
super
.onResume();
140.
// 得到所有音频
141.
if
(ifFirstIn) {
142.
ifFirstIn =
false
;
143.
scanMusic();
144.
}
145.
// 动态注册广播
146.
IntentFilter filter =
new
IntentFilter();
147.
filter.addAction(
"seekbarmaxprogress"
);
148.
filter.addAction(
"seekbarprogress"
);
149.
filter.addAction(
"playNextSong"
);
150.
filter.addAction(
"pause"
);
151.
filter.addAction(
"setplay"
);
152.
filter.addAction(
"stoploop"
);
153.
filter.addAction(
"startloop"
);
154.
registerReceiver(broadcastReceiver, filter);
155.
}
156.
157.
@Override
158.
protected
void
onDestroy() {
159.
super
.onDestroy();
160.
// 关闭通知
161.
intent =
new
Intent(
"stopnotification"
);
162.
startService(intent);
163.
164.
// 停止服务
165.
stopService(intent);
166.
// 取消广播的注册
167.
unregisterReceiver(broadcastReceiver);
168.
}
169.
170.
@Override
171.
public
boolean
onKeyDown(
int
keyCode, KeyEvent event) {
172.
if
(keyCode == KeyEvent.KEYCODE_BACK) {
173.
AlertDialog.Builder builder =
new
AlertDialog.Builder(
this
);
174.
builder.setTitle(
"你确定要退出吗?"
);
175.
builder.setPositiveButton(
"确定"
,
176.
new
DialogInterface.OnClickListener() {
177.
@Override
178.
public
void
onClick(DialogInterface dialog,
int
which) {
179.
finish();
180.
}
181.
});
182.
builder.setNegativeButton(
"取消"
,
183.
new
DialogInterface.OnClickListener() {
184.
@Override
185.
public
void
onClick(DialogInterface dialog,
int
which) {
186.
}
187.
});
188.
builder.show();
189.
return
true
;
190.
}
else
{
191.
return
super
.onKeyDown(keyCode, event);
192.
}
193.
}
194.
195.
/**
196.
* 得多所有的音频
197.
*/
198.
private
void
scanMusic() {
199.
// 置空list集合中的所有元素,放置反复启动导致的数据重复,其实这个部分是因为每次进来都会重新获得焦点,执行onResume造成的
200.
// 这个修改虽然可以,但是每次进来都有重新加载,增加了手机的符合,所以可以设置一个标志,只有在第一进来的时候才会加载数据
201.
// list.clear();
202.
new
Thread() {
203.
public
void
run() {
204.
Cursor cursor = getContentResolver().query(
205.
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null
,
206.
null
,
null
, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
207.
208.
while
(cursor.moveToNext()) {
209.
String title = cursor
210.
.getString(cursor
211.
.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
212.
String path = cursor
213.
.getString(cursor
214.
.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
215.
String size = cursor
216.
.getString(cursor
217.
.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
218.
if
(Long.parseLong(size) >
1024
*
1024
) {
219.
HashMap<string, string=
""
> hashMap1 =
new
HashMap<string, string=
""
>();
220.
hashMap1.put(
"title"
, title);
221.
hashMap1.put(
"path"
, path);
222.
list.add(hashMap1);
223.
}
224.
}
225.
cursor.close();
226.
};
227.
}.start();
228.
229.
}
230.
231.
/**
232.
* 监听
233.
*/
234.
@Override
235.
public
void
onClick(View v) {
236.
switch
(v.getId()) {
237.
case
R.id.imagebutton_previous:
238.
playLastSong();
239.
break
;
240.
case
R.id.imagebutton_play:
241.
intent =
new
Intent(
"clickplay"
);
242.
startService(intent);
243.
break
;
244.
case
R.id.imagebutton_next:
245.
playNextSong();
246.
break
;
247.
case
R.id.imagebutton_loops:
248.
intent =
new
Intent(
"loops"
);
249.
startService(intent);
250.
break
;
251.
default
:
252.
break
;
253.
}
254.
}
255.
256.
/**
257.
* 播放下一曲
258.
*/
259.
private
void
playNextSong() {
260.
// 只有当有音乐在播放的时候才可以点击下一首
261.
if
(currentPositionMusic != -
1
) {
262.
// 如果当前歌曲为最后一首,就播放第一首歌曲
263.
if
(currentPositionMusic == list.size() -
1
) {
264.
// 设置当前歌曲为第一首
265.
currentPositionMusic =
0
;
266.
try
{
267.
// 播放第一首歌曲
268.
playMusic();
269.
}
catch
(Exception e) {
270.
e.printStackTrace();
271.
}
272.
}
// 否则就播放下一首歌曲
273.
else
{
274.
// 设置当前歌曲为下一首
275.
currentPositionMusic++;
276.
try
{
277.
// 播放下一首歌曲
278.
playMusic();
279.
}
catch
(Exception e) {
280.
e.printStackTrace();
281.
}
282.
}
283.
284.
}
285.
}
286.
287.
/**
288.
* 播放上一曲
289.
*/
290.
private
void
playLastSong() {
291.
// 只有当有音乐在播放的时候才可以点击上一首
292.
if
(currentPositionMusic != -
1
) {
293.
// 如果当前歌曲为第一首,就播放最后一首歌曲
294.
if
(currentPositionMusic ==
0
) {
295.
// 设置当前歌曲为最后一首
296.
currentPositionMusic = list.size() -
1
;
297.
try
{
298.
// 播放最后一首歌曲
299.
playMusic();
300.
}
catch
(Exception e) {
301.
e.printStackTrace();
302.
}
303.
}
// 否则就播放上一首歌曲
304.
else
{
305.
// 设置当前歌曲为前一首
306.
currentPositionMusic--;
307.
try
{
308.
// 播放前一首歌曲
309.
playMusic();
310.
}
catch
(Exception e) {
311.
e.printStackTrace();
312.
}
313.
}
314.
315.
}
316.
}
317.
318.
/**
319.
* 广播对象,动态注册,用来接收从Service传过来的消息,根据不同的消息做不同的事情
320.
*/
321.
private
BroadcastReceiver broadcastReceiver =
new
BroadcastReceiver() {
322.
323.
@Override
324.
public
void
onReceive(Context context, Intent intent) {
325.
if
(intent.getAction().equals(
"seekbarmaxprogress"
)) {
326.
playSeekBar.setMax(intent
327.
.getIntExtra(
"seekbarmaxprogress"
,
100
));
328.
}
else
if
(intent.getAction().equals(
"seekbarprogress"
)) {
329.
playSeekBar.setProgress(intent
330.
.getIntExtra(
"seekbarprogress"
,
0
));
331.
}
else
if
(intent.getAction().equals(
"playNextSong"
)) {
332.
playNextSong();
333.
}
else
if
(intent.getAction().equals(
"pause"
)) {
334.
// 还要把图片改为暂停的图片
335.
playImageButton.setImageResource(R.drawable.pause);
336.
}
else
if
(intent.getAction().equals(
"setplay"
)) {
337.
// 把图片设置成播放的图片
338.
playImageButton.setImageResource(R.drawable.play);
339.
}
else
if
(intent.getAction().equals(
"stoploop"
)) {
340.
// 还要把图片改为不循环的图片
341.
loopImageButton.setImageResource(R.drawable.loop_false);
342.
}
else
if
(intent.getAction().equals(
"startloop"
)) {
343.
// 把图片设置成循环播放的图片
344.
loopImageButton.setImageResource(R.drawable.loop_true);
345.
}
346.
347.
}
348.
};
349.
350.
}
351.
</string,></string,></string,></string,></hashmap<string,></hashmap<string,>
Service代码
view sourceprint?001.
package
com.siyehuazhilian.service;
002.
003.
import
java.util.HashMap;
004.
005.
import
com.siyehuazhilian.musicplay.MainActivity;
006.
import
com.siyehuazhilian.musicplay.R;
007.
008.
import
android.annotation.SuppressLint;
009.
import
android.app.Notification;
010.
import
android.app.NotificationManager;
011.
import
android.app.PendingIntent;
012.
import
android.app.Service;
013.
import
android.content.Intent;
014.
import
android.media.MediaPlayer;
015.
import
android.media.MediaPlayer.OnCompletionListener;
016.
import
android.media.MediaPlayer.OnPreparedListener;
017.
import
android.os.Handler;
018.
import
android.os.IBinder;
019.
import
android.os.Message;
020.
import
android.widget.Toast;
021.
022.
public
class
PlayMusicService
extends
Service {
023.
private
MediaPlayer mediaPlayer;
024.
// 设置Seebar最大进度
025.
private
static
final
int
SET_SEEKBAR_MAX =
3
;
026.
// 刷新SeekBar进度
027.
private
static
final
int
UPDATE_PROGRESS =
1
;
028.
// 加载数据
029.
private
static
final
int
LOADING_DATA =
2
;
030.
031.
// 通知管理
032.
private
NotificationManager notificationManager;
033.
// 通知
034.
private
Notification notification;
035.
036.
private
Intent intent;
037.
038.
@Override
039.
public
IBinder onBind(Intent intent) {
040.
return
null
;
041.
}
042.
043.
@SuppressLint
(
"ShowToast"
)
044.
@Override
045.
public
int
onStartCommand(Intent intent,
int
flags,
int
startId) {
046.
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
047.
048.
if
(intent.getAction().equals(
"play"
)) {
// 如果是播放Action,就播放音乐
049.
try
{
050.
Toast.makeText(getApplicationContext(),
"开始播放"
,
1000
).show();
051.
playMusic(intent.getStringExtra(
"uri"
));
052.
showNotification(intent.getStringExtra(
"title"
));
053.
}
catch
(Exception e) {
054.
e.printStackTrace();
055.
}
056.
}
else
if
(intent.getAction().equals(
"changed"
)) {
// 如果是拖动的Action,就跳至拖动的进度
057.
if
(mediaPlayer !=
null
) {
058.
mediaPlayer.seekTo(intent.getIntExtra(
"seekbarprogress"
,
0
));
059.
}
060.
}
else
if
(intent.getAction().equals(
"clickplay"
)) {
// 如果是播放/暂停Action,就执行相应的播放或者暂停
061.
Toast.makeText(getApplicationContext(),
"播放被点击了"
,
1000
).show();
062.
if
(mediaPlayer !=
null
) {
063.
// 如果音乐播放器正在播放
064.
if
(mediaPlayer.isPlaying()) {
065.
// 那就暂停它
066.
mediaPlayer.pause();
067.
// 发送暂停广播给程序
068.
this
.intent =
new
Intent(
"pause"
);
069.
sendBroadcast(
this
.intent);
070.
}
else
{
071.
// 否则就播放它
072.
mediaPlayer.start();
073.
// 发送播放广播
074.
this
.intent =
new
Intent(
"setplay"
);
075.
sendBroadcast(
this
.intent);
076.
}
077.
}
078.
}
else
if
(intent.getAction().equals(
"loops"
)) {
// 如果是loop循环Action,就把歌曲设置为循环播放
079.
Toast.makeText(getApplicationContext(),
"循环被点击了"
,
1000
).show();
080.
if
(mediaPlayer !=
null
) {
081.
// 如果音乐播放器正在循环
082.
if
(mediaPlayer.isLooping()) {
083.
// 那就终止循环它
084.
mediaPlayer.setLooping(
false
);
085.
// 发送终止循环广播
086.
this
.intent =
new
Intent(
"stoploop"
);
087.
sendBroadcast(
this
.intent);
088.
}
else
{
089.
// 否则就循环播放它
090.
mediaPlayer.setLooping(
true
);
091.
// 发送开始循环广播
092.
this
.intent =
new
Intent(
"startloop"
);
093.
sendBroadcast(
this
.intent);
094.
}
095.
}
096.
}
else
if
(intent.getAction().equals(
"stopnotification"
)) {
097.
notificationManager.cancelAll();
098.
}
099.
100.
return
super
.onStartCommand(intent, flags, startId);
101.
}
102.
103.
@Override
104.
public
void
onDestroy() {
105.
super
.onDestroy();
106.
handler.removeMessages(UPDATE_PROGRESS);
107.
mediaPlayer.stop();
108.
mediaPlayer.release();
109.
mediaPlayer =
null
;
110.
}
111.
112.
/**
113.
* 播放音乐
114.
*
115.
* @param path
116.
* @throws Exception
117.
*/
118.
private
void
playMusic(String path)
throws
Exception {
119.
if
(mediaPlayer ==
null
) {
120.
// 新建一个mediaPalyer对象
121.
mediaPlayer =
new
MediaPlayer();
122.
}
123.
// 使mediaPalyer进入Idle状态
124.
mediaPlayer.reset();
125.
// 设置数据源,使mediaPlayer进入Intialized状态
126.
mediaPlayer.setDataSource(path);
127.
// 准备播放
128.
mediaPlayer.prepareAsync();
129.
mediaPlayer.setOnPreparedListener(
new
OnPreparedListener() {
130.
131.
@Override
132.
public
void
onPrepared(MediaPlayer mp) {
133.
// 开始播放音乐
134.
mp.start();
135.
handler.sendEmptyMessage(SET_SEEKBAR_MAX);
136.
handler.sendEmptyMessage(UPDATE_PROGRESS);
137.
138.
}
139.
});
140.
mediaPlayer.setOnCompletionListener(
new
OnCompletionListener() {
141.
142.
@Override
143.
public
void
onCompletion(MediaPlayer mp) {
144.
if
(mp.isLooping()) {
145.
mp.start();
146.
}
else
{
147.
intent =
new
Intent(
"playNextSong"
);
148.
sendBroadcast(intent);
149.
}
150.
}
151.
});
152.
}
153.
154.
private
Handler handler =
new
Handler() {
155.
@SuppressLint
(
"HandlerLeak"
)
156.
public
void
handleMessage(Message msg) {
157.
switch
(msg.what) {
158.
case
UPDATE_PROGRESS:
159.
// 设置最大当前播放进度
160.
intent =
new
Intent(
"seekbarprogress"
);
161.
intent.putExtra(
"seekbarprogress"
,
162.
mediaPlayer.getCurrentPosition());
163.
sendBroadcast(intent);
164.
// 需要随着播放设置
165.
handler.sendEmptyMessageDelayed(UPDATE_PROGRESS,
1000
);
166.
break
;
167.
case
LOADING_DATA:
168.
// adapter.notifyDataSetInvalidated();
169.
break
;
170.
case
SET_SEEKBAR_MAX:
171.
intent =
new
Intent(
"seekbarmaxprogress"
);
172.
intent.putExtra(
"seekbarmaxprogress"
, mediaPlayer.getDuration());
173.
sendBroadcast(intent);
174.
// 因为进度条只需要设置一次就够了,所以不需要反复发送Message;
175.
break
;
176.
default
:
177.
break
;
178.
}
179.
};
180.
};
181.
182.
/**
183.
* 显示通知
184.
*
185.
*/
186.
private
void
showNotification(String title) {
187.
notification =
new
Notification(R.drawable.app_icon,
"百度音乐"
,
188.
System.currentTimeMillis());
189.
190.
notification.flags |= Notification.FLAG_NO_CLEAR;
191.
notification.flags |= Notification.FLAG_ONGOING_EVENT;
192.
193.
Intent intent =
new
Intent(
this
, MainActivity.
class
);
194.
intent.setAction(Intent.ACTION_MAIN);
195.
intent.addCategory(Intent.CATEGORY_LAUNCHER);
196.
PendingIntent pendingIntent = PendingIntent.getActivity(
this
,
0
,
197.
intent,
0
);
198.
199.
notification.setLatestEventInfo(
this
,
"正在播放"
, title, pendingIntent);
200.
201.
notificationManager.notify(
1
, notification);
202.
}
203.
}
AndroidManifest.xml代码
view sourceprint?01.
<!--?xml version="1.0" encoding="utf-8"?-->
02.
<
manifest
android:versioncode
=
"1"
android:versionname
=
"1.0"
package
=
"com.siyehuazhilian.musicplay"
xmlns:android
=
"/apk/res/android"
>
03.
04.
<
uses-sdk
android:minsdkversion
=
"8"
android:targetsdkversion
=
"18"
>
05.
06.
<
uses-permission
android:name
=
"android.permission.VIBRATE"
>
07.
08.
<
application
android:allowbackup
=
"true"
android:icon
=
"@drawable/app_icon"
android:label
=
"@string/app_name"
android:theme
=
"@android:style/Theme.Light.NoTitleBar"
>
09.
<
activity
android:label
=
"@string/app_name"
android:name
=
"com.siyehuazhilian.musicplay.MainActivity"
>
10.
<
intent-filter
>
11.
<
action
android:name
=
"android.intent.action.MAIN"
>
12.
13.
<
category
android:name
=
"android.intent.category.LAUNCHER"
>
14.
</
category
></
action
></
intent-filter
>
15.
<
intent-filter
>
16.
<
action
android:name
=
"android.intent.action.VIEW"
>
17.
18.
<
category
android:name
=
"android.intent.category.DEFAULT"
>
19.
20.
<
data
android:mimetype
=
"audio/*"
>
21.
</
data
></
category
></
action
></
intent-filter
>
22.
</
activity
>
23.
24.
<
service
android:name
=
"com.siyehuazhilian.service.PlayMusicService"
>
25.
<
intent-filter
>
26.
<
action
android:name
=
"play"
>
27.
<
action
android:name
=
"changed"
>
28.
<
action
android:name
=
"clickplay"
>
29.
<
action
android:name
=
"loops"
>
30.
<
action
android:name
=
"stopnotification"
>
31.
</
action
></
action
></
action
></
action
></
action
></
intent-filter
>
32.
</
service
>
33.
</
application
>
34.
35.
</
uses-permission
></
uses-sdk
></
manifest
>