Ответ 1
В настоящее время невозможно получить приложение foreground на Android 5.1.1+, если вам не предоставлено разрешение на уровне системы android.permission.PACKAGE_USAGE_STATS
. Обратите внимание, что несколько крупных поставщиков удалили системную активность, которая предоставляет доступ к API UsageStats с их устройств. Это означает, что приложения на этих устройствах никогда не смогут получить необходимое разрешение. Это может измениться при обновлении системы.
Вы упомянули, что Smart Lock (App Protector) может обнаружить текущую активность переднего плана на Android M. При первом запуске Smart Lock ( или аналогичные приложения) вам предлагается предоставить разрешение PACKAGE_USAGE_STATS
. Поэтому мы можем заключить, что они полагаются на UsageStatsManager
, чтобы получить приложение переднего плана.
Я попытался найти обходное решение (взломать), чтобы получить приложение переднего плана на Android M без разрешения на системном уровне. Пожалуйста, прочтите и попробуйте мой script в моем ответе здесь: Android 5.1.1 и выше - getRunningAppProcesses() возвращает только мой пакет приложений
Logcat
Если у вас нет прав на root, чтение логарифма для получения приложения переднего плана не будет работать. Чтение logcat, поскольку Jelly Bean возвращает только сообщения журнала из вашего приложения.
Полезные ссылки:
Как проверить, есть ли & android.permission.PACKAGE_USAGE_STATS " разрешение указано?
Как использовать UsageStatsManager?
https://code.google.com/p/android-developer-preview/issues/detail?id=2347
Edit:
После ротации через Android-источник я написал следующий код, чтобы получить приложение foreground на Android M без каких-либо разрешений. Я тестировал его только на Nexus 9 с последним предварительным просмотром разработчика. Скопируйте и вставьте код в класс в свой проект и проверьте его, вызвав статический метод getForegroundApp()
:
/** first app user */
public static final int AID_APP = 10000;
/** offset for uid ranges for each user */
public static final int AID_USER = 100000;
public static String getForegroundApp() {
File[] files = new File("/proc").listFiles();
int lowestOomScore = Integer.MAX_VALUE;
String foregroundProcess = null;
for (File file : files) {
if (!file.isDirectory()) {
continue;
}
int pid;
try {
pid = Integer.parseInt(file.getName());
} catch (NumberFormatException e) {
continue;
}
try {
String cgroup = read(String.format("/proc/%d/cgroup", pid));
String[] lines = cgroup.split("\n");
if (lines.length != 2) {
continue;
}
String cpuSubsystem = lines[0];
String cpuaccctSubsystem = lines[1];
if (!cpuaccctSubsystem.endsWith(Integer.toString(pid))) {
// not an application process
continue;
}
if (cpuSubsystem.endsWith("bg_non_interactive")) {
// background policy
continue;
}
String cmdline = read(String.format("/proc/%d/cmdline", pid));
if (cmdline.contains("com.android.systemui")) {
continue;
}
int uid = Integer.parseInt(
cpuaccctSubsystem.split(":")[2].split("/")[1].replace("uid_", ""));
if (uid >= 1000 && uid <= 1038) {
// system process
continue;
}
int appId = uid - AID_APP;
int userId = 0;
// loop until we get the correct user id.
// 100000 is the offset for each user.
while (appId > AID_USER) {
appId -= AID_USER;
userId++;
}
if (appId < 0) {
continue;
}
// u{user_id}_a{app_id} is used on API 17+ for multiple user account support.
// String uidName = String.format("u%d_a%d", userId, appId);
File oomScoreAdj = new File(String.format("/proc/%d/oom_score_adj", pid));
if (oomScoreAdj.canRead()) {
int oomAdj = Integer.parseInt(read(oomScoreAdj.getAbsolutePath()));
if (oomAdj != 0) {
continue;
}
}
int oomscore = Integer.parseInt(read(String.format("/proc/%d/oom_score", pid)));
if (oomscore < lowestOomScore) {
lowestOomScore = oomscore;
foregroundProcess = cmdline;
}
} catch (IOException e) {
e.printStackTrace();
}
}
return foregroundProcess;
}
private static String read(String path) throws IOException {
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(new FileReader(path));
output.append(reader.readLine());
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
output.append('\n').append(line);
}
reader.close();
return output.toString();
}