Android 5.1.1 이상-getRunningAppProcesses ()는 내 애플리케이션 패키지 만 반환합니다. {

Google은 마침내 현재 포 그라운드 애플리케이션 패키지를 얻기 위해 모든 문을 닫은 것 같습니다.

이 답변getRunningTasks(int maxNum) 덕분에 Lollipop 업데이트 후 Lollipop 이후 포 그라운드 애플리케이션 패키지를 가져 오는 데이 코드를 사용했습니다.

final int PROCESS_STATE_TOP = 2;
RunningAppProcessInfo currentInfo = null;
Field field = null;
try {
    field = RunningAppProcessInfo.class.getDeclaredField("processState");
} catch (Exception ignored) {
}
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
for (RunningAppProcessInfo app : appList) {
    if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
        app.importanceReasonCode == 0 ) {
        Integer state = null;
        try {
            state = field.getInt( app );
        } catch (Exception ignored) {
        }
        if (state != null && state == PROCESS_STATE_TOP) {
            currentInfo = app;
            break;
        }
    }
}
return currentInfo;

Android 5.1.1 이상 (6.0 Marshmallow)도 종료 된 것 같습니다 getRunningAppProcesses(). 이제 자체 애플리케이션 패키지 목록을 반환합니다.


UsageStatsManager

여기에 설명 된대로UsageStatsManagerAPI를 사용할 수 있지만 모든 애플리케이션에서 작동하는 것은 아닙니다. 일부 시스템 응용 프로그램은 동일한 패키지를 반환합니다.

com.google.android.googlequicksearchbox

AccessibilityService (2017 년 12 월 : Google에서 사용 금지 예정)

일부 응용 프로그램은 AccessibilityService( 여기 에서 볼 수 있듯이 ) 사용하지만 몇 가지 단점이 있습니다.


현재 실행중인 애플리케이션 패키지를 가져 오는 다른 방법이 있습니까?



답변

Android 1.6-Android 6.0에서 실행중인 프로세스 목록을 얻으려면 내가 작성한이 라이브러리를 사용할 수 있습니다. https://github.com/jaredrummler/AndroidProcesses 라이브러리는 프로세스 정보를 얻기 위해 / proc을 읽습니다.

Google은 Android Nougat에서 / proc에 대한 액세스를 크게 제한했습니다. Android Nougat에서 실행중인 프로세스 목록을 얻으려면 UsageStatsManager를 사용하거나 루트 액세스 권한이 있어야합니다.

이전 대체 솔루션에 대한 편집 내역을 클릭하십시오.


답변

 private String printForegroundTask() {
    String currentApp = "NULL";
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
        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();
            }
        }
    } else {
        ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
        currentApp = tasks.get(0).processName;
    }

    Log.e("adapter", "Current App in foreground is: " + currentApp);
    return currentApp;
}

이 방법을 사용하여 포 그라운드 작업을 가져옵니다. 시스템 권한 “android : get_usage_stats”가 필요합니다.

public static boolean needPermissionForBlocking(Context context){
    try {
        PackageManager packageManager = context.getPackageManager();
        ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
        AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
        return  (mode != AppOpsManager.MODE_ALLOWED);
    } catch (PackageManager.NameNotFoundException e) {
        return true;
    }
}

사용자가 설정-> 보안-> 사용 액세스 권한이있는 앱에서이를 활성화하는 경우. 그 후 u는 포 그라운드 작업을 받게됩니다. 유사 프로세스 Clean matser by Cheetahamobile
google play link


답변

https://github.com/ricvalerio/foregroundappchecker를 살펴보면 필요한 것일 수 있습니다. 샘플 코드를 제공하고 교차 버전 전경 감지기를 구현해야하는 번거 로움을 제거합니다.

다음은 두 가지 샘플입니다.

AppChecker appChecker = new AppChecker();
String packageName = appChecker.getForegroundApp();

또는 정기적으로 확인하십시오.

AppChecker appChecker = new AppChecker();
appChecker
    .when("com.other.app", new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .when("com.my.app", new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .other(new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .timeout(1000)
    .start(this);


답변

Google은 시스템 앱에 대해서만이 기능을 제한했습니다. 버그 티켓 에보고 된대로 여기에 액세스 하려면 REAL_GET_TASKS 권한 이 필요합니다 .

모든 애플리케이션에 대한 프로세스 정보를 가져올 수 있으려면 애플리케이션에 … permission.REAL_GET_TASKS가 있어야합니다. 앱에 권한이없는 경우 호출 애플리케이션에 대한 프로세스 정보 만 반환됩니다. 권한 앱은 새 권한이 없지만 더 이상 사용되지 않는 … permission.GET_TASKS가있는 모든 애플리케이션에 대한 프로세스 정보를 일시적으로 가져올 수 있습니다. 또한 시스템 앱만 REAL_GET_TASKS 권한을 얻을 수 있습니다.


답변

내가 상상하는 것에 대한 잠재적 인 최적화를 버리는 것은 Android M에서 최상위 애플리케이션을 감지하기 위해 많이 복사하여 붙여 넣은 코드입니다.

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
    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();
        }
    }
}

이것으로 단순화 할 수 있습니다

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    UsageStatsManager usm = (UsageStatsManager) context.getSystemService(
        Context.USAGE_STATS_SERVICE);
    long time = System.currentTimeMillis();
    List<UsageStats> appStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
            time - 1000 * 1000, time);
    if (appStatsList != null && !appStatsList.isEmpty()) {
        currentApp = Collections.max(appStatsList, (o1, o2) ->
            Long.compare(o1.getLastTimeUsed(), o2.getLastTimeUsed())).getPackageName();
    }
}

이 코드를 2 초 루프에서 사용하는 것을 발견했고 O (n) 인 Collections.max ()에서 더 간단한 솔루션을 사용할 수있을 때 O (n * log (n)) 인 복잡한 솔루션을 사용하는 이유가 궁금했습니다. ).


답변

public class AccessibilityDetectingService 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(final AccessibilityEvent event) {
        if (event == null ) {
            return;
        } else if(event.getPackageName() == null && event.getClassName() == null){
            return;
        }

            if (activityInfo != null){

                Log.d("CurrentActivity", componentName.flattenToShortString());
        }

}

private ActivityInfo tryGetActivity(ComponentName componentName) {
    try {
        return getPackageManager().getActivityInfo(componentName, 0);
    } catch (PackageManager.NameNotFoundException e) {
        return null;
    }
}
@Override
public void onInterrupt() {
}
}
}//`enter code here`uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.GET_TASKS" />

그런 다음 장치 설정-> 접근성-> 해당 서비스의 앱에서 서비스 및 앱 접근성을 시작합니다.


답변

방법 getRunningServices()대신 사용 해보세요 getRunningAppProcesses().

 ActivityManager mActivityManager = (ActivityManager) getSy stemService(Context.ACTIVITY_SERVICE);

 List<ActivityManager.RunningServiceInfo> appProcessInfoList = mActivityManager.getRunningServices(Integer.MAX_VALUE);