Android : 서비스에서 현재 포 그라운드 활동을 얻으려면 어떻게해야합니까?


180

서비스에서 현재 실행중인 활동에 대한 참조를 얻는 기본 안드로이드 방법이 있습니까?

백그라운드에서 서비스를 실행하고 있으며 서비스에서 이벤트가 발생할 때 현재 활동을 업데이트하고 싶습니다. (위에서 제안한 것과 같은) 쉬운 방법이 있습니까?


아마도 이것은 당신에게 아이디어를 줄 수 있습니다 stackoverflow.com/a/28423385/185022
AZ_

답변:


87

서비스에서 현재 실행중인 활동에 대한 참조를 얻는 기본 안드로이드 방법이 있습니까?

"현재 실행중인 활동"을 소유 할 수 없습니다.

백그라운드에서 서비스를 실행하고 있으며 서비스에서 이벤트가 발생할 때 현재 활동을 업데이트하고 싶습니다. (위에서 제안한 것과 같은) 쉬운 방법이 있습니까?

  1. 방송 Intent을 활동으로 보내기 - 이 패턴을 보여주는 샘플 프로젝트 는 다음과 같습니다.
  2. 활동 이 서비스가 호출 하는 PendingIntent(예 :을 통해 createPendingResult()) 제공하도록하십시오
  3. 활동이 다음을 통해 서비스에 콜백 또는 리스너 객체를 등록하도록합니다. bindService() 하고 서비스가 해당 콜백 / 리스너 객체에서 이벤트 메소드를 호출하도록합니다.
  4. 백업 Intent으로 우선 순위가 낮은 주문형 브로드 캐스트 를 활동에 전송 하십시오 (활동이 화면에없는 경우 BroadcastReceiver증가시키기 위해 Notification) .이 패턴에 대해 더 많은 블로그 게시물 이 있습니다.

3
고마워하지만 액티비티가 많고 모두 업데이트하고 싶지 않기 때문에 foregroundActivity를 얻는 안드로이드 방법을 찾고있었습니다. 당신이 말했듯이, 나는 그렇게 할 수 없어야합니다. 이 문제를 해결해야 함을 의미합니다.
조지

1
@George : 당신이 원하는 것은 어쨌든 도움이되지 않을 것입니다. 지적했듯이 "활동의 전리품"이 있습니다. 따라서 이들은 모두 별도의 클래스입니다. 따라서 방대한 if-block instanceof점검이나 공통 수퍼 클래스 또는 인터페이스를 공유하기 위해 활동을 리팩토링 하지 않고는 서비스로 수행 할 수있는 작업이 없습니다 . 또한 활동을 리팩토링하려면 프레임 워크에 더 적합하고 활동이없는 것과 같은 더 많은 시나리오를 다루는 방식으로 수행 할 수도 있습니다. # 4는 아마도 가장 작고 가장 유연 할 것입니다.
CommonsWare

2
고맙지 만 더 나은 해결책이 있습니다. 모든 활동은 사용자 정의 된 BaseActivity 클래스를 확장합니다. 포 그라운드에있을 때마다 활동을 현재로 등록하는 ContextRegister를 설정했습니다 .BaseActivity 클래스에는 3 줄이 있습니다. 여전히 지원해 주셔서 감사합니다.
George

3
@George : 메모리 누수를 조심하십시오. 가변 정적 데이터 멤버는 가능하면 Java에서 피해야합니다.
CommonsWare

나는 실제로 이것을 명심할 것이지만, 나는 그 대상을 단단히 캡슐화했다. 감사.
조지

139

업데이트 :이 더 이상 작동하지 않습니다 와 함께 Android 5.0부터 다른 앱 활동


활동 관리자를 사용하여이를 수행하는 좋은 방법이 있습니다. 기본적으로 활동 관리자에서 runningTasks를 얻습니다. 항상 현재 활성화 된 작업을 먼저 반환합니다. 거기에서 topActivity를 얻을 수 있습니다.

여기 예

ActivityManager 서비스에서 실행중인 작업 목록을 얻는 쉬운 방법이 있습니다. 전화기에서 실행중인 최대 작업 수를 요청할 수 있으며 기본적으로 현재 활성화 된 작업이 먼저 반환됩니다.

일단 당신이 당신의 목록에서 topActivity를 요청하여 ComponentName 객체를 얻을 수 있습니다.

다음은 예입니다.

    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();

매니페스트에 대해 다음 권한이 필요합니다.

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

3
귀하의 답변은 100 % 정확합니다 .Thanxx 4 it. 여기에 같은 답변을 게시하는 것이 좋습니다
Shahzad Imam

1
@ArtOfWarfare는 확인하지 않았지만 예, 하나의 활동으로 항상 호스팅되므로 조각 수는 관련이 없습니다.
넬슨 라미레즈

2
현재 활동이 더 자주 필요한 경우 매우 자주 설문 조사를해야합니까? 포 그라운드 활동이 변경 될 때마다 콜백 이벤트를 얻는 방법이 있습니까?
nizam.sp

43
모든 사람들이 알고 있듯이 문서는 getRunningTasks () 메소드에 대해 이것을 설명합니다. -------- 참고 :이 방법은 작업 관리 사용자 인터페이스를 디버깅하고 표시하기위한 것입니다. 여기에 나와있는 정보에 따라 다른 동작을 결정하는 것과 같이 응용 프로그램의 핵심 논리에 사용해서는 안됩니다. 이러한 사용은 지원되지 않으며 향후 중단 될 수 있습니다. 예를 들어, 여러 응용 프로그램을 동시에 활발하게 실행할 수있는 경우 제어 흐름을 목적으로 여기에서 데이터의 의미에 대한 가정은 올바르지 않습니다. ------------
Ryan

30
api 21에서 As 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.
준결승

115

경고 : Google Play 위반

Google은 접근성이 아닌 목적으로 접근성 서비스를 사용하는 경우 Play 스토어에서 앱을 삭제 하겠다고 위협 했습니다. 그러나 이것은보고 된 바있다 .


사용 AccessibilityService

혜택

  • Android 7.1 (API 25)을 통해 Android 2.2 (API 8)에서 테스트 및 작동
  • 폴링이 필요하지 않습니다.
  • GET_TASKS권한이 필요하지 않습니다 .

단점

  • 각 사용자는 Android의 접근성 설정에서 서비스를 활성화해야합니다.
  • 이것은 100 % 신뢰할 수 없습니다. 때때로 이벤트는 순서가 맞지 않습니다.
  • 서비스는 항상 실행 중입니다.
  • 사용자가을 활성화하려고 AccessibilityService하면 앱이 화면에 오버레이를 배치 한 경우 확인 버튼을 누를 수 없습니다. 이를 수행하는 일부 앱은 Velis Auto Brightness 및 Lux입니다. 사용자가 버튼을 누를 수없는 이유 또는 해결 방법을 모르기 때문에 혼동 될 수 있습니다.
  • AccessibilityService처음 할 때까지 현재의 활동을 알 수 없습니다 변화 활동을.

서비스

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

이것을 매니페스트에 병합하십시오.

<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>

서비스 정보

이것을 넣으십시오 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"/>

서비스 활성화

앱의 각 사용자는 앱을 사용하려면 명시 적으로 활성화해야합니다 AccessibilityService. 작업을 수행하는 방법 은 이 StackOverflow 답변 을 참조하십시오 .

앱이 Velis Auto Brightness 또는 Lux와 같은 화면에 오버레이를 배치 한 경우 사용자는 접근성 서비스를 활성화하려고 할 때 확인 버튼을 누를 수 없습니다.


1
@lovemint, 의미는 :의 예 settingsActivity를 지정 your.app.ServiceSettingsActivity했으므로 접근성 서비스에 대한 설정 활동으로 변경해야합니다. 어쨌든 설정 활동은 선택 사항이라고 생각하므로 더 간단하게하기 위해 답변에서 해당 부분을 제거했습니다.
Sam

1
고마워요, 마지막 질문입니다. API 8에서 현재까지 처리 해야하는 경우 XML을 사용하는 대신 코드에서 작동해야합니까?
paolo2988

1
@ lovemint, 맞습니다. 방금 예제 코드를 업데이트했습니다.
Sam

1
@Sam이 서비스가 완벽하게 작동 함을 확인할 수 있습니다. 이상한 행동 하나, 나는 주요 활동의 의도를 사용하여 접근성 서비스를 활성화했습니다. 이 첫 번째 활성화 후 서비스가 활성화되었지만 onAccessibilityEvent이벤트를받지 못하지만 접근성 서비스를 비활성화했다가 다시 활성화하면 서비스가 다시 활성화되고 onAccessibilityEvent작동하기 시작합니다.
paolo2988

2
코드 감사합니다. 나는 당신을 위해이 앱 을 만들었습니다 :)
vault

20

다음을 수행 할 수 있습니다.

  1. 자체 애플리케이션 클래스를 구현하고 ActivityLifecycleCallbacks에 등록하십시오.이를 통해 앱에서 진행중인 작업을 확인할 수 있습니다. 다시 시작할 때마다 콜백은 화면에 현재 보이는 활동을 할당하고 일시 중지하면 할당을 제거합니다. registerActivityLifecycleCallbacks()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. 서비스 요청시 getApplication()앱 클래스 이름 (이 경우 앱)으로 캐스트하십시오. 당신이 호출 할 수있는 것보다 app.getActiveActivity()-그것은 당신에게 현재 보이는 활동을 줄 것입니다 (또는 활동이 보이지 않으면 null입니다). 당신은 전화하여 활동의 이름을 얻을 수 있습니다activeActivity.getClass().getSimpleName()


1
나는 activeActivity.getClass ()에서 Nullpointer의 예외에 무엇입니까 getSimpleName ()을 당신이 도와주세요 수 있습니다..
초보자

ActivityLifecycleCallbacks에서 볼 수 있듯이 활동이 표시되지 않는 경우 application.getActiveActivity ()는 null을 반환합니다. 즉, 활동이 보이지 않습니다. 서비스 나 다른 곳에서이를 확인해야합니다.
Vit Veres

ok .. 그러나 활동이 재개되면 null을 반환해서는 안됩니다 ?? 내 활동이 시작되었고 그 이력서에 도착했습니다
초보자

하드에 중단 점을 넣어하려고 생각합니다 onActivityResumed(), onActivityPaused()하고 getActiveActivity()지금까지 그렇다면, 그것은 callet하는 방법을 참조하십시오.
Vit Veres

@beginner 한 경우 확인해야 activity하고 activeActivity할당하기 전에 동일 activeActivitynull인해 다양한 활동의 라이프 사이클 방식의 혼합 된 호출 순서를 피하기 오류를 위해.
Rahul Tiwari

16

우리 팀이 만족할만한 해결책을 찾을 수 없었으므로 우리는 우리 자신을 굴 렸습니다. 우리는 사용ActivityLifecycleCallbacks 는 현재 활동을 추적 한 다음 서비스를 통해 노출합니다.

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
            }
        });
    }
}

그런 다음 반환 인스턴스에 DI 컨테이너를 구성 MyApplication하기위한 ContextProvider, 예를 들어,

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

( getCurrent()위의 코드에서는 구현 이 생략되었습니다. 응용 프로그램 생성자에서 설정 한 정적 변수 일뿐입니다.)


4
한 경우 확인해야 activity하고 currentActivity할당하기 전에 동일 currentActivitynull인해 다양한 활동의 라이프 사이클 방식의 혼합 된 호출 순서를 피하기 오류를 위해.
Rahul Tiwari

14

사용하다 ActivityManager

현재 활동이 포함 된 응용 프로그램 만 알고 싶다면을 사용하면 ActivityManager됩니다. 사용할 수있는 기술은 Android 버전에 따라 다릅니다.

혜택

  • 현재 모든 Android 버전에서 작동합니다.

단점

  • Android 5.1 이상에서는 작동하지 않습니다 (자신의 앱만 반환)
  • 이 API에 대한 설명서 디버깅 및 관리 사용자 인터페이스만을위한 것입니다.
  • 실시간 업데이트를 원할 경우 폴링을 사용해야합니다.
  • 숨겨진 API에 의존 ActivityManager.RunningAppProcessInfo.processState
  • 이 구현은 앱 스위처 활동을 선택하지 않습니다.

예 ( 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);
    }

}

명백한

다음에 GET_TASKS권한을 추가하십시오 AndroidManifest.xml.

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

10
이것은 더 이상 Android M에서 작동하지 않습니다. getRunningAppProcesses ()는 이제 응용 프로그램 패키지 만 반환합니다
Lior Iluz

1
API 레벨 22 (Android 5.1)에서도 작동하지 않습니다. 빌드 LPB23에서 테스트
sumitb.mdi

9

나는 이것을 테스트에 사용하고 있습니다. API> 19이며 앱 활동 에만 해당됩니다 .

@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");
}

ArrayMap을 Map으로 바꾸면 4.3에서도 작동합니다. 이전 Android 버전에서는 테스트되지 않았습니다.
Oliver Jonas

2

API 21 이상에이 코드를 사용하십시오. 이것은 작동하고 다른 답변에 비해 더 나은 결과를 제공하며 전경 프로세스를 완벽하게 감지합니다.

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();
        }
    }

이 방법의 결과가 다른 답변보다 나은 점에 대해 자세히 설명해 주시겠습니까?
Sam

알림 메뉴에서도 작동합니다. 전화 나 메시지를받는 문제에 직면하고 있습니다. UsageStatsManager가 내 앱 대신 systemUi의 패키지 이름을 제공하기 시작합니다.
kukroid

@kukroid에서 별도의 질문을 게시하고 소스 코드, 장치 정보 및 사용중인 메시징 및 전화 앱을 포함하십시오.
Sam

0

잘 작동하는 내 대답은 다음과 같습니다.

이런 식으로 현재 활동을 얻을 수 있어야합니다 ... 조각이 많은 활동을 몇 가지로하여 앱을 구성하고 현재 활동을 추적하려는 경우 많은 작업이 필요합니다. 나의 상원은 여러 조각으로 하나의 활동을 가지고 있다는 것이었다. 따라서 전역 변수의 현재 상태를 모두 저장할 수있는 응용 프로그램 개체를 통해 현재 활동을 추적 할 수 있습니다.

방법이 있습니다. 활동을 시작하면 Application.setCurrentActivity (getIntent ()); 이 응용 프로그램은 그것을 저장합니다. 서비스 클래스에서 Intent currentIntent = Application.getCurrentActivity (); getApplication (). startActivity (currentIntent);


2
이것은 서비스가 활동과 동일한 프로세스에서 실행된다고 가정합니다.
helleye

0

나는 그것이 멍청한 대답인지 모르겠지만, 활동의 onCreate ()를 입력 할 때마다 공유 환경 설정에 플래그를 저장 하여이 문제를 해결했습니다.


1
우리는 그것을 할 수있는 기본 방법을 찾고 있습니다
IgniteCoders

-3

최근에 이것에 대해 알게되었습니다. API를 다음과 같이 사용하십시오.

  • minSdk 버전 19
  • targetSdk 버전 26

    ActivityManager.getCurrentActivity (컨텍스트)

이것이 어떤 용도로 사용되기를 바랍니다.


1
내 희망이 있었다. 아마도 이것이 대답했을 때 존재했지만 현재로서는 클래스에 getCurrentActivity()기능 이 없습니다 ActivityManager( developer.android.com/reference/android/app/ActivityManager ). 이 기능이 존재한다는 것은 재미있다 : ActivityManager.isUserAMonkey().
ByteSlinger

1
원숭이 테스트 에이전트를 사용하여 활동을 테스트하고 있는지 감지합니다. 재밌는 이름이지만, 테스트하고 다른 사람들을 웃게 만드는데도 유용합니다. developer.android.com/studio/test/monkeyrunner
Ken Corey
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.