一、权限声明
播放内部URI指定资源:
三、处理异步差错,当进行异步资源加载时,可能出现一些异常,此时可以实现MediaPlayer.OnErrorListener接口,并在
onError()方法中进行差错处理,如:
四、当设备息屏一段时间后,CPU,WiFi硬件等会停止工作,为使你的app能够在这种条件下运行,应该使用"wake locks","wake lock"就是告诉系统即使手机息屏了,你的
注:记得在不需要服务的时候,停止前台设置:stopForeground(true);
八、播放本地音乐:
注:id值对应android.provider.MediaStore.Audio.Media._ID列。
如果播放的音频流来自网络,需声明权限:
<uses-permission android:name="android.permission.INTERNET" />
如果想让播放期间屏幕不息屏,可以调用MediaPlayer.setScreenOnWhilePlaying() 或
MediaPlayer.setWakeMode()方法,需要权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
如播放本地row文件夹下的音频资源:
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you
注:此处无需调用prepare()方法。
播放内部URI指定资源:
Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();
播放外部URL指定资源:
String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
注:prepare()方法需要做一些资源解码操作,所以应避免在主线程中调用。可以选择调用prepareAsync()方法,该方法
进行异步的音频解码,同时给MediaPlayer设置一个MediaPlayer.OnPreparedListener,如:
public class MyService extends Service implements MediaPlayer.OnPreparedListener {
private static final String ACTION_PLAY = "com.example.action.PLAY";
MediaPlayer mMediaPlayer = null;
public int onStartCommand(Intent intent, int flags, int startId) {
...
if (intent.getAction().equals(ACTION_PLAY)) {
mMediaPlayer = ... // initialize it here
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.prepareAsync(); // prepare async to not block main thread
}
}
/** Called when MediaPlayer is ready */
public void onPrepared(MediaPlayer player) {
player.start();
}
}
三、处理异步差错,当进行异步资源加载时,可能出现一些异常,此时可以实现MediaPlayer.OnErrorListener接口,并在
onError()方法中进行差错处理,如:
public class MyService extends Service implements MediaPlayer.OnErrorListener {
MediaPlayer mMediaPlayer;
public void initMediaPlayer() {
// ...initialize the MediaPlayer here...
mMediaPlayer.setOnErrorListener(this);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// ... react appropriately ...
// The MediaPlayer has moved to the Error state, must be reset!
}
}
注:当出现差错时,MediaPlayer进入Error状态。
四、当设备息屏一段时间后,CPU,WiFi硬件等会停止工作,为使你的app能够在这种条件下运行,应该使用"wake locks","wake lock"就是告诉系统即使手机息屏了,你的
app仍需要使用一些硬件特性,如WiFi,CPU等。这种特征应该合理使用,因为会增加应用耗电量。可以通过调用setWakeMode()方法,如:
mMediaPlayer = new MediaPlayer();
// ... other initialization here ...
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
上述只保证了CPU的可用性,如果你的app播放的是网络资源,应该同时保留WiFi特性,如:
WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();
注:当退出播放时,记得释放资源:wifiLock.release();
五、使用前台服务:用户可以明显的意识到播放音乐的服务在运行,因此该服务应该具有较高的优先级,不会轻易的被杀死,所以应该设置成前台服务,要想升级为前台服务,你必须在设备通知栏创建一个通知,然后调用startForeground()方法,并且当用户点击通知时,跳转到程序界面与用户交互,如:
String songName;
// assign the song name to songName
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
new Intent(getApplicationContext(), MainActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification();
notification.tickerText = text;
notification.icon = R.drawable.play0;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample",
"Playing: " + songName, pi);
startForeground(NOTIFICATION_ID, notification);
注:记得在不需要服务的时候,停止前台设置:stopForeground(true);
六、处理音频焦点的改变:
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
// resume playback
if (mMediaPlayer == null) initMediaPlayer();
else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
mMediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
// Lost focus for an unbounded amount of time: stop playback and release media player
if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// Lost focus for a short time, but we have to stop
// playback. We don't release the media player because playback
// is likely to resume
if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// Lost focus for a short time, but it's ok to keep playing
// at an attenuated level
if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
break;
}
}
注:需要Android系统版本2.2(API Level 8)。
七、使用内容解析者获取本地音乐:
ContentResolver contentResolver = getContentResolver();
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor == null) {
// query failed, handle error.
} else if (!cursor.moveToFirst()) {
// no media on the device
} else {
int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
do {
long thisId = cursor.getLong(idColumn);
String thisTitle = cursor.getString(titleColumn);
// ...process entry...
} while (cursor.moveToNext());
}
八、播放本地音乐:
long id = /* retrieve it from somewhere */;
Uri contentUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(getApplicationContext(), contentUri);
注:id值对应android.provider.MediaStore.Audio.Media._ID列。