我的应用程序出现错误,表明BroadcastReceiver组件不允许绑定到服务。
短信到达时,我正在呼叫广播接收器,文本将转换为语音。
我的收款人打了电话。
但是我的代码给出了错误
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);
}
}
您能够解决此问题吗? 面临同样的问题。
似乎在stackoverflow.com/a/5646770/1651940上得到了回答
由于问题似乎仍然存在,因此我将添加一些行。
首先,我认为您应该有一个服务,并从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 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上声明一个特定的动作。
(all your stuff)
android:name=".broadcastreceivers.ReadMessageBroadcastReceiver"
android:enabled="true">
您还需要在您的应用中的某处声明此操作
public static final String ACTION_TTS_READ_MESSAGE ="com.example.action.ACTION_TTS_READ_MESSAGE";
最后,您需要实现TTSService本身。我从这里使用了部分代码
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 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 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文件中注册服务
android:name=".services.TextToSpeechService"
android:exported="false"/>
不利的一面是,我需要花太多时间才能开始(一秒到两秒之间,具体取决于手机)。好的一面,您的tts不会一直按需运行。由于在Intent上传递给服务的参数是ArrayList,因此实现了一些逻辑以找出是否是序列中的最后一条消息。如果只需要一个字符串,则可以简化实现。