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
여기에 설명 된대로 새 UsageStatsManager
API를 사용할 수 있지만 모든 애플리케이션에서 작동하는 것은 아닙니다. 일부 시스템 응용 프로그램은 동일한 패키지를 반환합니다.
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);