Android: Jak mogę uzyskać bieżącą aktywność na pierwszym planie (z usługi)?


180

Czy istnieje natywny sposób na Androida, aby uzyskać odniesienie do aktualnie działającego działania z usługi?

Mam usługę działającą w tle i chciałbym zaktualizować moją bieżącą aktywność, gdy wystąpi zdarzenie (w usłudze). Czy jest na to łatwy sposób (taki jak ten, który zasugerowałem powyżej)?


może to da ci pomysł stackoverflow.com/a/28423385/185022
AZ_

Odpowiedzi:


87

Czy istnieje natywny sposób na Androida, aby uzyskać odniesienie do aktualnie działającego działania z usługi?

Możesz nie być właścicielem „aktualnie działającego działania”.

Mam usługę działającą w tle i chciałbym zaktualizować moją bieżącą aktywność, gdy wystąpi zdarzenie (w usłudze). Czy jest na to łatwy sposób (taki jak ten, który zasugerowałem powyżej)?

  1. Wyślij transmisję Intentdo działania - oto przykładowy projekt demonstrujący ten wzór
  2. Poproś, aby działanie dostarczyło PendingIntent(np. Przez createPendingResult()) wywołaną przez usługę
  3. Niech aktywność zarejestruje obiekt zwrotny lub obiekt nasłuchujący w usłudze za pośrednictwem bindService() , a usługa wywołała metodę zdarzenia dla tego obiektu wywołania zwrotnego / obiektu nasłuchiwania
  4. Wyślij zamówioną transmisję Intentdo działania, z niskim priorytetem BroadcastReceiverjako kopię zapasową (aby podnieść, Notificationjeśli aktywność nie jest wyświetlana na ekranie) - oto post na blogu z większą ilością tego wzoru

3
Dzięki, ale ponieważ mam mnóstwo działań i nie chcę ich wszystkich aktualizować, szukałem sposobu na Androida, aby uzyskać aktywność na pierwszym planie. Jak mówisz, nie powinienem być w stanie tego zrobić. Oznacza, że ​​muszę sobie z tym poradzić.
George,

1
@George: To, czego chcesz, i tak by ci nie pomogło. Jak zauważyłeś, masz „pętlę działań”. Dlatego są to oddzielne klasy. W związku z tym usługa nic nie może z nimi zrobić bez masowego blokowania instanceofczeków lub refaktoryzacji działań w celu udostępnienia wspólnej nadklasy lub interfejsu. A jeśli zamierzasz refaktoryzować działania, równie dobrze możesz to zrobić w sposób, który lepiej pasuje do frameworka i obejmuje więcej scenariuszy, takich jak brak aktywności. # 4 to prawdopodobnie najmniej pracochłonna i najbardziej elastyczna.
CommonsWare

2
Dzięki, ale mam lepsze rozwiązanie. Wszystkie moje działania rozszerzają niestandardową klasę BaseActivity. Ustawiłem ContextRegister, który rejestruje aktywność jako bieżącą za każdym razem, gdy jest na pierwszym planie, z dosłownie 3 liniami w mojej klasie BaseActivity. Mimo to dziękuję za wsparcie.
George,

3
@George: Uważaj na wycieki pamięci. W miarę możliwości w Javie należy unikać zmiennych elementów danych statycznych.
CommonsWare

Ściśle zamknąłem przedmiot, choć rzeczywiście będę o tym pamiętać. Dzięki.
George,

139

Aktualizacja : nie działa już w przypadku działań innych aplikacji od Androida 5.0


Oto dobry sposób na zrobienie tego za pomocą menedżera aktywności. Zasadniczo dostajesz runningTasks od menedżera aktywności. Zawsze najpierw zwróci aktualnie aktywne zadanie. Stamtąd możesz uzyskać najwyższą Aktywność.

Przykład tutaj

Istnieje prosty sposób na uzyskanie listy uruchomionych zadań z usługi ActivityManager. Możesz zażądać maksymalnej liczby zadań uruchomionych na telefonie, a domyślnie aktualnie aktywne zadanie jest zwracane jako pierwsze.

Gdy już to zrobisz, możesz uzyskać obiekt ComponentName, żądając topActivity z listy.

Oto przykład.

    ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
    Log.d("topActivity", "CURRENT Activity ::" + taskInfo.get(0).topActivity.getClassName());
    ComponentName componentInfo = taskInfo.get(0).topActivity;
    componentInfo.getPackageName();

Będziesz potrzebować następującego pozwolenia na swój manifest:

<uses-permission android:name="android.permission.GET_TASKS"/>

3
Twoja odpowiedź jest w 100% poprawna.Tanxx 4 to. Lepiej, żebyś opublikował tę samą odpowiedź tutaj
Shahzad Imam

1
@ ArtOfWarfare nie zweryfikował, ale tak, liczba posiadanych fragmentów jest nieistotna, ponieważ zawsze są one hostowane przez pojedyncze działanie.
Nelson Ramirez

2
Jeśli potrzebuję częściej bieżącej działalności, muszę często sondować, prawda? Czy istnieje sposób na uzyskanie zdarzenia zwrotnego za każdym razem, gdy zmienia się aktywność na pierwszym planie?
nizam.sp

43
Tak, aby wszyscy byli tego świadomi, dokumenty mówią o metodzie getRunningTasks (). -------- Uwaga: ta metoda jest przeznaczona wyłącznie do debugowania i prezentacji interfejsów użytkownika zarządzania zadaniami. Nie należy tego nigdy używać do podstawowej logiki w aplikacji, takiej jak podejmowanie decyzji między różnymi zachowaniami na podstawie informacji tutaj znalezionych. Takie zastosowania nie są obsługiwane i prawdopodobnie zepsują się w przyszłości. Na przykład, jeśli wiele aplikacji może być jednocześnie aktywnych, założenia przyjęte na temat znaczenia danych tutaj dla celów przepływu sterowania będą niepoprawne. ------------
Ryan

30
semifake on api 21As of LOLLIPOP, this method is no longer available to third party applications: the introduction of document-centric recents means it can leak person information to the caller. For backwards compatibility, it will still return a small subset of its data: at least the caller's own tasks, and possibly some other tasks such as home that are known to not be sensitive.
sherpya

115

Ostrzeżenie: naruszenie Google Play

Google zagroził usunięciem aplikacji ze Sklepu Play, jeśli będą korzystać z usług ułatwień dostępu w celach niedostępności. Jednakże, jest to podobno ponownie rozpatrzona .


Użyj AccessibilityService

Korzyści

  • Testowane i działające w systemie Android 2.2 (API 8) poprzez Android 7.1 (API 25).
  • Nie wymaga odpytywania.
  • Nie wymaga GET_TASKSpozwolenia.

Niedogodności

  • Każdy użytkownik musi włączyć usługę w ustawieniach ułatwień dostępu Androida.
  • To nie jest w 100% niezawodne. Czasami wydarzenia są nieczynne.
  • Usługa jest zawsze uruchomiona.
  • Gdy użytkownik próbuje włączyć opcję AccessibilityService, nie może nacisnąć przycisku OK, jeśli aplikacja umieściła nakładkę na ekranie. Niektóre aplikacje, które to robią, to Velis Auto Brightness i Lux. Może to być mylące, ponieważ użytkownik może nie wiedzieć, dlaczego nie może nacisnąć przycisku ani jak go obejść.
  • AccessibilityServiceNie będą wiedzieć, bieżącej działalności, aż do pierwszej zmiany aktywności.

Przykład

Usługa

public class WindowChangeDetectingService extends AccessibilityService {

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();

        //Configure these here for compatibility with API 13 and below.
        AccessibilityServiceInfo config = new AccessibilityServiceInfo();
        config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
        config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;

        if (Build.VERSION.SDK_INT >= 16)
            //Just in case this helps
            config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;

        setServiceInfo(config);
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            if (event.getPackageName() != null && event.getClassName() != null) {
                ComponentName componentName = new ComponentName(
                    event.getPackageName().toString(),
                    event.getClassName().toString()
                );

                ActivityInfo activityInfo = tryGetActivity(componentName);
                boolean isActivity = activityInfo != null;
                if (isActivity)
                    Log.i("CurrentActivity", componentName.flattenToShortString());
            }
        }
    }

    private ActivityInfo tryGetActivity(ComponentName componentName) {
        try {
            return getPackageManager().getActivityInfo(componentName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }

    @Override
    public void onInterrupt() {}
}

AndroidManifest.xml

Połącz to ze swoim manifestem:

<application>
    <service
        android:label="@string/accessibility_service_name"
        android:name=".WindowChangeDetectingService"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService"/>
        </intent-filter>
        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/accessibilityservice"/>
    </service>
</application>

Informacje serwisowe

Umieść to w res/xml/accessibilityservice.xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- These options MUST be specified here in order for the events to be received on first
 start in Android 4.1.1 -->
<accessibility-service
    xmlns:tools="http://schemas.android.com/tools"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagIncludeNotImportantViews"
    android:description="@string/accessibility_service_description"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:ignore="UnusedAttribute"/>

Włączanie usługi

Każdy użytkownik aplikacji będzie musiał wyraźnie włączyć opcję, AccessibilityServiceaby można było z niej korzystać. Zobacz odpowiedź StackOverflow, jak to zrobić.

Pamiętaj, że użytkownik nie będzie mógł nacisnąć przycisku OK podczas próby włączenia usługi ułatwień dostępu, jeśli aplikacja umieściła na ekranie nakładkę, taką jak Velis Auto Brightness lub Lux.


1
@lovemint, co mam na myśli to: I podano przykład settingsActivityo your.app.ServiceSettingsActivity, więc należy zmienić na swojej własnej działalności ustawień dla usługi dostępności. Wydaje mi się, że i tak aktywność ustawień jest opcjonalna, więc usunąłem tę część z mojej odpowiedzi, aby uprościć.
Sam

1
Dziękuję bardzo, tylko ostatnie pytanie. Jeśli muszę zająć się interfejsem API 8 do bieżącego, powinienem to zrobić w kodzie zamiast przy użyciu XML?
paolo2988,

1
@lovemint, zgadza się. Właśnie zaktualizowałem przykładowy kod, aby to zrobić.
Sam

1
@Sam Mogę potwierdzić, że ta usługa działa idealnie. Jedno dziwne zachowanie, użyłem zamiaru w głównym działaniu, aby włączyć usługę ułatwień dostępu. Po tej pierwszej aktywacji usługa jest aktywowana, ale onAccessibilityEventnie otrzymuje żadnego zdarzenia, ale jeśli wyłączę i ponownie włączę usługę dostępności, usługa zostanie ponownie aktywowana i onAccessibilityEventzacznie działać.
paolo2988,

2
Dziękuję za Twój kod. Stworzyłem tę aplikację dla ciebie :)
sklepienie

20

Można to zrobić przez:

  1. Zaimplementuj własną klasę aplikacji, zarejestruj się w ActivityLifecycleCallbacks - w ten sposób zobaczysz, co się dzieje z naszą aplikacją. Przy każdym wznowieniu oddzwonienie przypisuje bieżącą widoczną aktywność na ekranie, a po wstrzymaniu usuwa przypisanie. Wykorzystuje metodę registerActivityLifecycleCallbacks()dodaną w API 14.

    public class App extends Application {
    
    private Activity activeActivity;
    
    @Override
    public void onCreate() {
        super.onCreate();
        setupActivityListener();
    }
    
    private void setupActivityListener() {
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            }
            @Override
            public void onActivityStarted(Activity activity) {
            }
            @Override
            public void onActivityResumed(Activity activity) {
                activeActivity = activity;
            }
            @Override
            public void onActivityPaused(Activity activity) {
                activeActivity = null;
            }
            @Override
            public void onActivityStopped(Activity activity) {
            }
            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            }
            @Override
            public void onActivityDestroyed(Activity activity) {
            }
        });
    }
    
    public Activity getActiveActivity(){
        return activeActivity;
    }
    
    }
  2. W zgłoszeniu serwisowym getApplication()i rzuć go na nazwę klasy aplikacji (w tym przypadku App). Niż możesz zadzwonić app.getActiveActivity()- to da ci bieżącą widoczną Aktywność (lub zero, gdy żadna aktywność nie jest widoczna). Nazwę działania można uzyskać, dzwoniącactiveActivity.getClass().getSimpleName()


1
Dostaję wykonanie Nullpointer w activeActivity.getClass (). GetSimpleName (). Czy możesz mi pomóc
początkujący

Jak widać z ActivityLifecycleCallbacks - w przypadku, gdy aktywność nie jest widoczna, application.getActiveActivity () zwraca null. Oznacza to, że żadna aktywność nie jest widoczna. Musisz to sprawdzić w swoim serwisie lub gdziekolwiek indziej.
Vit Veres,

ok .. ale w przypadku wznowienia działania nie powinno to zwracać wartości null? Moja działalność rozpoczęła się i w jej wznowieniu tak się stało
początkujący

Trudno odgadnąć, spróbuj umieścić na punkty przerwania onActivityResumed(), onActivityPaused()i getActiveActivity()zobaczyć jak to jest Callet, jeśli kiedykolwiek tak.
Vit Veres

@beginner trzeba sprawdzić, czy activityi activeActivitysą takie same przed przypisaniem activeActivityze nullaby uniknąć błędów z uwagi na przeplataną celu wywołującego metod cyklu życia różnych działań.
Rahul Tiwari

16

Nie mogłem znaleźć rozwiązania, z którego nasz zespół byłby zadowolony, więc wprowadziliśmy własne. Używamy ActivityLifecycleCallbacksdo śledzenia bieżącej aktywności, a następnie ujawniamy ją za pośrednictwem usługi:

public interface ContextProvider {
    Context getActivityContext();
}

public class MyApplication extends Application implements ContextProvider {
    private Activity currentActivity;

    @Override
    public Context getActivityContext() {
         return currentActivity;
    }

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

        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                MyApplication.this.currentActivity = activity;
            }

            @Override
            public void onActivityStarted(Activity activity) {
                MyApplication.this.currentActivity = activity;
            }

            @Override
            public void onActivityResumed(Activity activity) {
                MyApplication.this.currentActivity = activity;
            }

            @Override
            public void onActivityPaused(Activity activity) {
                MyApplication.this.currentActivity = null;
            }

            @Override
            public void onActivityStopped(Activity activity) {
                // don't clear current activity because activity may get stopped after
                // the new activity is resumed
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                // don't clear current activity because activity may get destroyed after
                // the new activity is resumed
            }
        });
    }
}

Następnie skonfiguruj kontener DI, aby zwracał instancję MyApplicationdla ContextProvidernp

public class ApplicationModule extends AbstractModule {    
    @Provides
    ContextProvider provideMainActivity() {
        return MyApplication.getCurrent();
    }
}

(Zauważ, że implementacja getCurrent()jest pominięta w powyższym kodzie. Jest to po prostu zmienna statyczna ustawiona w konstruktorze aplikacji)


4
należy sprawdzić, czy activityi currentActivitysą takie same przed przypisaniem currentActivityze nullaby uniknąć błędów z uwagi na przeplataną celu wywołującego metod cyklu życia różnych działań.
Rahul Tiwari

14

Posługiwać się ActivityManager

Jeśli chcesz tylko znać aplikację zawierającą bieżącą aktywność, możesz to zrobić za pomocą ActivityManager. Technika, której możesz użyć, zależy od wersji Androida:

Korzyści

  • Powinien działać we wszystkich dotychczasowych wersjach Androida.

Niedogodności

  • Nie działa w systemie Android 5.1+ (zwraca tylko własną aplikację)
  • Dokumentacja tych interfejsów API mówi, że są one przeznaczone wyłącznie do debugowania i zarządzania interfejsami użytkownika.
  • Jeśli chcesz otrzymywać aktualizacje w czasie rzeczywistym, musisz użyć odpytywania.
  • Opiera się na ukrytym interfejsie API: ActivityManager.RunningAppProcessInfo.processState
  • Ta implementacja nie rejestruje aktywności przełącznika aplikacji.

Przykład (na podstawie kodu KNaito )

public class CurrentApplicationPackageRetriever {

    private final Context context;

    public CurrentApplicationPackageRetriever(Context context) {
        this.context = context;
    }

    public String get() {
        if (Build.VERSION.SDK_INT < 21)
            return getPreLollipop();
        else
            return getLollipop();
    }

    private String getPreLollipop() {
        @SuppressWarnings("deprecation")
        List<ActivityManager.RunningTaskInfo> tasks =
            activityManager().getRunningTasks(1);
        ActivityManager.RunningTaskInfo currentTask = tasks.get(0);
        ComponentName currentActivity = currentTask.topActivity;
        return currentActivity.getPackageName();
    }

    private String getLollipop() {
        final int PROCESS_STATE_TOP = 2;

        try {
            Field processStateField = ActivityManager.RunningAppProcessInfo.class.getDeclaredField("processState");

            List<ActivityManager.RunningAppProcessInfo> processes =
                activityManager().getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo process : processes) {
                if (
                    // Filters out most non-activity processes
                    process.importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                    &&
                    // Filters out processes that are just being
                    // _used_ by the process with the activity
                    process.importanceReasonCode == 0
                ) {
                    int state = processStateField.getInt(process);

                    if (state == PROCESS_STATE_TOP) {
                        String[] processNameParts = process.processName.split(":");
                        String packageName = processNameParts[0];

                        /*
                         If multiple candidate processes can get here,
                         it's most likely that apps are being switched.
                         The first one provided by the OS seems to be
                         the one being switched to, so we stop here.
                         */
                        return packageName;
                    }
                }
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        return null;
    }

    private ActivityManager activityManager() {
        return (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    }

}

Oczywisty

Dodaj GET_TASKSuprawnienie do AndroidManifest.xml:

<!--suppress DeprecatedClassUsageInspection -->
<uses-permission android:name="android.permission.GET_TASKS" />

10
to nie działa już na Androidzie M. getRunningAppProcesses () zwraca teraz tylko pakiet aplikacji
Lior Iluz

1
Nie działa również w przypadku interfejsu API poziomu 22 (Android 5.1). Przetestowano na kompilacji LPB23
sumitb.mdi

9

Używam tego do moich testów. Jest to API> 19, ale tylko dla działań Twojej aplikacji.

@TargetApi(Build.VERSION_CODES.KITKAT)
public static Activity getRunningActivity() {
    try {
        Class activityThreadClass = Class.forName("android.app.ActivityThread");
        Object activityThread = activityThreadClass.getMethod("currentActivityThread")
                .invoke(null);
        Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
        activitiesField.setAccessible(true);
        ArrayMap activities = (ArrayMap) activitiesField.get(activityThread);
        for (Object activityRecord : activities.values()) {
            Class activityRecordClass = activityRecord.getClass();
            Field pausedField = activityRecordClass.getDeclaredField("paused");
            pausedField.setAccessible(true);
            if (!pausedField.getBoolean(activityRecord)) {
                Field activityField = activityRecordClass.getDeclaredField("activity");
                activityField.setAccessible(true);
                return (Activity) activityField.get(activityRecord);
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    throw new RuntimeException("Didn't find the running activity");
}

Zastąp ArrayMap mapą, a także będzie działać na 4.3. Nie testowano wcześniejszych wersji Androida.
Oliver Jonas,

2

Użyj tego kodu dla API 21 lub nowszego. Działa to i daje lepszy wynik w porównaniu do innych odpowiedzi, doskonale wykrywa proces pierwszego planu.

if (Build.VERSION.SDK_INT >= 21) {
    String currentApp = null;
    UsageStatsManager usm = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE);
    long time = System.currentTimeMillis();
    List<UsageStats> applist = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 1000, time);
    if (applist != null && applist.size() > 0) {
        SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
        for (UsageStats usageStats : applist) {
            mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);

        }
        if (mySortedMap != null && !mySortedMap.isEmpty()) {
            currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
        }
    }

Czy możesz wyjaśnić, w jaki sposób wyniki tej metody są lepsze niż inne odpowiedzi?
Sam

Czy działa to również z Menu powiadomień. Mam do czynienia z problemem, w którym jeśli otrzymam połączenie lub wiadomość. UsageStatsManager zaczyna dawać mi nazwę pakietu systemUi zamiast mojej aplikacji.
kukroid

@kukroid, opublikuj osobne pytanie i dołącz kod źródłowy, informacje o urządzeniu oraz używane aplikacje do przesyłania wiadomości i telefonu.
Sam

0

Oto moja odpowiedź, która działa dobrze ...

Powinieneś być w stanie uzyskać bieżącą Aktywność w ten sposób ... Jeśli zbudujesz aplikację z kilkoma Aktywnościami z wieloma fragmentami i chcesz śledzić, jaka jest twoja Aktywność, zajmie to jednak dużo pracy. Moim senario było to, że mam jedną Aktywność z wieloma Fragmentami. Mogę więc śledzić bieżącą aktywność za pośrednictwem obiektu aplikacji, który może przechowywać cały bieżący stan zmiennych globalnych.

Oto sposób. Kiedy zaczynasz swoją aktywność, przechowujesz ją przez Application.setCurrentActivity (getIntent ()); Ta aplikacja będzie go przechowywać. W klasie usług możesz po prostu zrobić jak Intent currentIntent = Application.getCurrentActivity (); getApplication (). startActivity (currentIntent);


2
Zakłada się, że usługa działa w tym samym procesie co działanie, prawda?
helleye

0

Nie wiem, czy to głupia odpowiedź, ale rozwiązałem ten problem, przechowując flagę we wspólnych preferencjach za każdym razem, gdy wpisywałem funkcję onCreate () dowolnej aktywności, a następnie wykorzystałem wartość z preferencji ścinania, aby dowiedzieć się, co to jest aktywność na pierwszym planie.


1
Szukamy natywnego sposobu na zrobienie tego
IgniteCoders

-3

Niedawno się o tym dowiedziałem. Z apis jako:

  • minSdkVersion 19
  • targetSdkVersion 26

    ActivityManager.getCurrentActivity (kontekst)

Mam nadzieję, że to się przyda.


1
Miałem nadzieję. Być może po udzieleniu odpowiedzi istniało, ale na razie nie ma żadnej getCurrentActivity()funkcji w ActivityManagerklasie ( developer.android.com/reference/android/app/ActivityManager ). Zabawne, że ta funkcja nie istnieje: ActivityManager.isUserAMonkey().
ByteSlinger,

1
To wykrywa, czy używasz małpiego agenta testującego do testowania swojej aktywności. Choć zabawna nazwa, może być bardzo przydatna do testowania (i rozśmieszania innych ludzi, obvs.) Developer.android.com/studio/test/monkeyrunner
Ken Corey
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.