2016-07-04 4 views
1

Ich habe einen Dienst, der eine C-Funktion über JNI aufruft. Diese Funktion erzeugt dann eine pthread und verbindet sie mit der JVM. Ich rufe eine Java-Methode von dieser pthread, die eine Toast Benachrichtigung veröffentlichen sollte. Leider, sobald die Toast Benachrichtigung aufgerufen wird, bekomme ich eine Nullzeiger Ausnahme.Android - Null-Zeiger auf Toast Anruf

Hier ist die Methode, die den Toast Anruf in meiner Dienst-Klasse verarbeitet:

public void showToast(final String msg) { 
    final Context MyContext = this; 
    Handler h = new Handler(MyContext.getMainLooper()); 
    h.post(new Runnable() { 
     @Override 
     public void run() { 
      Toast myToast = Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT); 
      myToast.show(); 
     } 
    }); 
} 

Was die Null-Zeiger Ausnahme verursacht sein könnte, und wie kann ich es beheben?

Wird versucht, den Kontext aus der C-Funktion zu nehmen? Hier

ist die Fehlermeldung

W/dalvikvm(4010): JNI WARNING: JNI method called with exception pending 
W/dalvikvm(4010):    in Ldalvik/system/NativeStart;.run:()V (CallVoidMethod) 
W/dalvikvm(4010): Pending exception is: 
I/dalvikvm(4010): java.lang.NullPointerException: 
I/dalvikvm(4010): at android.content.ContextWrapper.getMainLooper(ContextWrapper.java:104) 

Mit getApplicationContext:

I/dalvikvm(6242): java.lang.NullPointerException: 
I/dalvikvm(6242): at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:109) 
+0

Können Sie die genaue Fehlermeldung posten? –

+2

Haben Sie versucht, getApplicationContext() anstelle von 'this' zu verwenden? –

+0

Ja.Sie sollten getApplicationContext() als @ ρяσѕρєяK verwenden. –

Antwort

0

Das Problem ist, dass, wenn von einem C-Thread über JNI aufgerufen werden, wir den Kontext nicht abrufen können. Wir müssen den Kontext aus dem Dienstthread selbst abrufen. Um dies zu tun:

public class MyService extends Service{ 
    private static Context MyContext; /* get context to use when displaying toast from JNI*/ 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    public void onDestroy() { 
    } 

    @Override 
    public int onStartCommand(Intent intent,int flags, int startid){ 
     MyContext = getApplicationContext(); 
     // do what you need to 
     return START_STICKY; 
    } 

    public void showToast(final String msg) { 
     Handler h = new Handler(MyContext.getMainLooper()); 
     h.post(new Runnable() { 
      @Override 
      public void run() { 
      Toast myToast = Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT); 
      myToast.show(); 
      } 
     }); 
    } 
} 

Auf diese Weise haben wir einen statischen Verweis auf den richtigen Kontext, dass wir mit unserem Anruf von JNI zugreifen können

0

Versuchen Sie folgendes:

Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT).show(); 

Das ist, wie ich habe es immer getan, und es wird nur zum Absturz bringen, wenn msg ist nicht null.

Versuchen Sie das, und wenn das nicht funktioniert, prüfen Sie, ob msg vorher null ist. Du könntest so etwas tun.

Übrigens habe ich vergessen zu berücksichtigen, dass Sie nicht bekommen, was das bedeutet.

Wenn Sie die Toast-Nachricht erhalten Variable war null, wenn Sie Ihre App ausführen. Das heißt, wo immer der Methodenaufruf herkommt, wird eine leere Zeichenfolge gesendet. Sie müssen den Methodenaufruf finden und herausfinden, warum die übergebene Variable null ist.

Zum Beispiel suchen Ihr Projekt für diese showToast (

Suche nach diesem Anruf, so oft, wie es gemacht wird. Wenn es mehr als ein Anruf Sie bei jedem Aufruf der Zeichenfolge überprüfen können, bevor Sie es machen, und Wenn es null ist, können Sie eine Zeichenfolge hinzufügen, die Ihnen hilft festzustellen, woher der Anruf kam. Sie können den oben angegebenen Code vor jedem Anruf verwenden, aber stattdessen die gesendete Variable überprüfen und dann gleich machen "Anruf von xxxxx ist null." "xxxx ist der Ort, an dem der Anruf getätigt wird. Dann können Sie herausfinden, warum die gesendete Variable null ist.

versuchen Sie auch, was ich mit getApplicationContext() anstelle von MyContext

+0

Es ist nicht die Zeichenfolge, die null ist, sondern der Kontext –