15

私は現在、店舗でコマーシャルを表示するタブレット用のアプリを開発しています。設定アプリケーションにパスワード保護を追加する必要があります。これを実現するには、設定アプリがバックグラウンド サービスで開始されたことを検出する必要があります。API 21 未満の Android を搭載したデバイスの場合、これはgetRunningTasks()で実行できます。残念ながら、このメソッドは現在非推奨です。この回答で目標を達成しようとしましたが、必要に応じて機能していません。リッスンしようとしてV/WindowManager( 740): Adding window Window{1f4535ef u0 com.android.settings/com.android.settings.Settings} at 9 of 16 (before Window{e14eed2 u0 Starting com.android.settings})いますが、出力として表示されません。上記で参照した回答のコードを使用しています。トーストする代わりに、logcat に出力しています。

API 21 より上の Android バージョンで私の目標を達成する方法を教えてください。Smart AppLock のようなアプリがそれを行うため、それが可能であることはわかっています。前もって感謝します!

4

1 に答える 1

7

システム レベルの権限が付与されていない限り、現在 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();
}
于 2015-09-12T09:06:15.290 に答える