我的应用程序给出错误,即不允许BroadcastReceiver组件绑定到服务。 当短信到达时,我正在呼叫广播接收器,文本将转换为语音。 我的接收器呼叫正常。
但是我的代码给出了错误,如
致命的例外:主要 处理:texttospeech.tts.com.tts,PID:12811 java.lang.RuntimeException:无法启动接收器texttospeech.tts.com.tts.ttsBroadcast: android.content.ReceiverCallNotAllowedException: BroadcastReceiver 组件不允许绑定到服务 在android.app.ActivityThread.handleReceiver(ActivityThread.java:2618) 在android.app.ActivityThread.access $ 1700(ActivityThread.java:148) 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1369) 在android.os.Handler.dispatchMessage(Handler.java:102) 在android.os.Looper.loop(Looper.java:135) 在android.app.ActivityThread.main(ActivityThread.java:5312) at java.lang.reflect.Method.invoke(Native Method) 在java.lang.reflect.Method.invoke(Method.java:372) 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:901) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696) 引起:android.content.ReceiverCallNotAllowedException:不允许BroadcastReceiver组件绑定到服务 在android.app.ReceiverRestrictedContext.bindService(ContextImpl.java:215) 在android.speech.tts.TextToSpeech.connectToEngine(TextToSpeech.java:800) 在android.speech.tts.TextToSpeech.initTts(TextToSpeech.java:770) 在android.speech.tts.TextToSpeech。(TextToSpeech.java:723) 在android.speech.tts.TextToSpeech。(TextToSpeech.java:702) 在android.speech.tts.TextToSpeech。(TextToSpeech.java:686) 在texttospeech.tts.com.tts.ttsBroadcast.onReceive(ttsBroadcast.java:23) 在android.app.ActivityThread.handleReceiver(ActivityThread.java:2611) 在android.app.ActivityThread.access $ 1700(ActivityThread.java:148) 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1369) 在android.os.Handler.dispatchMessage(Handler.java:102) 在android.os.Looper.loop(Looper.java:135) 在android.app.ActivityThread.main(ActivityThread.java:5312) at java.lang.reflect.Method.invoke(Native Method) 在java.lang.reflect.Method.invoke(Method.java:372) 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:901) 在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);
}
}
答案 0 :(得分:3)
由于问题似乎仍处于活动状态,我将添加一些行。 首先,我认为你应该有一个服务,并从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>
。如果您只需要一个字符串,则可以简化实现。