I need to know when a specific app is in the background (not foreground).
I was able to get package name of all the applications running in the background with this code:
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(ACTIVITY_SERVICE);
// Process running
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService(USAGE_STATS_SERVICE);
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);
Log.d("RunningAppProcessInfo","Package name : "+usageStats.getPackageName());
}
}
}
But now how do I check if the specific app is on the list or not?
Thanks
If you want to check Specific Package than check below code I have added code in below method.
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(ACTIVITY_SERVICE);
// Process running
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService(USAGE_STATS_SERVICE);
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);
Log.d("RunningAppProcessInfo","Package name : "+usageStats.getPackageName());
if(usageStats.getPackageName().equals("package name")) {
Log.d("Package ","Package name : Success");
}
}
}
}
Related
In Android 6.0 Marshmallow I query for the foreground app with the following code but there was a problem with incoming notifications because it shows foreground app to the app which sends notification. The problem exists only in Marshmallow (5.X works correctly).
// API 21 and above
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static String getProcessNew(UsageStatsManager mUsageStatsManager, Context c) throws Exception {
String st = null;
try {
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000 * 10;
// We get usage stats for the last minute
List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, beginTime,
endTime);
// 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 != null && !mySortedMap.isEmpty()) {
st = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
} catch (Exception e) {
Log.d("main", "Wxxxxexx " + e);
}
return st;
}
and then notification problem is solved using solution from this answer UsageEvents.
As solution in answer I put the code and its working to get Foreground app but it delayed by 3 seconds. My service is checking foreground app and is repeating every 500ms but whatsapp package detects after 3 seconds of starting whatsapp. this is code of UsageEvents i use from above solution.
if (BuildV >= 23) {
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000 * 10;
UsageEvents usageEvents = mUsageStatsManager.queryEvents(beginTime, endTime);
UsageEvents.Event event = new UsageEvents.Event();
while (usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event);
}
if (st.equals(event.getPackageName())
&& event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
pack = st;
}
}
I'm using below code to get Top Activity
private String getTopPackageName() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return activityManager.getRunningTasks(1).get(0).topActivity.getPackageName();
} else {
final List<ActivityManager.RunningAppProcessInfo> pis = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo pi : pis) {
if (pi.pkgList.length == 1) return pi.pkgList[0];
}
}
return "";
}
It word on API<21 but API>=21 it return "" :(
How to get that?
I will try:
private void printForegroundTask() {
String currentApp = "NULL";
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
} else {
ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
currentApp = tasks.get(0).processName;
}
Log.e(TAG, "Current App in foreground is: " + currentApp);
}
BUT return NULL :( please help me! thanks
getRunningTasks() is deprecated in API level 21(Lollipop)
As alternate you can do like this
List<ActivityManager.RunningAppProcessInfo> task = manager.getRunningAppProcesses();
ComponentName componentInfo = task.get(0).importanceReasonComponent;
String packageName = componentInfo.getPackageName()
Note:
this method is only intended for debugging and presenting task management user interfaces. This should never be used for core logic in an application, such as deciding between different behaviors based on the information found here.
Refer the doc
UPDATE:
ActivityManager manager = (ActivityManager) MainActivity.this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> task = manager.getRunningAppProcesses();
ActivityManager.RunningAppProcessInfo runningAppProcessInfo = null;
for(ActivityManager.RunningAppProcessInfo singleTask : task){
if(singleTask.importanceReasonComponent !=null){
runningAppProcessInfo = singleTask;
break;
}
}
if(runningAppProcessInfo!=null) {
ComponentName componentInfo = runningAppProcessInfo.importanceReasonComponent;
String packageName = componentInfo.getPackageName();
Log.d("myPackageName", packageName);
}
You can also use Accessibility Services but for that you need to redirect your users to the Accessibility Settings to turn it on. Sample code is below to get the package of the app which has been just opened or in your case the top activity.
public class MyAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
String packageName = event.getPackageName();
}
}
you need use permission "PACKAGE_USAGE_STATS" for UsageStatsManager:
"This API requires the permission android.permission.PACKAGE_USAGE_STATS, which is a system-level permission and will not be granted to third-party apps. However, declaring the permission implies intention to use the API and the user of the device can grant permission through the Settings application."
Refer:https://developer.android.com/reference/android/app/usage/UsageStatsManager.html
I use the code below to get the application package name.
But when I swipe the notification bar, it will take the name of the application package running in the notification bar.
Or where applications are updating the new version, it will take the name of the application package.
I tried it on Android 5 get exact results open application package name.
So how to get the name of the application package is currently running on Android open 6
public static String printForegroundTask(Context context) {
String currentApp = "Null";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) context
.getSystemService("usagestats");
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(
UsageStatsManager.INTERVAL_DAILY, time - 1000 * 1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey())
.getPackageName();
}
}
} else {
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
currentApp = am.getRunningTasks(1).get(0).topActivity
.getPackageName();
}
return currentApp;
}
How to detect which app has been launched by user in my app i.e my application should get notified when Whatsapp is launched by user even if my app is not running in foreground or background.
hike messenger has achieved same functionality with accessibility service.
How can I solve this problem ?
Thanks in advance!!
Depending on the Android version running your application, you will have to use different methods.
On Pre-Lollipop devices, it is pretty straight-forward:
String[] result = new String[2];
List<ActivityManager.RunningTaskInfo> runningTasks;
ComponentName componentInfo;
runningTasks = activityManager.getRunningTasks(1);
componentInfo = runningTasks.get(0).topActivity;
result[0] = componentInfo.getPackageName();
result[1] = componentInfo.getClassName();
If you are on a Lollipop or newer device, you have to use UsageStatsManager class, which requires your application to be granted specific permissions
//no inspection ResourceType
UsageStatsManager mUsageStatsManager = (UsageStatsManager)context.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<>();
for (UsageStats usageStats : stats) {
mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
}
if(mySortedMap != null && !mySortedMap.isEmpty()) {
return mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
return null;
This will tell you if your apps has been granted permissions:
try {
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
return (mode != AppOpsManager.MODE_ALLOWED);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
And finally this will launch the Android permission granting activity for the user:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
activity.startActivity(intent);
Hope that helps
Try this code:
ActivityManager activityManager = (ActivityManager) this.getSystemService( ACTIVITY_SERVICE );
List<RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
for(int i = 0; i < procInfos.size(); i++)
{
if(procInfos.get(i).processName.equals("put the package name here"))
{
Toast.makeText(getApplicationContext(), "Notify Message", Toast.LENGTH_LONG).show();
}
}
No, this is not really possible using the public SDK.
You can get the current running process by ActivityManager#getRunningAppProcesses But it is definitely impossible to get notified .However, it isn't the most accurate, or efficient method
From a background service, I am getting a launcher app package name.
Code used:
private String printForegroundTask() {
String currentApp = "NULL";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, time - 1000 * 1000,
time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
} else {
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
currentApp = am.getRunningTasks(1).get(0).topActivity.getPackageName();
}
return currentApp;
}
When I launched the Downloads app, I am getting package name com.android.documentsui, but this package belong to Documents app.
Documents App: com.android.documentsui
Download Manager App: com.android.providers.downloads
Downloads App: com.android.providers.downloads.ui
I am facing this issue for Lollipop.
I checked the App lock application. I found that if Downloads app is locked and launched I see the Documents as the app name instead of Downloads,
i.e. app lock application is recognizing that all above defined packages belongs to same app.
Any idea regarding this?
use this code so that you can get the package name of list of apps installed in moblie
final PackageManager pm = getPackageManager();
//get a list of installed apps.
List packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo packageInfo : packages) {
Log.d(TAG, "Installed package :" + packageInfo.packageName);
Log.d(TAG, "Launch Activity :" + pm.getLaunchIntentForPackage(packageInfo.packageName));
}