2012-07-21 66 views
0

我無法讓我的應用程序爲各種reasosn正常工作。如何讓服務綁定到正確的活動實例?

設計概述: 我的目標是一個活動,它有兩個按鈕(連接,斷開)和一個顯示從連接收到的數據的文本視圖。我編寫了一個處理WebSocket連接(Gottox的Java實現)的「MySocket」服務,並且此服務在tit接收到來自服務器的某些內容時向該活動發佈消息,然後該活動將該數據附加到textview上。該服務必須接收來自活動的連接/斷開連接提示,並且能夠將消息傳遞給活動。 MySocket還需要作爲前臺服務運行,以便無限期地保持連接,並向用戶提供粘性通知。

我在各個地方都遇到過這個問題。首先,我注意到我可以開始另一個活動實例,而原始內容仍在更新中。我通過在清單中指定android:launchMode="singleInstance">來解決這個問題。我遇到的問題是,當活動被摧毀並創建一個新的活動時,該服務繼續發佈更新,但重點活動沒有收到它們。如果原始活動被破壞,服務處理程序沒有更新,那麼一旦活動被銷燬,它肯定會拋出空指針異常,但應用程序仍在運行。然後,我嘗試在我的onDestroy方法中運行unbindService(mConnection),但是投擲了一個java.lang.IllegalArgumentException: Service not registered:該服務正在傳送東西這應該是重點活動,但似乎沒有收到它。我懷疑我的前臺服務不好的實施是怪,但我真的沒有線索。

問題的兩個類都是LONG,所以我刪除了Logcat行,全局變量和一些我確定無關的方法。我意識到這個架構非常可怕,但這與我的工作接近。如果代碼太可怕無法閱讀,我會很高興有人建議一個替代結構,只要它達到預期的結果。

活動類:

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
     ... 
     mMessenger = new Messenger(mHandler); 
     connect.setOnClickListener(new View.OnClickListener() 
    { 
     @Override 
     public void onClick(View v) 
     { 
      messageSocket("ACTION", "CONNECT"); 
     } 
    }); 

    @Override 
    protected void onDestroy() 
    { 
     super.onDestroy(); 
     doUnbindService(); 
    } 

    private ServiceConnection conn = new ServiceConnection() 
    { 
    public void onServiceConnected(ComponentName className, IBinder binder) 
    { 
     Log.d(debug, "Service Connected"); 
     messenger = new Messenger(binder); 
     boundToService = true; 
    } 

    public void onServiceDisconnected(ComponentName className) 
    { 
     Log.d(debug, "Service Disconnected"); 
     messenger = null; 
     boundToService = false; 
    } 
    }; 

    void doBindService() 
    { 
    final Intent intent = new Intent(this, MySocket.class); 
    intent.putExtra("MESSENGER", messenger); 
    Thread t = new Thread() 
    { 
     public void run() 
     { 
     boundToService = 
       getApplicationContext().bindService(
       intent, 
       conn, 
       Context.BIND_AUTO_CREATE 
      ); 
     } 
    }; 
    t.start(); 
} 

而且MySocket類:

class IncomingHandler extends Handler 
{ 
    @Override 
    public void onCreate() 
{...} 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     startForeground(id, showNotification()); 
    connect(); 
     return START_STICKY; 
} 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     startForeground(id, showNotification()); 
     connect(); 
     return START_STICKY; 
} 


private Notification showNotification() 
{ 
    nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
    CharSequence text = "WebSocket currently active"; 
    Notification notification = new Notification(R.drawable.ic_launcher, 
      text, System.currentTimeMillis()); 
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, 
      new Intent(this, SocketTester.class), 0); 
    notification.setLatestEventInfo(this, "WebSocket Test", text, 
      contentIntent); 
    notification.flags = Notification.FLAG_FOREGROUND_SERVICE; 
    return notification; 
} 
     @Override 
    public IBinder onBind(Intent intent) 
    { 
     Bundle extras = intent.getExtras(); 
     Log.d(debug, "onBind called"); 
     if (intent.getExtras() != null) 
     { 
      Log.d(debug, "Setting messenger"); 
      outMessenger = (Messenger) extras.get("MESSENGER"); 
     } 
     return inMessenger.getBinder(); 
     } 

    @Override 
    public void handleMessage(Message msg) 
      {   
     Bundle data = msg.getData();    
     Message backMsg = Message.obtain(); 
     Bundle bundle = new Bundle(); 
     backMsg.setData(bundle); 

     if ("CONNECT".equals(data.getString(ACTION))) 
     { 
      Log.d(debug, "Connecting"); 
      startService(new Intent(MySocket.this, MySocket.class)); 
      /*startService now calls connect();*/ 
     } 
     else if ("DISCONNECT".equals(data.getString(ACTION))) 
     { 
      if (socket != null) 
      { 
       socket.disconnect(); 
      } 
      stopForeground(true); 
      stopSelf(); 
     } 
    } 
} 
+0

我將爲您提供與另一個架構,但你必須解釋,你願意在你的應用程序中做什麼,應該是關鍵點。謝謝:) – SALMAN 2012-07-22 00:04:00

+0

需要一個活動,顯示數據通過websocket傳遞,並提供用戶打開和關閉連接,一旦打開,連接應該保持打開狀態,直到用戶關閉爲止,還必須有一個粘性通知讓用戶知道連接仍然是操作恩。 – Chironex 2012-07-22 15:19:25

+0

ok爲什麼不保存你的數據,它已被rec。通過SharedPreference in Service類中的websocket連接,因此,您可以收集數據並顯示您想要的任何活動? – SALMAN 2012-07-22 17:16:33

回答

-1

「如果你開始與startService(..)的機器人服務該服務將繼續運行,直到您顯式調用stopService(。 )如果有人調用Context.startService(),那麼系統將檢索服務(如果需要,創建它並調用它的onCreate()方法),然後調用它的onStartCommand (Intent,int,int)方法由客戶提供。此服務將繼續運行,直到調用Context.stopService()或stopSelf()。請注意,對Context.startService()的多次調用不會嵌套(儘管它們會導致對onStartCommand())進行多次相應調用),因此無論啓動多少次,服務都會停止一次Context.stopService()或stopSelf () 叫做;然而,服務可以使用他們的stopSelf(int)方法來確保服務不會停止,直到已處理啓動的意向。

客戶端還可以使用Context.bindService()來獲得服務的持久連接。如果服務尚未運行(同時調用onCreate()),則同樣會創建服務,但不會調用onStartCommand()。客戶端將收到服務從其onBind(Intent)方法返回的IBinder對象,從而允許客戶端將該服務調用回該服務。只要建立連接(無論客戶是否保留對服務的IBinder的引用),該服務就會繼續運行。返回的IBinder通常是用於一個複雜的接口,已經被寫入aidl。

服務既可以啓動,也可以綁定連接。在這種情況下,只要系統啓動,或者存在與Context.BIND_AUTO_CREATE標誌的一個或多個連接,系統就會繼續運行該服務。一旦這些情況都不成立,就會調用服務的onDestroy()方法,並且服務被有效終止。所有清理(停止線程,註銷接收器)應在從返回的onDestroy()是完整的。」

我希望這將有助於使你所做的工作。

謝謝:)