2016-03-30 8 views
1

Ich arbeite an einer Android-Anwendung, in der ich eine Verbindung mit einem Dienst herstelle und auf das Objekt darin zugreifen möchte. Derselbe Mechanismus funktioniert für eine Klasse und für andere mit einer NPE. Ich weiß nicht warum und was schief läuft. Jede Hilfe wäre nett.Android: Das aus dem Dienst abgerufene Objekt ist nach dem Bindungsdienst null.

Fehlerprotokoll:

java.lang.RuntimeException: Unable to start activity ComponentInfo 
    {mycompany.notes/mycompany.notes.Activity.ChatMessagesActivity}: java.lang.NullPointerException: Attempt to read from field 'org.cometd.client.BayeuxClient mycompany.notes.Activity.ConsoleChatClient.client' on a null object reference 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
    at android.app.ActivityThread.-wrap11(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5417) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
    Caused by: java.lang.NullPointerException: Attempt to read from field 'org.cometd.client.BayeuxClient mycompany.notes.Activity.ConsoleChatClient.client' on a null object reference 
    at mycompany.notes.Activity.ChatMessagesActivity.onCreate(ChatMessagesActivity.java:177) 
    at android.app.Activity.performCreate(Activity.java:6237) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 

Servicecode:

public class ConsoleChatClient extends Service { 

    private final IBinder mBinder = new LocalBinder(); 
    BayeuxClient client; 
    HttpClient httpClient = StaticRestTemplate.getHttpClient(); 
    String defaultURL = StaticRestTemplate.baseURL + "/cometd"; 


    public class LocalBinder extends Binder { 
     ConsoleChatClient getService() { 
      // Return this instance of LocalService so clients can call public methods 
      return ConsoleChatClient.this; 
     } 
    } 

    private void connectionEstablished() { 
     System.err.printf("system: Connection to Server Opened%n"); 

    } 

    private void connectionClosed() { 
     System.err.printf("system: Connection to Server Closed%n"); 
    } 

    private void connectionBroken() { 
     System.err.printf("system: Connection to Server Broken%n"); 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     performConnection(); 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     performConnection(); 
     return mBinder; 

    } 



private void performConnection() { 
     try { 
      httpClient.start(); 
      ClientTransport clientTransport = new LongPollingTransport(null, httpClient); 
      bayeuxClient = new BayeuxClient(defaultURL, clientTransport); 
      // Below for use with Spring-Security post-login. 
      bayeuxClient.putCookie(new HttpCookie("JSESSIONID", StaticRestTemplate.getJsessionid())); 
      bayeuxClient.getChannel(Channel.META_HANDSHAKE).addListener(new InitializerListener()); 
      bayeuxClient.getChannel(Channel.META_CONNECT).addListener(new ConnectionListener()); 
      bayeuxClient.handshake(); 
      StaticRestTemplate.setClient(bayeuxClient); 
      StaticRestTemplate.setHttpClient(httpClient); 
      boolean success = bayeuxClient.waitFor(2000, BayeuxClient.State.CONNECTED); 
      if (!success) { 
       System.err.printf("Could not handshake with server at %s%n", defaultURL); 
      }else { 
       System.err.printf("Handhskare complete"); 
      } 

     } catch (Exception ignored) {} 
    } 
    } 

ChatMessagesActivity.java:

public class ChatMessagesActivity extends ApplicationDrawerLoader { 

    HttpClient httpClient; 
    ConsoleChatClient consoleChatClient; 
    boolean mBound = false; 

    private ChatListener chatListener = new ChatListener(); 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     Intent intent = new Intent(this, ConsoleChatClient.class); 
     bindService(intent, mConnection, Context.BIND_IMPORTANT); 
    } 

    private ServiceConnection mConnection = new ServiceConnection() { 

     @Override 
     public void onServiceConnected(ComponentName className, 
             IBinder service) { 
      ConsoleChatClient.LocalBinder binder = (ConsoleChatClient.LocalBinder) service; 
      consoleChatClient = binder.getService(); 
      mBound = true; 
     } 

     @Override 
     public void onServiceDisconnected(ComponentName arg0) { 
      mBound = false; 
     } 
    }; 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     // Unbind from the service 
     if (mBound) { 
      unbindService(mConnection); 
      mBound = false; 

      if (conversationId != 0) { 
       consoleChatClient.client.getChannel("/person/" + conversationId).unsubscribe(); 
      } 

      if (groupAccountId != 0) { 
       consoleChatClient.client.getChannel("/chat/" + conversationId).unsubscribe(); 
      } 
     } 
    } 



    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_chat_messages); 

    try { 

      Intent intent = new Intent(this, ConsoleChatClient.class); 
      startService(intent); 
      httpClient = consoleChatClient.httpClient; 
     } catch (Exception ignored) { 
     } 

// Below code crashes at consoleChatClient.client 
if (conversationId != 0) { 
      consoleChatClient.client.getChannel("/person/" + conversationId).subscribe(chatListener); 
     } 

     if (groupAccountId != 0) { 
      consoleChatClient.client.getChannel("/chat/" + conversationId).subscribe(chatListener); 
     } 
} 

Also, was mache ich falsch, dass es in einer Klasse arbeitet, und nicht in anderen. Irgendeine Hilfe. Vielen Dank.

+0

Wo Sie die 'Klient' Instanzvariable zu initialisieren? –

+0

'httpClient = consoleChatClient.httpClient;' hier ist 'consoleChatClient' null – pskink

+0

@pskink: Eigentlich nein, httpClient ist nicht null, der BayeuxClient ist null. Das verwirrt mich, das habe ich gerade bestätigt. –

Antwort

2

Rufen Sie bindService() direkt nach nach startService(), weil onStart() später ausgeführt wird. Bindung ist nicht sofort, also warten Sie auf onServiceConnected() zu fangen Sie an, mit Ihrem consoleChatClient zu arbeiten, anstatt es direkt nach startService() zu machen. Dies garantiert, dass es ordnungsgemäß initialisiert wird.

Sie können auch die Bindung mithilfe von getApplicationContext().unbindService() lösen, da die Verwendung des Kontexts Ihrer Aktivität möglicherweise nicht funktioniert.

Hier ist, wie ich es tun würde:

public class ChatMessagesActivity extends ApplicationDrawerLoader { 

    HttpClient httpClient; 
    ConsoleChatClient consoleChatClient; 
    boolean mBound = false; 

    private ChatListener chatListener = new ChatListener(); 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     Intent intent = new Intent(this, ConsoleChatClient.class); 
     bindService(intent, mConnection, Context.BIND_IMPORTANT); 
    } 

    private ServiceConnection mConnection = new ServiceConnection() { 

     @Override 
     public void onServiceConnected(ComponentName className, 
             IBinder service) { 
      ConsoleChatClient.LocalBinder binder = (ConsoleChatClient.LocalBinder) service; 
      consoleChatClient = binder.getService(); 
      mBound = true; 
      onConsoleChatClientReady() 
     } 

     @Override 
     public void onServiceDisconnected(ComponentName arg0) { 
      mBound = false; 
     } 
    }; 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     // Unbind from the service 
     if (mBound) { 
      unbindService(mConnection); 
      mBound = false; 

      if (conversationId != 0) { 
       consoleChatClient.client.getChannel("/person/" + conversationId).unsubscribe(); 
      } 

      if (groupAccountId != 0) { 
       consoleChatClient.client.getChannel("/chat/" + conversationId).unsubscribe(); 
      } 
     } 
    } 



    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_chat_messages); 

     Intent intent = new Intent(this, ConsoleChatClient.class); 
     startService(intent); 


    } 

    private void onConsoleChatReady(){ 
     httpClient = consoleChatClient.httpClient; 
     if (conversationId != 0) { 
     consoleChatClient.client.getChannel("/person/" + conversationId).subscribe(chatListener); 
     } 

     if (groupAccountId != 0) { 
     consoleChatClient.client.getChannel("/chat/" + conversationId).subscribe(chatListener); 
     } 
    } 
} 
+0

Wie kann ich auf onServiceConnected warten ?? Danke –

+0

Das funktionierte wie ein Zauber. Vielen Dank .. :-) Ich habe einen letzten Fehler beim Aktualisieren einer Liste direkt für neue Nachricht. Ich werde den Link hier posten, sobald ich die Frage gepostet habe. Danke vielmals .. :-) –

Verwandte Themen