2015-01-15 56 views
1

我在获取Exception时试图让语音在到达时说出短信文本,它给了我一个NullPointerException,我似乎可以弄清楚是它想让我去做或错误在哪里。什么可能是我的问题?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); 
} 
} 

TTS.java

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); 
    } 
} 
} 

AndroidManifest.xml中

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.fegeley.handsfreetexting" > 

<application 
    android:allowBackup="true" 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme"> 
    <activity 
     android:name=".MainActivity" 
     android:label="@string/app_name" 
     android:screenOrientation="portrait" > 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 

    <receiver android:name="com.fegeley.handsfreetexting.TTS"> 
     <intent-filter> 
      <action android:name="android.provider.Telephony.SMS_RECEIVED"/> 
     </intent-filter> 
    </receiver> 
</application> 

<uses-permission android:name="android.permission.READ_SMS"/> 
<uses-permission android:name="android.permission.RECEIVE_SMS"/> 
<uses-permission android:name="android.permission.READ_CONTACTS"/> 

</manifest> 

回答

0

我不知道库,但堆栈跟踪告诉了NullPointerException异常的发生TTS.java在线52:

str += "SMS from " + msgs[i].getOriginatingAddress(); 

这意味着封邮件[i]是null虽然它之前被分配了一行:

msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); 

因此,createFromPdu返回null。 因为createFromPdu似乎是一个框架方法,所以从包中检索到的pdus [i]很可能是空的。 请确保您在阅读之前已将“pdus”写入捆绑包。

问候, 最大

+0

创建service类,其中一个TTS对象实例化和启动服务其实,我只是意识到了这一点,有在TTS.java中有16个额外的行,其中进口是和我复制到问题时错过了,所以52行实际上是16行。我将编辑该问题以解决该问题。 – 2015-01-15 18:12:30

+0

哦,我没有看到querstion中的不一致,抱歉。 AADTechnical的解决方案可能就是它。 – mxg 2015-01-15 18:30:14

1

你的 “TTS” 在空上线52的对象。

您似乎正在将它初始化为BroadcastReceiver的“onCreate()”。

protected void onCreate(Bundle savedInstanceState){ 
    tts = new TextToSpeech(context, 
      new TextToSpeech.OnInitListener() 

注意,广播接收器类没有任何的onCreate()活动样式的回调方法。

我想你认为系统会调用BroadcastReceiver类的onCreate()。对于BroadcastReceiver来说并非如此。

可以初始化 “TTS” 对象的onReceive()如下:

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

删除行:tts.giveContext(this);地址:TTS.giveContext(getApplicationContext());

此更改是为了防止ReceiverCallNotAllowedException

+0

应用您建议的内容后,我测试了代码,当应用程序仍然打开时收到短信时,它给了我一个错误,说'发言失败:不绑定到TTS引擎' 但是,当我收到短信被关闭时,它仍表示 – 2015-01-15 18:59:08

+0

'在TTS.java:45的NullPointerException',这是 '公共无效的onReceive(上下文CONTEXT1,意图意图){ (线45)TTS =新文字转语音(上下文, 新TextToSpeech.OnInitListener() { @Override 公共无效的OnInit(INT状态){ 如果(状态= TextToSpeech.ERROR!){ tts.setLanguage(Locale.US); } } });' – 2015-01-15 19:00:15

+0

1.当应用程序关闭并收到SMS时,TTS.giveContext(getApplicationContext())不能为您提供上下文(因为应用程序可能会被终止)。您可以使用以下代码保存App上下文:public class MyApp extends Application { private static Context _appContext; @Override public void onCreate() { super.onCreate(); _appContext = this; } public static Context getAppContext() { return _appContext; } } – AADProgramming 2015-01-16 13:05:43

1

您不能在广播接收器中实例化TextToSpeech对象。您的代码

speakText(str); 

onReceive末的文本到语音呼叫onInit之前这样你说话失败不会绑定到TTS引擎被调用。
当SMS到达时,系统按清单中的定义实例化一个TTS对象。它与你在MainActivity中实例化的tts无关。您的应用程序打开时
你没有得到NPE因为static声明在TTScontext,你在你的MainActivity实例化一个对象,从而context不为空,因此tts对象,你在onCreate声明或onReceiveAADTechnical建议不为空。
当你的应用是接近MainActivity宣布tts对象从而破坏了context成员在任何TTS对象发起,而无需人叫giveContext woud为空。并且giveContext在实例化TTS对象时不会被系统调用,因此context为空,并且tts对象在该类中实例化为空,并且您获得NPE

你需要做的是在onReceive

public class SMSService extends Service 
{ 
    // instantiate a TTS object in this class 
} 

public class TTS extends BroadcastReceiver 
{ 
    @Override 
    public void onReceive(Context context, Intent intent) 
    { 
     // get your SMS message 
     // and then start the SMSService passing the message in the intent bundle 
    } 

} 
相关问题