2012-10-16 12 views
14

Mam usługę w aplikacji i mogę korzystać z tej usługi z różnych aplikacji. A gdy aplikacje próbują powiązać tę usługę, chcę wiedzieć, która aplikacja próbuje powiązać moją usługę z funkcją onBind, , ale nie mogę uzyskać nazwy pakietu lub UID tej aplikacji w funkcji onBind.Jak uzyskać nazwę pakietu aplikacji lub identyfikator UID, który próbuje powiązać moją usługę z funkcją onBind?

Czy można uzyskać nazwę aplikacji lub identyfikator UID, który próbuje powiązać moją usługę z funkcją onBind?

Odpowiedz

13

Możesz użyć następujących opcji, aby określić aplikację wywołującą.

String callingApp = context.getPackageManager().getNameForUid(Binder.getCallingUid()); 

Ważne jest, aby zwrócić uwagę na JavaDoc for getCallingUid() który mówi:

Powrót uid Linux przypisane do procesu, który wysłał Ci bieżącej transakcji, który jest przetwarzany. Ten identyfikator może być używany z usługami systemu wyższego poziomu w celu określenia jego tożsamości i uprawnień kontrolnych. Jeśli bieżący wątek nie wykonuje aktualnie transakcji przychodzącej, zwracany jest jego własny identyfikator UID.

+3

Jeśli zgłoszę kod dostarczany w funkcji onBind, zwraca nazwę packageName z apk który przebywa usługa. Znaczy nie powrócić od rozmówcy packageName innego apk, zwraca tylko sam packageName która usługa pozostaje w. – umituzun84

+2

z dokumentacji Android public static końcowy int getCallingUid() Powrót identyfikator użytkownika przypisany do procesu, który was wysłał bieżąca transakcja, która jest przetwarzany. Ten identyfikator może być używany z usługami systemu wyższego poziomu w celu określenia jego tożsamości i uprawnień kontrolnych. Jeśli bieżący wątek nie wykonuje aktualnie transakcji przychodzącej, zwracany jest jego własny identyfikator UID. –

+0

Oba komentarze na temat tej odpowiedzi są poprawne - ale jeśli wywołasz to w metodach ujawnionych przez twój plik AIDL, wydaje się, że raport jest poprawny. Bardzo przydatna odpowiedź dla mnie. – brandall

2

Nie możesz tego zrobić.

Funkcja onBind() jest wywoływana z "menedżera cyklu życia systemu Android" (tworząc przydatną nazwę) i będzie wywoływana tylko raz dla każdego zamiaru (aby mógł się dowiedzieć, który segregator powinien zostać zwrócony w tym celu).

Wezwanie do usługi następnie przechodzi przez ten segregator i można zrobić Binder.getCallingUid() w jednej z tych metod.

0

Przyjęta odpowiedź nie była całkiem poprawna! Dlaczego? Jeśli dwóch lub więcej aplikacji używać tego samego android:sharedUserId metoda Binder.getCallingUid() zwróci samo uid i getPackageManager().getNameForUid(uid) zwróci ten sam ciąg, wygląda na to: com.codezjx.demo: 10058, ale nie jest to nazwa pakietu!

Właściwy sposób jest używać pid:

int pid = Binder.getCallingPid(); 

a następnie użyć PID, aby uzyskać nazwę pakietu przez ActivityManager, każdy proces może pomieścić wiele pakietów, tak to wygląda:

private String[] getPackageNames(Context context, int pid) { 
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
    List<RunningAppProcessInfo> infos = am.getRunningAppProcesses(); 
    if (infos != null && infos.size() > 0) { 
     for(RunningAppProcessInfo info : infos) { 
      if(info.pid == pid) { 
       return info.pkgList; 
      } 
     } 
    } 
    return null; 
} 

Warnning: W przypadku korzystania z metody Binder.getCallingPid() i jeśli bieżący wątek nie wykonuje aktualnie transakcji przychodzącej, wówczas jej własny pid jest równy urne. Oznacza to, że musisz wywołać tę metodę w metodzie narażonych interfejsów AIDL.

+0

To nie zadziała w przypadku ostatnich wersji Androida. Funkcja getRunningAppProcesses() została zmieniona, aby zwracać tylko proces wywoływania. Więcej tutaj: http://stackoverflow.com/questions/30619349/android-5-1-1-and-above-getrunningappprocesses-return-moje-programowanie-packag –

0

Powyższa przyjęta odpowiedź nie sprawdziła się u mnie. Ale mała modyfikacja załatwiła sprawę. Działa to całkiem dobrze z komunikacją opartą na Messenger.

public class BoundService extends Service { 

    public static final int TEST = 100; 
    private final Messenger messenger = new Messenger(new MessageHandler()); 

    class MessageHandler extends Handler { 
     @Override 
     public void handleMessage(Message msg) { 

      String callerId = getApplicationContext().getPackageManager().getNameForUid(msg.sendingUid); 
      Toast.makeText(getApplicationContext(), "Calling App: " + callerId, Toast.LENGTH_SHORT).show(); 

      switch (msg.what) { 
       case TEST: 
        Log.e("BoundService", "Test message successfully received.") 
        break; 
       default: 
        super.handleMessage(msg); 
      } 
     } 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return messenger.getBinder(); 
    } 
} 

Z powyższej odpowiedzi, trzeba tylko zmienić Binder.getCallingUid() do msg.sendingUid

Powiązane problemy