2016-05-05 35 views
6

Próbuję utworzyć zestaw 2 aplikacji (aplikacja usługi + aplikacja kliencka) przy użyciu AIDL. Mam obecnie konfiguracji z 3 modułów:Usługa AIDL nie łączy się po bindService()

  • android-Agent-Framework (moduł biblioteki android posiadających tylko plik AIDL)
  • android-agent (usługi)
  • android-np-client (the klient)

Android-agent i platforma-agent-android mają zależność od pierwszej, aby uzyskać dostęp do interfejsu.

Ilekroć klient wywołuje bindService(), dostaje false jako return, a w ServiceConnection nie jest wywoływana onServiceConnected(). Również w implementacji usługi funkcja onBind() nie jest wywoływana. W dziennikach nie ma błędów.

Oto kod:

aktywność android-agent:

public class MyCompanyStartActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     Log.i(MyCompanyStartActivity.class.toString(), "Create MyCompanyStartActivity"); 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     ComponentName service = startService(new Intent(this, MyCompanyRequestService.class)); 
     Log.i("tag", service.getClassName() + "::" + service.getPackageName()); 
    } 

} 

usługa android-agent:

public class MyCompanyRequestService extends Service { 

@Override 
public IBinder onBind(Intent intent) { 
    Log.i(MyCompanyRequestService.class.toString(), "Starting SmartRest Service"); 
    return mBinder; 
} 

private final IMyCompanyRequestService.Stub mBinder = new IMyCompanyRequestService.Stub() { 

    @Override 
    public void sendData(String xid, String authentication, String data) throws RemoteException{ 
     Log.i(MyCompanyRequestService.class.toString(), "sending data: " + data); 
    } 
}; 

} 

android-agent oczywisty:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.mycompany.android.agent" > 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <activity 
      android:name=".MyCompanyStartActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

     <!-- Services --> 
     <service 
      android:name="com.mycompany.android.agent.framework.MyCompanyRequestService" 
      android:process=":remote" 
      android:exported="true" 
      android:enabled="true"> 
      <intent-filter> 
       <action android:name="MyCompanyRequestService"/> 
       <category android:name="android.intent.category.DEFAULT"/> 
      </intent-filter> 
     </service> 

     <!-- Permissions --> 

    </application> 

</manifest> 

android -example-client activity:

public class ClientStarter extends Activity { 

    protected IMyCompanyRequestService mycompanyRequestService = null; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     Log.i("tag","create client"); 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

    } 
    @Override 
    protected void onStart() { 
     super.onStart(); 
     if (mycompanyRequestService == null) { 
      printServices(); 
      Intent it = new Intent("MyCompanyRequestService"); 
      it.setPackage("com.mycompany.android.agent.framework"); 
      Log.i("tag","before binding service: " + it.getAction() + "::" + it.getPackage()); 
      boolean serviceBinding = getApplicationContext().bindService(it, connection, Context.BIND_AUTO_CREATE); 
      Log.i("tag", "service is bound: " + serviceBinding); 
     } 
     Handler handler = new Handler(); 
     handler.postDelayed(new Runner(), 10000); 
    } 

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

    private ServiceConnection connection = new ServiceConnection() { 
     @Override 
     public void onServiceConnected(ComponentName name, IBinder service) { 
      Log.i("service", "Service connected"); 
      mycompanyRequestService = IMyCompanyRequestService.Stub.asInterface(service); 
      Toast.makeText(getApplicationContext(), "Service Connected", Toast.LENGTH_SHORT).show(); 
      Log.i("service", "Service connected"); 
     } 
     @Override 
     public void onServiceDisconnected(ComponentName name) { 
      Log.i("service", "Service disconnected"); 
      mycompanyRequestService = null; 
      Toast.makeText(getApplicationContext(), "Service Disconnected", Toast.LENGTH_SHORT).show(); 
      Log.i("service", "Service disconnected"); 
     } 
    }; 

    private void printServices() { 
     ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
     for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 
      Log.d("service", service.service.getClassName()); 
     } 
    } 

    private class Runner implements Runnable { 

     @Override 
     public void run() { 
      Log.i("tag","starting"); 
      LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
      Location loc; 
      try { 
       Thread.sleep(10000); 
      } catch (InterruptedException e) { 
       Log.e(ClientStarter.class.toString(), "Error", e); 
      }   while(true) { 
       try { 
        if (mycompanyRequestService != null) { 
         loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 
         Log.i(ClientStarter.class.toString(), loc.getLatitude() + " - " + loc.getLongitude() + " - " + loc.getAltitude()); 
         mycompanyRequestService.sendData("test", "auth", String.valueOf(loc.getLatitude()) + "," + String.valueOf(loc.getLongitude()) + "," + String.valueOf(loc.getAltitude())); 
        } else { 
         Log.i(ClientStarter.class.toString(), "service not yet available"); 
        } 
        Thread.sleep(5000); 
       } catch (InterruptedException e) { 
        Log.e(ClientStarter.class.toString(), "Error", e); 
       } catch (RemoteException e) { 
        Log.e(ClientStarter.class.toString(), "Error", e); 
       } 
      } 
     } 


    } 

} 

Wywołanie funkcji printServices() przed próbą związania usługą powoduje wyświetlenie usługi, która jest uruchomiona.

Dziennik nie zawiera żadnych błędów, a klient jest na końcu uruchomiony w pętli, ale usługa jest nadal pusta.

Może ktoś napotkał podobny problem wcześniej.

+0

W systemie Android 5.0 lub nowszym należy użyć jawnego polecenia 'Intent' do powiązania z usługą. Jestem sceptyczny, że 'setPackage()' jest wystarczające. – CommonsWare

+0

@CommonsWare Naprawdę dodałem setPackage() po tym, jak wpadłem na problem z Androidem, który narzekał, że intencja nie była wyraźna. Przetestowałem jeden przykładowy projekt AIDL, który również użył setPackage() na tym samym telefonie i zadziałało. Dzięki setPackage() błąd zniknął również w moim projekcie – TyrManuZ

Odpowiedz

2

Po przejściu kolejnej rundy przez wszystkie pliki znalazłem mój błąd.

Musiałem zmienić:

Intent it = new Intent("MyCompanyRequestService"); 
it.setPackage("com.mycompany.android.agent.framework"); 

do:

Intent it = new Intent("MyCompanyRequestService"); 
it.setPackage("com.mycompany.android.agent"); 

Pakiet o zamiarze musi dopasować pakiet aplikacji, a nie pakiet usług.