- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我的应用程序出错,不允许 BroadcastReceiver 组件绑定(bind)到服务。当短信到达时,我正在调用广播接收器,文本将转换为语音。我的接收器正确调用。
但是我的代码给出了这样的错误
FATAL EXCEPTION: main Process: texttospeech.tts.com.tts, PID: 12811 java.lang.RuntimeException: Unable to start receiver texttospeech.tts.com.tts.ttsBroadcast: android.content.ReceiverCallNotAllowedException: BroadcastReceiver components are not allowed to bind to services at android.app.ActivityThread.handleReceiver(ActivityThread.java:2618) at android.app.ActivityThread.access$1700(ActivityThread.java:148) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1369) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5312) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696) Caused by: android.content.ReceiverCallNotAllowedException: BroadcastReceiver components are not allowed to bind to services at android.app.ReceiverRestrictedContext.bindService(ContextImpl.java:215) at android.speech.tts.TextToSpeech.connectToEngine(TextToSpeech.java:800) at android.speech.tts.TextToSpeech.initTts(TextToSpeech.java:770) at android.speech.tts.TextToSpeech.(TextToSpeech.java:723) at android.speech.tts.TextToSpeech.(TextToSpeech.java:702) at android.speech.tts.TextToSpeech.(TextToSpeech.java:686) at texttospeech.tts.com.tts.ttsBroadcast.onReceive(ttsBroadcast.java:23) at android.app.ActivityThread.handleReceiver(ActivityThread.java:2611) at android.app.ActivityThread.access$1700(ActivityThread.java:148) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1369) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5312) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
这是我的代码
ttsBroadcast.java
public class ttsBroadcast extends BroadcastReceiver implements TextToSpeech.OnInitListener {
private TextToSpeech tts;
private String msg;
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"sms recived",Toast.LENGTH_LONG).show();
tts = new TextToSpeech(context,this);
tts.speak(msg,TextToSpeech.QUEUE_FLUSH,null);
}
@Override
public void onInit(int i) {
tts.setLanguage(Locale.ENGLISH);
}
}
最佳答案
由于问题似乎仍然存在,我将添加一些行。首先我认为你应该有一个服务并从 BroadcastReceiver 调用这个服务。这可能是一个可能的实现。
广播接收器:
public class ReadMessageBroadcastReceiver extends BroadcastReceiver {
public final static String TAG = "ReadMessageBroadcastReceiver";
public ReadMessageBroadcastReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Actions.ACTION_TTS_READ_MESSAGE)) {
Log.v(TAG, "Read messages on tts received trough notification");
String[] unreadMessages = intent.getStringArrayExtra(Constants.EXTRA_UNREAD_MESSAGES);
if (unreadMessages != null) {
Log.v(TAG, "Read messages on tts trough notification received " + unreadMessages.length
+ " total messages");
String messageNumber = context.getString(R.string.notification_message_number);
ArrayList<String> allMessagesToRead = new ArrayList<>(unreadMessages.length);
for (int i = 0; i < unreadMessages.length; i++) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(messageNumber);
stringBuilder.append(" ");
stringBuilder.append(i + 1);
stringBuilder.append(" ");
stringBuilder.append(unreadMessages[i]);
stringBuilder.append(" ");
allMessagesToRead.add(stringBuilder.toString());
}
Log.d(TAG, "Texts to read loud: " + allMessagesToRead);
Intent speechIntent = new Intent(context, TextToSpeechService.class);
speechIntent.putStringArrayListExtra(TextToSpeechService.TEXT_TO_READ, allMessagesToRead);
context.startService(speechIntent);
}
}
}
}
这个广播接收器通过点击系统栏通知被调用。需要使用特定操作在 AndroidManifest.xml 上声明接收器。
<application>(all your stuff)
<receiver
android:name=".broadcastreceivers.ReadMessageBroadcastReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.example.action.ACTION_TTS_READ_MESSAGE" />
</intent-filter>
</receiver>
</application>
您还需要在应用中的某处声明此操作
public static final String ACTION_TTS_READ_MESSAGE = "com.example.action.ACTION_TTS_READ_MESSAGE";
最后您需要实现 TTSService 本身。我使用了 here 中的部分代码
public class TextToSpeechService extends Service implements TextToSpeech.OnInitListener {
public final static String TAG = "TextToSpeechService";
public static final String TEXT_TO_READ = "text";
private final String UTTERANCE_ID = "FINISHED_PLAYING";
private final int MULTI_LINE = 2;
private TextToSpeech tts;
private ArrayList<String> texts;
private boolean isInit;
private UtteranceProgressListener utteranceProgressListener = new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
}
@Override
public void onDone(String utteranceId) {
if (utteranceId.equals(UTTERANCE_ID)) {
stopSelf();
}
}
@Override
public void onError(String utteranceId) {
stopSelf();
}
};
@Override
public void onCreate() {
super.onCreate();
tts = new TextToSpeech(getApplicationContext(), this);
tts.setOnUtteranceProgressListener(utteranceProgressListener);
Log.d(TAG, "onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
texts = intent.getStringArrayListExtra(TTSService.TEXT_TO_READ);
if (isInit) {
speak();
}
return TextToSpeechService.START_NOT_STICKY;
}
@Override
public void onDestroy() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
Log.d(TAG, "onDestroy");
super.onDestroy();
}
@Override
public void onInit(int status) {
Log.d(TAG, "onInit");
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.getDefault());
if (result != TextToSpeech.LANG_MISSING_DATA
&& result != TextToSpeech.LANG_NOT_SUPPORTED) {
speak();
isInit = true;
}
}
}
private void speak() {
if (tts != null) {
// Speak with 3 parameters deprecated but necessary on pre 21 version codes
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// This is a single message
String utteranceId = null;
if (texts.size() < MULTI_LINE) {
// If is a single message this needs to be the last one
utteranceId = UTTERANCE_ID;
}
tts.speak(texts.get(0), TextToSpeech.QUEUE_FLUSH, null, utteranceId);
if (texts.size() >= MULTI_LINE) {
for (int i = 1; i < texts.size(); i++) {
if (texts.size() - 1 == i) {
// If is the last message add the id
utteranceId = UTTERANCE_ID;
}
tts.speak(texts.get(i), TextToSpeech.QUEUE_ADD, null, utteranceId);
}
}
} else {
HashMap<String, String> myHashAlarm = null;
if (texts.size() < MULTI_LINE) {
myHashAlarm = new HashMap<>();
myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, UTTERANCE_ID);
}
tts.speak(texts.get(0), TextToSpeech.QUEUE_FLUSH, myHashAlarm);
if (texts.size() >= MULTI_LINE) {
for (int i = 1; i < texts.size(); i++) {
if (texts.size() - 1 == i) {
// If is the last message add the id
myHashAlarm = new HashMap<>();
myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
UTTERANCE_ID);
}
tts.speak(texts.get(i), TextToSpeech.QUEUE_ADD, myHashAlarm);
}
}
}
}
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
最后别忘了在AndroidManifest.xml文件上注册你的服务
<service
android:name=".services.TextToSpeechService"
android:exported="false"/>
缺点,我会说启动时间有点长(一秒或两秒之间,具体取决于手机)。好的一面是,您不会一直运行 tts 并按需启动和停止。实现了一些逻辑来查明是否是系列中的最后一条消息,因为在 Intent 上传递给服务的参数是 ArrayList<String>
。 .如果你只需要一个字符串,你可以简化实现。
关于android - 广播接收器组件不允许绑定(bind)服务。如何从广播接收器开始文本到语音?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31915672/
我不知道该怎么做... function f1() { var x = 10; function f2(fx) { var x; x = 6;
早期绑定(bind)和后期绑定(bind)有什么区别? 最佳答案 简短的回答是,早期(或静态)绑定(bind)是指编译时绑定(bind),后期(或动态)绑定(bind)是指运行时绑定(bind)(例如
如何在 SwiftUI View 上使用 Binding(get: { }, set: { }) 自定义绑定(bind)与 @Binding 属性。我已成功使用此自定义绑定(bind)与 @State
我经常发现自己遇到问题,即控件的两个(相关)值被更新,并且两者都会触发昂贵的操作,或者控件可能会暂时处于不一致的状态。 例如,考虑一个数据绑定(bind),其中两个值 (x,y) 相互减去,最终结果用
我想通过我的 ViewModel 控制我的一个窗口的高度和宽度。 这看起来很简单。 但没有。它不起作用。 它检查 ViewModel 的 Width但不是 Height . 奇怪的是,如果我切换 W
UI5中一次性绑定(bind)和单向绑定(bind)有什么区别? 是否有任何用户特定的用例我会使用它们? 我无法从文档中获得太多信息。 最佳答案 单程 它的作用:单向数据流。模型数据的变化(例如通过
(define make (lambda (x) (lambda (y) (cons x (list y))))) (let ((x 7) (p (make 4))) (cons
尽管我或多或少地了解什么是语言绑定(bind),但我很难理解它们是如何工作的。 例如,谁能解释一下如何为 WinAPI 制作 Java 绑定(bind)? 最佳答案 如果您搜索 Foreign Fun
谁能解释为什么我可以重新绑定(bind)列表但不能+? (binding [list vector] (list 1 3)) (binding [list +] (list 1 3)) (bi
我真的很喜欢 Caliburn 和命名约定绑定(bind),我很惊讶 可见性与“CanNAME”约定用于保护 Action 的方式不同。 据我所知, BooleanToVisibilityConver
我了解动态绑定(bind)的实现方式以及静态绑定(bind)和动态绑定(bind)之间的区别,但我只是无法理解动态绑定(bind)的定义。基本上它是一种运行时绑定(bind)类型。 最佳答案 基本上,
http://jsfiddle.net/3NRsd/ var foo = $("div").bind("click", function() { $("div").animate({"hei
这个问题我快疯了...我有一个用户控件,它有一个用于插入操作的 FormView 和一个用于所有其他操作的 GridView。 在这两个控件中,我都有一个 DropDownList,如下所示: '
我有一个绑定(bind)到 ListBox 的地址的 ObservableCollection。然后在 ItemTemplate 中,我使用 {Binding .} 绑定(bind)到当前地址记录。这
如果我有以下简单的 js/knockout 代码: .js( View 模型): var image = ko.observable('http://placehold.it/300x150'); 看
我正在 aurelia 上开发一个自定义属性,让用户在输入文本区域时从列表中进行选择。例如,用法将是这样的: 正如您可能注意到的,auto-complete是属性。现在,当我想显示提示时,我想在自定
我正在使用 EventEmitter2作为我的应用程序内部的消息总线。现在我需要绑定(bind)和取消绑定(bind)一些事件处理程序。因为我也希望他们bind将它们添加到给定的上下文中,我最终得到以
我有以下函数调用: $(".selector").on("click", callback.bind(this, param1, param2)); 在我的回调函数中,我想使用绑定(bind)的 th
我目前正在试验新的编译绑定(bind),并且(再次)达到了我在拼图中遗漏了一个小问题:为什么我必须调用 Bindings.Update?直到现在,我还认为实现 INotifyPropertyChang
我正在阅读一本关于编写 JavaScript 框架的书,并找到了这段代码。但是我不明白它是如何工作的,尤其是 bind.bind 的用法?有人知道吗? var bind = Function.prot
我是一名优秀的程序员,十分优秀!