システム レベルの権限が付与されていない限り、現在 Android 5.1.1 以降でフォアグラウンド アプリを取得することはできませんandroid.permission.PACKAGE_USAGE_STATS
。いくつかの主要なベンダーは、デバイスから UsageStats API へのアクセスを許可するシステム アクティビティを削除したことに注意してください。これは、これらのデバイス上のアプリが必要なアクセス許可を取得できないことを意味します。これは、システム アップデートによって変更される可能性があります。
Smart Lock (App Protector)は Android M の現在のフォアグラウンド アクティビティを検出できるとのことでした。Smart Lock (または同様のアプリ) を初めて開くと、PACKAGE_USAGE_STATS
アクセス許可を付与するよう求められます。UsageStatsManager
したがって、フォアグラウンド アプリケーションを取得するために依存していると結論付けることができます。
システム レベルの権限なしで Android M でフォアグラウンド アプリを取得するための回避策 (ハック) を見つけようとしました。私の回答で私のスクリプトを読んで試してください: Android 5.1.1 以降 - getRunningAppProcesses() は私のアプリケーション パッケージのみを返します
ログキャット
root 権限がない限り、logcat を読み取ってフォアグラウンド アプリケーションを取得することはできません。Jelly Bean のみがアプリケーションからのログ メッセージのみを返すため、logcat を読み取る。
便利なリンク:
「android.permission.PACKAGE_USAGE_STATS」権限が与えられているかどうかを確認するには?
UsageStatsManager の使用方法
https://code.google.com/p/android-developer-preview/issues/detail?id=2347
編集:
Android ソースを掘り下げた後、許可なしで 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();
}