Android学习 ——SystemUIService之RingtonePlayer分析
2017-11-21 10:40
429 查看
在android API 的media包中有三种方式可供我们选择,它们分别是Ringtone,SoundPool,MediaPlayer。
MediaPlayer 适合比较长且对时间要求不高的情况
Ringtone 铃声,闹钟,提示音等
SoundPool 适合短促且对反应速度比较高的情况(游戏音效或按键声等,音频流组合音)
RingtonePlayer.java 分析
首先看start()函数
mAsyncPlayer 是NotificationPlayer的实例。调用 setUsesWakeLock()设置休眠状态
mAudioService 音频服务。调用 setRingtonePlayer()设置播放 mCallback
在mCallback 中主要方法有
play() // 使用Ringtone播放
stop() // 使用Ringtone停止
isPlaying() // 是否正在播放
playAsync() // 使用MediaPlayer播放(NotificationPlayer 类实现)
stopAsync() // 使用MediaPlayer停止(NotificationPlayer 类实现)
当使用RingtonePlayer操作时主要使用到Client 类
private class Client implements IBinder.DeathRecipient {
private final IBinder mToken;
private final Ringtone mRingtone;
public Client(IBinder token, Uri uri, UserHandle user, int streamType) {
mToken = token;
mRingtone = new Ringtone(getContextForUser(user), false);
mRingtone.setStreamType(streamType);
mRingtone.setUri(uri);
}
@Override
public void binderDied() {
if (LOGD) Log.d(TAG, "binderDied() token=" + mToken);
synchronized (mClients) {
mClients.remove(mToken);
}
mRingtone.stop();
}
}
在Client中 new Ringtone() 并设置type 和URI
Client 实现了 DeathRecipient 死亡通知 重写 binderDied() 从 mClients 中移除对应的token 并调用 mRingtone.stop() 停止铃声播放
再看play() 函数中client 的实现
当play()函数调用后根据token从 mClients 这个Map 中获取Client ,如果为空则new Client() 并linkToDeath() 同时添加到mClients 中
最后 client.mRingtone.play(); 执行播放
MediaPlayer 适合比较长且对时间要求不高的情况
Ringtone 铃声,闹钟,提示音等
SoundPool 适合短促且对反应速度比较高的情况(游戏音效或按键声等,音频流组合音)
RingtonePlayer.java 分析
首先看start()函数
@Override public void start() { mAsyncPlayer.setUsesWakeLock(mContext); mAudioService = IAudioService.Stub.asInterface( ServiceManager.getService(Context.AUDIO_SERVICE)); try { mAudioService.setRingtonePlayer(mCallback); } catch (RemoteException e) { Log.e(TAG, "Problem registering RingtonePlayer: " + e); } }
mAsyncPlayer 是NotificationPlayer的实例。调用 setUsesWakeLock()设置休眠状态
public void setUsesWakeLock(Context context) { if (mWakeLock != null || mThread != null) { // if either of these has happened, we've already played something. // and our releases will be out of sync. throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock + " mThread=" + mThread); } PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);//屏幕关,键盘灯关,不休眠 }
mAudioService 音频服务。调用 setRingtonePlayer()设置播放 mCallback
private IRingtonePlayer mCallback = new IRingtonePlayer.Stub() { @Override public void play(IBinder token, Uri uri, int streamType) throws RemoteException { if (LOGD) { Log.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid=" + Binder.getCallingUid() + ")"); } Client client; synchronized (mClients) { client = mClients.get(token); if (client == null) { final UserHandle user = Binder.getCallingUserHandle(); client = new Client(token, uri, user, streamType); token.linkToDeath(client, 0); mClients.put(token, client); } } client.mRingtone.play(); } @Override public void stop(IBinder token) { if (LOGD) Log.d(TAG, "stop(token=" + token + ")"); Client client; synchronized (mClients) { client = mClients.remove(token); } if (client != null) { client.mToken.unlinkToDeath(client, 0); client.mRingtone.stop(); } } @Override public boolean isPlaying(IBinder token) { if (LOGD) Log.d(TAG, "isPlaying(token=" + token + ")"); Client client; synchronized (mClients) { client = mClients.get(token); } if (client != null) { return client.mRingtone.isPlaying(); } else { return false; } } @Override public void playAsync(Uri uri, UserHandle user, boolean looping, int streamType) { if (LOGD) Log.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")"); if (Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("Async playback only available from system UID."); } mAsyncPlayer.play(getContextForUser(user), uri, looping, streamType); } @Override public void stopAsync() { if (LOGD) Log.d(TAG, "stopAsync()"); if (Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("Async playback only available from system UID."); } mAsyncPlayer.stop(); } };
在mCallback 中主要方法有
play() // 使用Ringtone播放
stop() // 使用Ringtone停止
isPlaying() // 是否正在播放
playAsync() // 使用MediaPlayer播放(NotificationPlayer 类实现)
stopAsync() // 使用MediaPlayer停止(NotificationPlayer 类实现)
当使用RingtonePlayer操作时主要使用到Client 类
private class Client implements IBinder.DeathRecipient {
private final IBinder mToken;
private final Ringtone mRingtone;
public Client(IBinder token, Uri uri, UserHandle user, int streamType) {
mToken = token;
mRingtone = new Ringtone(getContextForUser(user), false);
mRingtone.setStreamType(streamType);
mRingtone.setUri(uri);
}
@Override
public void binderDied() {
if (LOGD) Log.d(TAG, "binderDied() token=" + mToken);
synchronized (mClients) {
mClients.remove(mToken);
}
mRingtone.stop();
}
}
在Client中 new Ringtone() 并设置type 和URI
Client 实现了 DeathRecipient 死亡通知 重写 binderDied() 从 mClients 中移除对应的token 并调用 mRingtone.stop() 停止铃声播放
再看play() 函数中client 的实现
当play()函数调用后根据token从 mClients 这个Map 中获取Client ,如果为空则new Client() 并linkToDeath() 同时添加到mClients 中
最后 client.mRingtone.play(); 执行播放
相关文章推荐
- Android学习——systemUIService 类分析
- Android学习——systemUIService 之PowerUI分析
- Android学习 ——SystemUIService之StorageNotification分析
- Android学习 ——SystemUIService之SettingsUI分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android学习(六)getService(String16(media.player))
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析(附码源分析)
- Android Service学习之IntentService 深入分析
- Android Binder学习(三)之defaultServiceManager()的分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析