Android获取栈顶的应用包名方法
作者:张行之 发布时间:2023-02-02 04:14:13
标签:Android,栈顶,包名
有时候我们需要判断栈顶的应用是否是我们的应用,于是获取栈顶的应用包名的需求就出现了。
在android5.0之前,系统提供了一套API可以实现这个功能。
ActivityManager manager = (ActivityManager) getApplicationContext().getSystemService(ACTIVITY_SERVICE);
String currentClassName = manager.getRunningTasks(1).get(0).topActivity.getPackageName();
但是在android5.0之后,这个getRunningTasks()过时了,google做了限制,不让获取第三方的应用任务栈,只能获取自己的应用和Launcher桌面的包名。
当然天无绝人之路,在android5.0之后,android提供了UsageStatsManager的方式来获取栈顶的应用包名(并非直接获取,需要处理)。
UsageStatManager是一个使用情况统计管理者,通过它可以获取应用的使用情况,通过List集合来记录APP的使用情况,通过UsageStats对象可以获取包名,最后的在前台的时间,在前台的次数等等。
他需要权限:
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
这个权限是需要系统授权的,系统不授权获取不到数据。
下面看下实现案例:
ForegroundAppUtils:将获取前台包名等方法封装成一个工具类
public class ForegroundAppUtil {
private static final long END_TIME = System.currentTimeMillis();
private static final long TIME_INTERVAL = 7 * 24 * 60 * 60 * 1000L;
private static final long START_TIME = END_TIME - TIME_INTERVAL;
/**
* 获取栈顶的应用包名
*/
public static String getForegroundActivityName(Context context) {
String currentClassName = "";
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
ActivityManager manager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
currentClassName = manager.getRunningTasks(1).get(0).topActivity.getPackageName();
} else {
UsageStats initStat = getForegroundUsageStats(context, START_TIME, END_TIME);
if (initStat != null) {
currentClassName = initStat.getPackageName();
}
}
return currentClassName;
}
/**
* 判断当前应用是否在前台
*/
public static boolean isForegroundApp(Context context) {
return TextUtils.equals(getForegroundActivityName(context), context.getPackageName());
}
/**
* 获取时间段内,
*/
public static long getTotleForegroundTime(Context context) {
UsageStats usageStats = getCurrentUsageStats(context, START_TIME, END_TIME);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return usageStats != null ? usageStats.getTotalTimeInForeground() : 0;
}
return 0;
}
/**
* 获取记录前台应用的UsageStats对象
*/
private static UsageStats getForegroundUsageStats(Context context, long startTime, long endTime) {
UsageStats usageStatsResult = null;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
List<UsageStats> usageStatses = getUsageStatsList(context, startTime, endTime);
if (usageStatses == null || usageStatses.isEmpty()) return null;
for (UsageStats usageStats : usageStatses) {
if (usageStatsResult == null || usageStatsResult.getLastTimeUsed() < usageStats.getLastTimeUsed()) {
usageStatsResult = usageStats;
}
}
}
return usageStatsResult;
}
/**
* 获取记录当前应用的UsageStats对象
*/
public static UsageStats getCurrentUsageStats(Context context, long startTime, long endTime) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
List<UsageStats> usageStatses = getUsageStatsList(context, startTime, endTime);
if (usageStatses == null || usageStatses.isEmpty()) return null;
for (UsageStats usageStats : usageStatses) {
if (TextUtils.equals(usageStats.getPackageName(), context.getPackageName())) {
return usageStats;
}
}
}
return null;
}
/**
* 通过UsageStatsManager获取List<UsageStats>集合
*/
public static List<UsageStats> getUsageStatsList(Context context, long startTime, long endTime) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager manager = (UsageStatsManager) context.getApplicationContext().getSystemService(Context.USAGE_STATS_SERVICE);
//UsageStatsManager.INTERVAL_WEEKLY,UsageStatsManager的参数定义了5个,具体查阅源码
List<UsageStats> usageStatses = manager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, startTime, endTime);
if (usageStatses == null || usageStatses.size() == 0) {// 没有权限,获取不到数据
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.getApplicationContext().startActivity(intent);
return null;
}
return usageStatses;
}
return null;
}
}
在MainActivity中启动service,在service中每5秒获取一次前台应用包名。
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(getApplicationContext(),MyService.class));
}
}
MyService
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
private Handler handler = new Handler();
private Runnable r = new Runnable() {
@Override
public void run() {
String foregroundActivityName = ForegroundAppUtil.getForegroundActivityName(getApplicationContext());
Toast.makeText(getApplicationContext(), foregroundActivityName, Toast.LENGTH_SHORT).show();
handler.postDelayed(r, 5000);
}
};
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler.postDelayed(r, 5000);
return START_STICKY;
}
}
AndroidManifest.xml权限
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
来源:http://blog.csdn.net/qq_33689414/article/details/77186276


猜你喜欢
- 引言:在使用循环的时候,循环里面带有break、continue、return的时候经常弄混,今天特意整理了下,以待后用... f
- 一、Statementimport java.sql.*;public class TestJDBC { public stati
- 装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。优点:装饰类和被装饰类可以独立发展,不会相互耦合,
- 下面的这些都算是比较高级的问题了,面试中一般也很少问到,因为它们可能会把面试者拒之门外。不过你可以自己找个时间来实践一下。 1.
- 1.微信配置信息 global.properties2.方法wxpay用于生成预支付订单信息方法notifyWeiXinPay用于微信支付成
- 1. 接口是一种规范很好,你已经知道接口是一种规范了!下面这张图是我们生活中遇到的接口:电源插座接口。2. 为什么需要规范呢?因为
- public static String toUtf8String(String s) {
- 中文乱码问题真的是一个很棘手的问题,特别是从前台传到后台之后,都不知道问题出在哪里了。现在分享解决javaWEB中前后台中文乱码问题的3种方
- 1.什么是灰度发布?灰度发布又称金丝雀发布,是在系统升级的时候能够平滑过渡的一种发布方式。在其上可以进行A/B测试,即让一部分用户继续用产品
- 以往都是使用反射调用实例方法,那么反射如何调用静态方法呢?看下面的例子Class<?> threadClazz = Class.
- 引言在项目中,时间的使用必不可少,而java 8之前的时间api Date和Calander等在使用上存在着很多问题,于是,jdk1.8引进
- java 对象的克隆一、对象的浅克隆(1)需要克隆类需要重写Object类的clone方法,并且实现Cloneable接口(标识接口,无需实
- 1.二叉树的概念及结构 ①概念:一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二
- 对于使用文件进行交换数据的应用来说,使用FTP 服务器是一个很不错的解决方案。关于FileZilla Server服务器的详细搭建配置过程,
- 一、抽象类是什么?在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的
- 接上一篇文章:Android实现图片区域裁剪功能上一篇文章提及了通过调用系统相册或拍照来实现图片的缩放\裁剪。不过这对于笔者项目的要求同样不
- Java为TCP协议提供了两个类,分别在客户端编程和服务器端编程中使用它们。在应用程序开始通信之前,需要先创建一个连接,由客户端程序发起;而
- 题目一 解法/** * Definition for a binary tree node. * public class Tre
- 背景:最近需要做一个任务:C# PDF文件需要传输为JPG图片。一开始没有头绪,最后去github找到了现在我用的PdfiumViewer组
- 先给大家展示下效果图,感觉不错请参考实例代码。实现思路在flutter中,如果想实现上面的页面切换效果,必然会想到pageView。page