2013-01-10 1 views
6

私のアプリは別の(私の)アプリケーションで提供されているサービスを使用しています。私はbound serviceMessengerを使ってそれにアクセスし、それと通信しています(別のアプリケーションでもリモートサービスです)。bindService()はfalseを返しますが、unbindService()を呼び出す必要がありますか?

私は適切な意図を持ってbindServiceを呼び出し、呼び出しがfalseを返す(APKがサービスを提供すると、期待どおりの周りではありません)、私は私がunbindする必要がないこと、ドキュメントやサンプルコードから推定ServiceConnection。しかし、私のGalaxy Nexus(Jelly Bean)デバイスでこれを行うと、Activityの終了時によく知られたServiceConnectionLeakedというメッセージが表示されます。

私はこれが

if (!ctxt.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)) { 
    try { 
     ctxt.unbindService(serviceConnection); 
    } catch (Throwable t) {} 
    // Clean up 
    return; 
} 
// Store serviceConnection for future use 

を行うことで、私は好奇心旺盛だということを引き揚げている:私はちょうどドキュメントに何かを欠場し、それがこのように動作するようになっていますか?私はtry ... catchを追加して、この動作が実際に他のデバイスやAndroidのバージョンで異なっていても、私のアプリはそれによって(否定的に)影響を受けないことを確認しています。

答えて

7

一般に、bindService()呼び出しがtrueまたはfalseを返すかどうかにかかわらず、ServiceConnectionは常にフレームワークによって割り当てられ、登録されます。 android.app.ContextImplでbindService()の実装を参照してください。

public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) { 
    IServiceConnection sd; 
    if (conn == null) { 
     throw new IllegalArgumentException("connection is null"); 
    } 
    if (mPackageInfo != null) { 
     // A new ServiceDispatcher will be created and registered along with 
     // ServiceConnection in LoadedApk.mService for your application context. 
     sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), 
       mMainThread.getHandler(), flags); 
    } else { 
     throw new RuntimeException("Not supported in system context"); 
    } 
    try { 
     ... ... 
     return res != 0; 
    } catch (RemoteException e) { 
     return false; 
    } 
} 

あなたがそれで行われたときにthe official dev guideにより示唆されるようにあなたが常に良いプログラミング方法として、サービスのバインドを解除する必要があります

  • 切断するにはサービスからunbindService()を呼び出します。

    クライアントが破棄されると、サービスからバインド解除されますが、サービスとのやりとりが完了したときや、サービスが使用されていない間にサービスをシャットダウンできるように、アクティビティが一時停止すると、 (適切な時間をバインドすると、バインド解除は、より後述する。)フレームワークは、最終的なクリーンアップを実行する起動時に

ServiceConnectionLeakedが上昇した(例えば、アプリが終了したとき)、見つかった未登録ServiceConnectionがあり、フレームワークは次にそれをバインド解除しようとします。 android.app.LoadedApk中)(実装をremoveContextRegistrationsを参照してください:返信用

public void removeContextRegistrations(Context context, 
     String who, String what) { 
    final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled(); 
    ... ... 
    //Slog.i(TAG, "Receiver registrations: " + mReceivers); 
    HashMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap = 
     mServices.remove(context); 
    if (smap != null) { 
     Iterator<LoadedApk.ServiceDispatcher> it = smap.values().iterator(); 
     while (it.hasNext()) { 
      LoadedApk.ServiceDispatcher sd = it.next(); 
      ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
        what + " " + who + " has leaked ServiceConnection " 
        + sd.getServiceConnection() + " that was originally bound here"); 
      leak.setStackTrace(sd.getLocation().getStackTrace()); 
      Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 
      if (reportRegistrationLeaks) { 
       StrictMode.onServiceConnectionLeaked(leak); 
      } 
      try { 
       ActivityManagerNative.getDefault().unbindService(
         sd.getIServiceConnection()); 
      } catch (RemoteException e) { 
       // system crashed, nothing we can do 
      } 
      sd.doForget(); 
     } 
    } 
    mUnboundServices.remove(context); 
    //Slog.i(TAG, "Service registrations: " + mServices); 
} 
+0

おかげで、それはまだサンプルと一致していない( 'は()'と呼ばれていたonServiceConnected場合ApiDemosで、例えばRemoteServiceはまた、唯一のバインド解除ん)。しかし、あなたの助けを借りれば、高レベルの説明でさえそのような解釈を可能にしているように見えるので、私はその答えを受け入れます。 – Stephan

関連する問題