Android学习 ——SystemUIService之RingtonePlayer分析
来源:互联网 发布:矩阵奖金制度 编辑:程序博客网 时间:2024/06/03 07:05
在android API 的media包中有三种方式可供我们选择,它们分别是Ringtone,SoundPool,MediaPlayer。
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(); 执行播放
阅读全文
0 0
- Android学习 ——SystemUIService之RingtonePlayer分析
- Android学习——systemUIService 之PowerUI分析
- Android学习 ——SystemUIService之SettingsUI分析
- Android学习 ——SystemUIService之StorageNotification分析
- Android学习——systemUIService 类分析
- SystemUI源码分析一(SystemUIService的启动)
- SystemUI RingtonePlayer
- android安全学习之6—signapk分析
- 【android学习之十二】——SDK实例NotePad 分析1
- 【android学习之十三】——SDK实例NotePad 分析2
- Android学习笔记之实现一个文档查看器(一)——应用分析
- 李兴华—JAVA学习之我见 分析!!!
- android 学习之---listview adapter分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- Android Service学习之IntentService 深入分析
- QT设置centralWidget布局
- Jenkins 打包出现You have not accepted the license agreements of the following SDK components: 错误的解决办法
- 谷歌和百度轨迹的详解
- Win32字符串处理函数
- java poi导出excel是文件名字符转译问题
- Android学习 ——SystemUIService之RingtonePlayer分析
- ERROR 1366 (HY000): Incorrect string value: '\xD6\xD0\xCE\xC4' for column XXX at row 1
- windows远程连接服务器中的jupyter notebook
- CentOS6.8 操作防火墙
- Hadoop运维配置
- vb读取excel中的数据并在窗体上显示
- 如何实现1080P延迟低于500ms的实时超清直播传输技术
- 剑网三的宏语法
- golang reflection