web-dev-qa-db-ja.com

Android "L"で最近のタスクを取得する方法は?

バックグラウンド

My app は、最近起動された時間でアプリリストを並べ替えることができます。

問題

Android "L"の時点で、関数 getRecentTasks は、 documentation に書かれているように、現在のアプリが起動したアプリ

アプリでActivityManager.getRecentTasks()を使用している場合...

次期リリースの新しい同時ドキュメントおよびアクティビティタスク機能の導入により(下記の[最近]画面の同時ドキュメントおよびアクティビティを参照)、ActivityManager.getRecentTasks()メソッドは非推奨になり、ユーザーのプライバシーが改善されました。後方互換性のために、このメソッドは、呼び出し元のアプリケーション自身のタスクや、場合によっては他の機密性の低いタスク(ホームなど)を含むデータの小さなサブセットを返します。アプリがこのメソッドを使用して独自のタスクを取得する場合は、代わりにAndroid.app.ActivityManager.getAppTasks()を使用してその情報を取得します。

ADTを使用してこの関数のドキュメントを表示するときにも同じことが書かれています(現在インターネットでは利用できません):

このメソッドは非推奨です。 Lの時点で、このメソッドはサードパーティのアプリケーションでは使用できなくなりました。ドキュメント中心の最近のものの導入により、個人情報が発信者に漏洩する可能性があるためです。下位互換性のために、データの小さなサブセットを返します:少なくとも呼び出し元のタスク(その情報を取得するためのサポートされている正しい方法についてはgetAppTasks()を参照)、およびおそらくホームなどのその他のタスク敏感ではありません。

ユーザーがどのアプリを持っているかを簡単に確認でき、許可がなくても、この行為が行われた理由はわかりません。

これは、私が追加したこの機能に対する大きな制限であるため、これを克服する方法があることを願っています。

私が試したこと

今のところ、最近起動したアプリについてヒューリスティックな方法のみを使用しました。代わりに実行中のプロセスのリストを取得します。

プロセスの重要度値と「importanceReasonComponent」を使用することもできますが、これはすべてのヒューリスティックと推測に過ぎません...

質問

この制限を克服する方法はありますか?私が考えていない回避策はありますか?

たぶんルートで可能ですか?またはBusyBox?

23

現在実行中の最上位(フォアグラウンド)パッケージ名を取得するには、Android LollipopのUsage Stats APIを使用する必要があります。

ただし、ユーザーは各アプリケーションの設定で使用データへのアクセスを承認する必要があります。したがって、設定アクションを起動して、ユーザーに直接設定を促す必要があります

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);

トップパッケージ名を取得するには:

String topPackageName ;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) { 
    UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService("usagestats");                       
    long time = System.currentTimeMillis(); 
    // We get usage stats for the last 10 seconds
    List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*10, time);                                    
    // Sort the stats by the last time used
    if(stats != null) {
        SortedMap<Long,UsageStats> mySortedMap = new TreeMap<Long,UsageStats>();
        for (UsageStats usageStats : stats) {
            mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
        }                    
        if(!mySortedMap.isEmpty()) {
            topPackageName =  mySortedMap.get(mySortedMap.lastKey()).getPackageName();                                   
        }                                       
    }
}
34
user3742392

UsageStatsを使用して現在のフォアグラウンドパッケージを取得する場合、ユーザーが通知ドロワーを開いたとき、またはロックされた画面で間違った情報を取得します。 (Android LollipopとMarshmallowの両方でテスト済み)

UsageStatsManager.queryEvents()を使用し、現在のフォアグラウンドパッケージを決定するために、MOVE_TO_FOREGROUNDイベントタイプで最新のイベントを探す必要があります。

6
Sam Lu

@ user3742392の回答は良いですが、TreeMapを使用して最後に使用した時間を見つけるのは少しやり過ぎです(特に、実行中のアプリを定期的にチェックする場合)。

代わりに、単純なループを使用したTreeMapを使用しない編集済みの回答を次に示します。

String topPackageName;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
    UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService("usagestats");
    long currentTime = System.currentTimeMillis();
    // get usage stats for the last 10 seconds
    List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, currentTime - 1000 * 10, currentTime);
    // search for app with most recent last used time
    if (stats != null) {
        long lastUsedAppTime = 0;
        for (UsageStats usageStats : stats) {
            if (usageStats.getLastTimeUsed() > lastUsedAppTime) {
                topPackageName = usageStats.getPackageName();
                lastUsedAppTime = usageStats.getLastTimeUsed();
            }
        }
    }
}
2
stevo.mit

Lollipopはこのメソッドを廃止しました。ただし、アプリの使用状況を表示できる新しいAPIがあります。このメソッドは、セキュリティ上の問題により廃止されました。 :\

UsageStatsManagerには、一定の時間間隔でアクティビティを確認するための便利なメソッドがいくつかあります。これでニーズが満たされることを願っています!

https://developer.Android.com/reference/Android/app/usage/package-summary.html

1
Atish