简介
在日常生活中我们常遇到一些腾不开手操作手机的时候,有时手机离自己还有一段距离,如:
- 做饭
- 洗澡
- 收拾
- 健身
这时当微信或者QQ有消息却不知道是否应该放下手中的任务去查看是谁发来的什么消息,如果能用语音播放消息并且通过语音进行回复就可以带来极大的方便。
语音播放的实现
方便起见,通过NotificationListenerService
从系统通知中抓取微信和QQ的信息。
实现NotificationListenerService
NotificationListenerService
在API level 18中加入,当有新的通知、现有通知移除和通知的排序发生变化时,系统会唤起该服务,通过实现该类可以捕获微信和QQ的信息。
该类中的onNotificationPosted
回调函数会传递一个StatusBarNotification
数据结构,通过该结构的getPackageName
方法获取发送该通知的包名,通过getNotification
方法获取通知的标题和内容。
...
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
...
public class NotificationListener extends NotificationListenerService{
...
public void onNotificationPosted(StatusBarNotification sbn) {
super.onNotificationPosted(sbn);
Bundle bundle = sbn.getNotification().extras;
String notificationPkg = sbn.getPackageName();
String title=bundle.getString(Notification.EXTRA_TITLE);
String text= bundle.getString(Notification.EXTRA_TEXT);
...
}
...
}
将捕获到的信息通过广播传递给主程序:
Intent i= new Intent("com.hit.lszt.getnote.receive");
i.putExtra("POSTED",false);
i.putExtra("PACKAGENAME",notificationPkg);
i.putExtra("TITLE",title);
i.putExtra("TEXT",text);
sendBroadcast(i);
此外,还需要在AndroidManifest.xml
中声明该服务和BIND_NOTIFICATION_LISTENER_SERVICE
权限:
<service
android:name="com.hit.lszt.getnote.NotificationListener"
android:label="@string/service_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
基于百度语音的微信&QQ信息语音播放的实现
百度离线语音合成
注册成为百度语音的开发者,创建应用并为其开通离线语音合成服务,下载安卓离在线融合SDK。
将SDK中的data
拷贝到app/libs
中,data
拷贝到app/src/main/assets
中。
其中,so库需要在在build.gradle
中添加如下代码导入:
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
初始化百度语音的代码可以在SDK中的samples
中找到,这里只提几个关键的代码:
// 请替换为语音开发者平台注册应用得到的APPID
this.mSpeechSynthesizer.setAppId("APPID");
// 请替换为语音开发者平台注册应用得到的apikey和secretkey
this.mSpeechSynthesizer.setApiKey("apikey", "secretkey");
// 设置Mix模式的合成策略
this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI);
百度提供的合成器参数设置说明:
参数名称 | 默认值 | 备注 |
---|---|---|
PARAM_MIX_MODE | MIX_MODE_DEFAULT | MIX_MODE_DEFAULT(mix模式下,wifi使用在线合成,非wifi使用离线合成) |
MIX_MODE_HIGH_SPEED_NETWORK(mix模式下,wifi,4G,3G使用在线合成,其他使用离线合成) | ||
MIX_MODE_HIGH_SPEED_SYNTHESIZE(mix模式下,在线返回速度如果慢(超时,一般为1.2秒)直接切换离线,适用于网络环境较差的情况) | ||
MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI(mix模式下,仅wifi使用在线合成,返回速度如果慢(超时,一般为1.2秒)直接切换离线,适用于仅WIFI网络环境较差的情况) |
但是我在自己手机(Huawei P9)上测试的时候,MIX_MODE_DEFAULT
模式只在wifi下进行语音合成,而使用MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI
则工作正常,非wifi环境下使用离线合成。
初始化成功后,通过调用
public int speak(String text)
合成并播放文本。
实现BroadcastReceiver
实现一个BroadcastReceiver接收刚才实现的NotificationListenerService
发出的广播信息:
private class NotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getBooleanExtra("POSTED", true)) {
String pkg = intent.getStringExtra("PACKAGENAME");
if (pkg.contains("tencent")) {
String TEXT=intent.getStringExtra("TEXT");
String TITLE=intent.getStringExtra("TITLE");
if(!TEXT.contains(TITLE)){
mSpeechSynthesizer.speak(intent.getStringExtra("TITLE")+"说"+intent.getStringExtra("TEXT"));
}
else {
mSpeechSynthesizer.speak(intent.getStringExtra("TEXT"));
}
}
}
}
}
如果包名中包含tencent
字段则判断为微信或者QQ的信息,通过百度语音合成引擎进行播放。
总结
本程序可以实现语音播放微信和QQ信息,界面图如下:
使用方式为点击ACCESS按钮并授权,如果要取消语音播放则取消授权。
目前程序不论是界面还是操作方式都有些简陋,但是不影响正常使用。
源代码&下载
https://github.com/shibajiu/ReadWeChatNotifications
参考
- NotificationListenerService Implementation
- https://github.com/kpbird/NotificationListenerService-Example
- NotificationListenerService的那些事儿
- https://github.com/lendylongli/qianghongbao
TODO
- 过滤名单
- 语音发送信息