2015-01-15 57 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 
    } 

} 
相關問題