Java NullPointerException在尝试使用文字对语音大声说出文字信息时发生
当我试图让文本到语音在到达时说sms文本时,我遇到了一个Java NullPointerException在尝试使用文字对语音大声说出文字信息时发生,java,android,nullpointerexception,sms,text-to-speech,Java,Android,Nullpointerexception,Sms,Text To Speech,当我试图让文本到语音在到达时说sms文本时,我遇到了一个异常,它给了我一个NullPointerException,我似乎可以弄清楚它是想让我做什么,或者错误到底在哪里。我可能有什么问题 错误日志 java.lang.RuntimeException: Unable to start receiver com.fegeley.handsfreetexting.TTS: java.lang.NullPointerException at android.app.ActivityTh
异常,它给了我一个NullPointerException
,我似乎可以弄清楚它是想让我做什么,或者错误到底在哪里。我可能有什么问题
错误日志
java.lang.RuntimeException: Unable to start receiver com.fegeley.handsfreetexting.TTS: java.lang.NullPointerException
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2677)
at android.app.ActivityThread.access$1800(ActivityThread.java:170)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1380)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5635)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.fegeley.handsfreetexting.TTS.speakText(TTS.java:52)
at com.fegeley.handsfreetexting.TTS.onReceive(TTS.java:74)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2669)
at android.app.ActivityThread.access$1800(ActivityThread.java:170)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1380)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5635)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
MainActivity.java
package com.fegeley.handsfreetexting;
import android.media.AudioManager;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.view.View;
import android.widget.Toast;
import java.util.HashMap;
import java.util.Locale;
public class MainActivity extends ActionBarActivity {
TTS tts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tts = new TTS();
tts.giveContext(this);
}
@Override
public void onPause(){
tts.onPause();
super.onPause();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
package com.fegeley.handsfreetexting;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.telephony.SmsMessage;
import java.util.HashMap;
import java.util.Locale;
/**
* Created by Kayne on 1/14/2015.
*/
public class TTS extends BroadcastReceiver {
private static Context context;
TextToSpeech tts;
public TTS(){
}
public static void giveContext(Context con){
context = con;
}
protected void onCreate(Bundle savedInstanceState){
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
tts.setLanguage(Locale.US);
}
}
});
}
public void onPause(){
if(tts !=null){
tts.stop();
tts.shutdown();
}
}
public void speakText(String toSpeak){
HashMap<String, String> hash = new HashMap<String,String>();
hash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
String.valueOf(AudioManager.STREAM_NOTIFICATION));
tts.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, hash);
}
@Override
public void onReceive(Context context, Intent intent) {
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
//if (bundle != null)
//{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
//}
//---display the new SMS message---
speakText(str);
}
}
}
TTS.java
package com.fegeley.handsfreetexting;
import android.media.AudioManager;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.view.View;
import android.widget.Toast;
import java.util.HashMap;
import java.util.Locale;
public class MainActivity extends ActionBarActivity {
TTS tts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tts = new TTS();
tts.giveContext(this);
}
@Override
public void onPause(){
tts.onPause();
super.onPause();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
package com.fegeley.handsfreetexting;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.telephony.SmsMessage;
import java.util.HashMap;
import java.util.Locale;
/**
* Created by Kayne on 1/14/2015.
*/
public class TTS extends BroadcastReceiver {
private static Context context;
TextToSpeech tts;
public TTS(){
}
public static void giveContext(Context con){
context = con;
}
protected void onCreate(Bundle savedInstanceState){
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
tts.setLanguage(Locale.US);
}
}
});
}
public void onPause(){
if(tts !=null){
tts.stop();
tts.shutdown();
}
}
public void speakText(String toSpeak){
HashMap<String, String> hash = new HashMap<String,String>();
hash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
String.valueOf(AudioManager.STREAM_NOTIFICATION));
tts.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, hash);
}
@Override
public void onReceive(Context context, Intent intent) {
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
//if (bundle != null)
//{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
//}
//---display the new SMS message---
speakText(str);
}
}
}
package com.fegeley.handsfreetexting;
导入android.content.BroadcastReceiver;
导入android.content.Context;
导入android.content.Intent;
导入android.media.AudioManager;
导入android.os.Bundle;
导入android.speech.tts.TextToSpeech;
导入android.telephony.sms消息;
导入java.util.HashMap;
导入java.util.Locale;
/**
*由Kayne于2015年1月14日创建。
*/
公共类TTS扩展广播接收机{
私有静态语境;
texttospeechtts;
公共TTS(){
}
公共静态上下文(上下文con){
上下文=con;
}
创建时受保护的void(Bundle savedInstanceState){
tts=新文本到语音(上下文,
新的TextToSpeech.OnInitListener(){
@凌驾
公共无效onInit(int状态){
if(状态!=TextToSpeech.ERROR){
tts.setLanguage(Locale.US);
}
}
});
}
公共无效暂停(){
如果(tts!=null){
tts.stop();
tts.shutdown();
}
}
公共void speakText(字符串到speak){
HashMap hash=新的HashMap();
hash.put(TextToSpeech.Engine.KEY_PARAM_流,
字符串.valueOf(AudioManager.STREAM_通知));
tts.speak(toSpeak、TextToSpeech.QUEUE\u FLUSH、hash);
}
@凌驾
公共void onReceive(上下文、意图){
//---获取传入的SMS消息---
Bundle=intent.getExtras();
SmsMessage[]msgs=null;
字符串str=“”;
//if(bundle!=null)
//{
//---检索收到的SMS消息---
Object[]pdus=(Object[])bundle.get(“pdus”);
msgs=新SMS消息[PDU.length];
对于(int i=0;i我不知道库,但堆栈跟踪告诉我们在TTS.java的第52行出现了NullPointerException:
str += "SMS from " + msgs[i].getOriginatingAddress();
这意味着msgs[i]为空,尽管在此之前它被分配了一行:
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
因此createFromPdu返回null。
由于createFromPdu似乎是一个框架方法,因此从bundle中检索到的PDU[i]很可能为空。
在阅读之前,请确保您已将“PDU”写入包中
问候,,
Max第52行的“tts”对象为空
您似乎正在BroadcastReceiver的“onCreate()”中初始化它
protected void onCreate(Bundle savedInstanceState){
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener()
请注意,BroadcastReceiver类没有任何onCreate()活动样式的回调方法。
我猜您假设系统将调用BroadcastReceiver类的onCreate(),但对于BroadcastReceiver则不是这样
protected void onCreate(Bundle savedInstanceState){
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener()
您可以在onReceive()中初始化“tts”对象,如下所示:
public void onReceive(Context context1, Intent intent) {
//---get the SMS message passed in---
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
tts.setLanguage(Locale.US);
}
}
});
另外,更改MainActivity.java中的以下行
package com.fegeley.handsfreetexting;
import android.media.AudioManager;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.view.View;
import android.widget.Toast;
import java.util.HashMap;
import java.util.Locale;
public class MainActivity extends ActionBarActivity {
TTS tts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tts = new TTS();
tts.giveContext(this);
}
@Override
public void onPause(){
tts.onPause();
super.onPause();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
package com.fegeley.handsfreetexting;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.telephony.SmsMessage;
import java.util.HashMap;
import java.util.Locale;
/**
* Created by Kayne on 1/14/2015.
*/
public class TTS extends BroadcastReceiver {
private static Context context;
TextToSpeech tts;
public TTS(){
}
public static void giveContext(Context con){
context = con;
}
protected void onCreate(Bundle savedInstanceState){
tts = new TextToSpeech(context,
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
tts.setLanguage(Locale.US);
}
}
});
}
public void onPause(){
if(tts !=null){
tts.stop();
tts.shutdown();
}
}
public void speakText(String toSpeak){
HashMap<String, String> hash = new HashMap<String,String>();
hash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
String.valueOf(AudioManager.STREAM_NOTIFICATION));
tts.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, hash);
}
@Override
public void onReceive(Context context, Intent intent) {
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
//if (bundle != null)
//{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
//}
//---display the new SMS message---
speakText(str);
}
}
}
删除:tts.giveContext(this);
Add:tts.giveContext(getApplicationContext());
此更改是为了防止receiver CallNotAllowedException您不能在广播接收器中实例化TextToSpeech对象。您的代码
speakText(str);
在onReceive
的末尾,在文本到语音的调用onInit
之前,会调用onReceive,因此您会得到speak failed,而不是绑定到TTS引擎。
当SMS到达时,系统将实例化清单中定义的TTS对象。它与您在MainActivity中实例化的TTS无关。
当你的应用程序打开时,你没有得到NPE
,因为TTS
类中static
声明context
,你在main活动中实例化了一个对象,因此context
不是空的,因此你在onCreate
或中声明的TTS
对象>onReceive
asAADTechnical建议值不为空。
当您的应用程序关闭时,在main活动中声明的tts
对象将被销毁,因此任何tts
对象中的context
成员将在不进行任何调用的情况下启动giveContext
将为空。并且当系统实例化tts
对象时,将不会调用giveContext
因此,objectcontext
为null,类中实例化的tts
对象为null,您将得到NPE
您需要做的是创建一个service
类,在该类中实例化一个TTS对象,并在onReceive
public class SMSService extends Service
{
// instantiate a TTS object in this class
}
及
事实上,我刚刚意识到,TTS.java中有16行额外的导入行,我在复制到问题时遗漏了它们,所以第52行实际上是16行。我将编辑问题以解决这个问题。哦,我没有看到查询中的不一致性,抱歉。AADTechnical的解决方案可能就是它。在应用了您的建议后,我测试了代码,当我在应用程序仍然打开的情况下收到短信时,它会给我一个错误,说“speak failed:not bound to TTS engine”,但当我在应用程序关闭的情况下收到短信时,它仍然会说“NullPointerException at TTS.java:45”,这是public void onReceive(上下文上下文1,意图){(第45行)tts=new TextToSpeech(上下文,new TextToSpeech.OnInitListener(){@Override public void onInit(int status){if(status!=TextToSpeech.ERROR){tts.setLanguage(Locale.US);}}}};
1.当关闭应用程序并收到短信时,TTS.giveContext(getApplicationContext())无法为您提供上下文(因为应用程序可能会被终止)。您可以