有没有办法获取当前正在运行或已打开的Android应用程序的列表,以便我可以找到在设备中运行的最后一个应用程序。感谢
答案 0 :(得分:1)
我很快就开始使用表情符号键盘了。我需要三天的时间来获取前景应用程序包名称以发送表情符号图像,因为每当我想发送图像时,它只需弹出intentchooser
来选择一个可以处理图像作为附加功能的应用程序。
所有教程和链接都不适用于我,因为谷歌弃用了用于获取当前正在运行的应用程序的getRunningTasks()
方法。
然后我有一个绝妙的想法,即使用ResolveInfo
在设备上获取当前正在运行的应用程序的堆栈,但它无效。
最后,我在API 21中引入了一个名为UsageStatsManager
的新类,它对我有用。 This github link提供了如何使用此类来获取正在运行的应用程序包名称。
以下是我的代码如何在顶部运行包名称应用程序:
public class UStats {
public static final String TAG = UStats.class.getSimpleName();
@SuppressLint("SimpleDateFormat")
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("M-d-yyyy HH:mm:ss");
public static ArrayList<String> printCurrentUsageStatus(Context context) {
return printUsageStats(getUsageStatsList(context));
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static ArrayList<String> printUsageStats(List<UsageStats> usageStatsList) {
HashMap<String, Integer> lastApp = new HashMap<String, Integer>();
for (UsageStats u : usageStatsList) {
lastApp.put(u.getPackageName(), (int) u.getLastTimeStamp());
/*Log.d(TAG, "Pkg: " + u.getPackageName() + "\t" + "ForegroundTime: "
+ u.getTotalTimeInForeground() + "\t" + "LastTimeStamp: " + new Date(u.getLastTimeStamp()));*/
}
Map<String, Integer> sortedMapAsc = sortByComparator(lastApp);
ArrayList<String> firstApp = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedMapAsc.entrySet()) {
String key = entry.getKey();
//Integer value = entry.getValue();
firstApp.add(key);
/*System.out.println("package name: " + key + ", time " + new Date(Math.abs(value)));*/
}
return firstApp;
}
// To check the USAGE_STATS_SERVICE permission
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static List<UsageStats> getUsageStatsList(Context context) {
UsageStatsManager usm = getUsageStatsManager(context);
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.MINUTE, -1);
long startTime = calendar.getTimeInMillis();
Log.d(TAG, "Under getUsageStateList");
Log.d(TAG, "Range start:" + dateFormat.format(startTime));
Log.d(TAG, "Range end:" + dateFormat.format(endTime));
List<UsageStats> usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, endTime);
return usageStatsList;
}
// Sort the map in the ascending order of the timeStamp
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap) {
List<Map.Entry<String, Integer>> list = new LinkedList<>(unsortMap.entrySet());
// Sorting the list based on values
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> o1,
Map.Entry<String, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
// Maintaining insertion order with the help of LinkedList
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Map.Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
@SuppressWarnings("ResourceType")
private static UsageStatsManager getUsageStatsManager(Context context) {
UsageStatsManager usm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
return usm;
}
}
然后我只需使用以下代码获取应用程序包名称的ArrayList:
ArrayList<String> sortedApplication = UStats.printCurrentUsageStatus(SimpleIME.this);
Log.d("TAG", "applicationList: " + sortedApplication.toString());
不要忘记添加权限:
<uses-permission android:name = "android.permission.PACKAGE_USAGE_STATS"
tools:ignore = "ProtectedPermissions"/>
以下代码检查我们的应用程序是否有权获取其他应用程序状态:
if (UStats.getUsageStatsList(this).isEmpty()) {
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
Toast.makeText(MainActivity.this, "Enable Usage Access for YOUR_APP_NAME to use this app", Toast.LENGTH_LONG).show();
startActivity(intent);
}
上面的代码将打开一个访问设置页面,使我们的应用程序能够获取其他应用程序使用情况统计信息(一次)。
希望这会有所帮助。
答案 1 :(得分:-1)
我使用以下代码块查看系统中安装的软件包名称的实际列表:
try {
Process process = Runtime.getRuntime().exec("pm list packages");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = bufferedReader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
bufferedReader.close();
process.waitFor();
Log.d("your tag", output.toString());
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
我确信通过软件包和PID,您可以在ADB Shell控制台中修改命令以查找有关应用程序列表的时间信息,但是我认为您看不到系统上最后一个打开的应用程序,尽管我不知道Shell控制台使用的所有命令...
Runtime.getRuntime().exec("top -n 1 -d 1");
例如,此命令显示设备中不同的进程及其资源消耗。
在以下文档中遇到它们:https://developer.android.com/studio/command-line
相关:
答案 2 :(得分:-2)
如果您希望它具有更高的反应性,我实际上只是通过LiveData处理类似的情况。看看我有关它的博客文章:https://bmcreations.dev/blog/foreground-app-observing-with-lifecycle-components