2014-10-13 2 views
0

이상한 문제가 있습니다. 코드가 테스트중인 일부 Android 장치에서 갑자기 이러한 문제가 발생합니다.중복 된 원격 서비스 인스턴스

전 시스템 내에서 통신을 관리하는 데 사용되는 것과 동일한 원격 서비스를 공유하는 여러 활동으로 구성된 시스템으로 작업하고 있습니다.

문제는 일부 장치에서 원격 서비스의 복제 인스턴스를 얻는 것이 문제가되지는 않지만 실제로는 큰 문제입니다. 실제로 원격 서비스는 UDP 또는 TCP를 통한 메시지 교환을 관리하는 데 사용되며 두 서비스가 동일한 포트 (브로드 캐스트 포트)를 사용하려고하기 때문에 소켓에 ​​문제가있는이 서비스의 인스턴스를 여러 개 얻으면 EADDRINUSE 예외가 발생합니다.

누군가이 서비스를 여러 번 사용하는 이유를 설명 할 수 있습니까?

@Override 
public int onStartCommand(final Intent intent, final int flags, 
     final int startId) { 

    return START_STICKY; 
} 

@Override 
public IBinder onBind(final Intent intent) { 

    if (IRemoteService.class.getName().equals(intent.getAction())) { 
     return mBinder; 
    } 
    return null; 
} 

@Override 
public void onCreate() { 
    Log.d(tag, "onCreate...RemoteService"); 

    //Here I have the registration of some receivers and the launch of other services 

} 

@Override 
public void onDestroy() { 

    mCallbacks.kill(); 

} 
: 내 원격 서비스의 코드는 이것이다

@Override 
protected void onCreate(final Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    startService(new Intent(
      MyAction.REMOTE_SERVICE_LOAD)); 

    getApplicationContext().bindService(
      new Intent(IRemoteService.class.getName()), mConnection, 
      Context.BIND_AUTO_CREATE); 

} 

/** The primary interface we will be calling on the service. */ 
private IRemoteService mService = null; 

private final ServiceConnection mConnection = new ServiceConnection() { 

    @Override 
    public void onServiceConnected(final ComponentName className, 
      final IBinder service) { 

     mService = IRemoteService.Stub.asInterface(service); 
     try { 
      mService.registerCallback(mCallback); 

       launchTask(); 

     } catch (final Throwable e) { 
      e.printStackTrace(); 
     } 

    } 

@Override 
public void onDestroy() { 
    super.onDestroy(); 

    try { 
     if (mConnection != null && mService != null) { 
      mService.unregisterCallback(mCallback); 
      getApplicationContext().unbindService(mConnection); 
      Log.d(tag, "UNREGISTER SERVICE CALLBACK for activity " 
        + getClass().getSimpleName()); 
     } 
    } catch (final Exception e) { 
     e.printStackTrace(); 
    } 
} 

//method that will be called when I get a notification on serverUp and i come from 
//a serverDown situation 

public void notifyConnectionUp() { 
    if (!serverConnected) { 

     if (mConnection != null) { 
      try { 
       mService.unregisterCallback(mCallback); 
      } catch (final RemoteException e) { 
       e.printStackTrace(); 
      } 
      getApplicationContext().unbindService(mConnection); 

     } 

     getApplicationContext().bindService(
       new Intent(IRemoteService.class.getName()), mConnection, 
       Context.BIND_AUTO_CREATE); 

     System.gc(); 

    } 
} 

: 여기

내가 내 모든 활동에 의해 상속 내 주요 활동에서 원격 서비스 바인딩을 설정하는 코드입니다

 <service 
     android:name="shared.RemoteService" 
     android:enabled="true" 
     android:process=":remote"> 
     <intent-filter> 

      <action 
       android:name="shared.IRemoteService"/> 

      <action 
       android:name="shared.REMOTE_SERVICE"/> 
     </intent-filter> 
    </service> 

또 다른 : CommonsWare에 의해 질문으로

이 내 서비스 응용 프로그램에 대한 태그입니다 질문, 새로운 활동을 시작할 때 항상 서비스의 StartCommand에있는 메소드에 대한 호출이 표시되는 것은 맞습니까? 내 mainActivity에서 startService()를 호출 한 다음 bindService를 호출했다는 것을 고려하여 서비스의 onBind() 메서드에 대한 호출을 기다리고있었습니다.

나는 내 장치에서 PS 명령을 실행할 때 때문에 나는 내 원격 서비스의 여러 인스턴스를 볼 나는 다음과 같은 결과를 얻을 : 14,013 2,330 478,116 28,620 u0_a67, 1 :

D/명령 (14049) : ID를 FFFFFFFF 40767ce8 R의 service.net:remote D/명령 (14049) : ID : 1, 31,493 14,013 477,100 21,416 00,000,000 40051a58 R의 service.net:remote

u0_a67 그리고 한 서비스의 부모 인 것 같습니다 당신이 볼 수 있듯이 다른 하나 (제 2 서비스 PPID는 제 1 서비스 PID 인 14013)이다.

나는 분명히하기를 희망한다.

+0

매니페스트의 ''요소를 게시하십시오. 또한 서비스 코드에'Log' 문과 같이 서비스 인스턴스가 여러 개 있는지 확인하려면 ** ps' **보다 나은 테스트를 사용하십시오. 여러 * 서비스 인스턴스 *를 보유하고있는 것과는 다른 * 프로세스 *가 여러 개 있음을 입증했습니다. – CommonsWare

+0

매니페스트 섹션에서 내 질문을 편집했습니다. 내가 게시 한 코드에서 로그 문을 제거했지만 코드에 로그가 가득 찼습니다. 불행히도 logcat과 나는 두 번째 서비스의 인스턴스를 볼 수 없습니다. –

답변

1

내가보고있는 것은 원격 서비스가 포함 된 android:process=":remote" 호의 두 번째 프로세스이며 원격 서비스 인스턴스는 하나 뿐인 것으로 알고 있습니다.

시험을 실행하고이 이론을 확인하기 위해 임시로 android:process=":remote"을 제거하고 사용자의 RAM을 더 많이 사용해야하는 분명한 이유가없는 한 영구적으로 제거하는 것이 좋습니다.

+0

질문 : 원격 정의를 제거하면 다른 활동이 동일한 서비스에 바인딩 될 수 있습니다 (또는 서비스가 분리 된 프로세스에서 실행되는 유일한 차이점)? 나는이 정의가 다른 활동에 의해 공유되는 서비스의 단일 인스턴스를 갖는 것이 필요하다고 생각했다. 어쨌든 나는 너의 제안을 시도 할 것이다. –

+0

@axlcoder : "이 정의는 다른 활동에 의해 공유되는 서비스의 단일 인스턴스를 가질 필요가 있다고 생각합니다." - 아니, 다른 앱에서 액세스 할 수있는 서비스를 갖기 위해 'android : process'가 필요하지 않습니다. – CommonsWare

+0

대단히 감사합니다 !!!!!! 당신은 오랫동안 나를 괴롭혀서 전체 시스템의 나쁜 행동으로 이끌어 낸 문제를 해결했습니다. 나는 당신에게 고전적인 맥주 이외에 행복한 저녁 식사를 제공 할 것이다;) –