I am trying to get running activity name (Foreground activity name) from package name as you all know that we can get currently running activity name
via this line
mActivityManager.getRunningTasks(1).get(0).topActivity.getClassName()
but this work only bellow android 5.0 i need same thing in above 5.0
i am able to get current package name but not activity
security is enhanced from android Lollipop; see this article for more details: getAppTask
You could get foreground activities via UsageStats class; first, you have to add this permission in your manifest:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/>
and this declaration:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your_application_package">
This will disable warning that permission is system level and will not be granted to third-party apps. User of the device can grant permission through the Settings application.
So, in onCreate() method of your MainActivity, check if user granted this permission
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
if(!hasPermission()){
startActivityForResult(
new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS),
Constant.MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS);
}
}
And if no, ask user to enable it:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Constant.MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS){
if (!hasPermission()){
startActivityForResult(
new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS),
Constant.MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS);
}
}
}
private boolean hasPermission() {
AppOpsManager appOps = (AppOpsManager)
getSystemService(Context.APP_OPS_SERVICE);
int mode = 0;
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.KITKAT) {
mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
android.os.Process.myUid(), getPackageName());
}
return mode == AppOpsManager.MODE_ALLOWED;
}
Finally, here's a snippet to put in a background service, that gives you package name of current foreground activites:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private String getUsageStatsForegroundActivityName() {
UsageStatsManager mUsageStatsManager = (UsageStatsManager) MyApplication.getInstance().getSystemService(Context.USAGE_STATS_SERVICE);
long endTime = System.currentTimeMillis();
long beginTime = endTime - 1000 * 60;
// result
String topActivity = null;
// 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()) {
topActivity = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
logger.info("topActivity: " + topActivity);
}
}
if (topActivity != null)
return topActivity;
else
return Constant.ACTIVITY_NOT_FOUND;
}
Related
I'm working an app called 'Prevent Uninstall', in this app user creates 4 digit pin and I'm going to save this pin in sharedpreferences. My requirement is when user clicks uninstall button of any application a popup or window should be displayed to confirm the pin which is already created in my application. So is it possible?, if possible please help me, i got stuck at this point.
hello guys finally i have found a solution below..
first get the current activity on foreground
public boolean isConcernedAppIsInForeground() {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> task = manager.getRunningTasks(5);
if (Build.VERSION.SDK_INT <= 20) {
if (task.size() > 0) {
ComponentName componentInfo = task.get(0).topActivity;
for (int i = 0; pakageName != null && i < pakageName.size(); i++) {
if (componentInfo.getPackageName().equals("com.google.android.packageinstaller")) {
currentApp_for = pakageName.get(i);
return true;
}
}
}
} else {
for (int i = 0; pakageName != null && i < pakageName.size(); i++) {
if (retriveNewApp().equals("com.google.android.packageinstaller")) {
currentApp_for = pakageName.get(i);
Log.e("DSSDSDCSDC", currentApp_for + " LLLLLL::::");
return true;
}
}
}
return false;
}
To get the current activity on foreground above api level 21+ use this code
private String retriveNewApp() {
String currentApp_for_ = null;
if (Build.VERSION.SDK_INT >= 21) {
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<>();
for (UsageStats usageStats : applist) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp_for_ = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
Log.e(">>>>>>>>>><<<", "Current App in foreground is: " + currentApp_for_);
} else {
Log.e("CCC>>C>C>C>", "User not given the permission: " + currentApp_for_);
}
}
return currentApp_for_;
}
Important permission
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
now check the current activity is in foreground or not using service
if (isConcernedAppIsInForeground()) {
if (!currentApp.matches(previousApp)) {
// if matches do your activity here..
startActivity(newIntent(context,Draw_Lock.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
previousApp = currentApp;
}
}
}
Note: When user clicks on uninstall button of any app alert dialog popups which is known as 'com.google.android.packageinstaller' activity check weather this activity is in foreground or not using service class
I am trying to get a list of currently running apps on my phone. Here is the code I am using:
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 - 10000*10000, time);
if (appList != null && appList.size() == 0) {
Log.d("Executed app", "######### NO APP FOUND ##########" );
}
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
Log.d("Executed app", "usage stats executed : " +usageStats.getPackageName() + "\t\t ID: ");
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
String currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
}
Here I have set the permission as well:
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
It does not detect any app usage. I have tried some other things on stackoverflow but nothing seems to work. I have even read somewhere that the ability for apps to monitor other apps running on the phone has been removed completely in the newer phones. Would greatly appreciate any help!
The problem is that your application does not have the system permission of android:get_usage_stats.
You can use the below code to check if you have the permission:
public static boolean needPermissionForBlocking(Context context){
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 true;
}
}
If you do not have the permission then the user must enable this permission by going to Settings -> Security-> Apps with usage access, and then adding your application. Your code should then work fine.
I try to use usage stats but after retrieving successfully the list of installed apps I try to query the usage stats but I get a 0 value.
After looking in StackOverflow I see that there is an extra permission on top of PACKAGE_USAGE_STATS: OPSTR_GET_USAGE_STATS
When I check this permission I don't have it.
Why isn't PACKAGE_USAGE_STATS sufficient?
Does it exist a way to set this permission programmatically?
Otherwise, I don't like the idea of re-directing the user to Settings: isn't it a way to prompt the user in the UI to allow this permission?
Here is an extract of my code:
manifest
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
java code:
void getInstalledApp() {
List<String> installedApps = getInstalledAppList();
if(!checkForPermission())
Log.i("PERM", "false");
List<UsageStats> usageStats =
usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,
getStartTime(), System.currentTimeMillis());
List<UsageStats> stats = new ArrayList<>();
}
private List<String> getInstalledAppList(){
List<ApplicationInfo> infos = packageManager.getInstalledApplications(flags);
List<String> installedApps = new ArrayList<>();
for (ApplicationInfo info : infos){
installedApps.add(info.packageName);
}
return installedApps;
}
private long getStartTime() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, -1);
return calendar.getTimeInMillis();
}
private boolean checkForPermission() {
AppOpsManager appOps = (AppOpsManager) activity.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(OPSTR_GET_USAGE_STATS, myUid(), activity.getPackageName());
return mode == MODE_ALLOWED;
}
Check this method for asking permission from user if not granted:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void checkForUsageStatsPermission() {
AppOpsManager appOps = (AppOpsManager) getActivity().getSystemService(Context.APP_OPS_SERVICE);
int mode = 0;
if (appOps != null) {
mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), getActivity().getPackageName());
}
if (mode != AppOpsManager.MODE_ALLOWED) {
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
}
}
It seems Google finally closed all doors for getting the current foreground application package.
After the Lollipop update, which killed getRunningTasks(int maxNum) and thanks to this answer, I used this code to get the foreground application package since Lollipop:
final int PROCESS_STATE_TOP = 2;
RunningAppProcessInfo currentInfo = null;
Field field = null;
try {
field = RunningAppProcessInfo.class.getDeclaredField("processState");
} catch (Exception ignored) {
}
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
for (RunningAppProcessInfo app : appList) {
if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
app.importanceReasonCode == 0 ) {
Integer state = null;
try {
state = field.getInt( app );
} catch (Exception ignored) {
}
if (state != null && state == PROCESS_STATE_TOP) {
currentInfo = app;
break;
}
}
}
return currentInfo;
Android 5.1.1 and above (6.0 Marshmallow), it seems, killed getRunningAppProcesses() as well. It now returns a list of your own application package.
UsageStatsManager
We can use the new UsageStatsManager API as described here but it doesn't work for all applications. Some system applications will return the same package
com.google.android.googlequicksearchbox
AccessibilityService (December 2017: Going to be banned for use by Google)
Some applications use AccessibilityService (as seen here) but it has some disadvantages.
Is there another way of getting the current running application package?
To get a list of running processes on Android 1.6 - Android 6.0 you can use this library I wrote: https://github.com/jaredrummler/AndroidProcesses The library reads /proc to get process info.
Google has significantly restricted access to /proc in Android Nougat. To get a list of running processes on Android Nougat you will need to use UsageStatsManager or have root access.
Click the edit history for previous alternative solutions.
private String printForegroundTask() {
String currentApp = "NULL";
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager)this.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)this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
currentApp = tasks.get(0).processName;
}
Log.e("adapter", "Current App in foreground is: " + currentApp);
return currentApp;
}
Use this method for getting foreground task.
U will need an System Permission "android:get_usage_stats"
public static boolean needPermissionForBlocking(Context context){
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 true;
}
}
IF user enable this in setting -> Security-> app with usage access. After that u will get foreground task. Similar process Clean matser by Cheetahamobile
google play link
Take a look at https://github.com/ricvalerio/foregroundappchecker, it might be what you need. Provides sample code, and takes away the pain of having to implement cross version foreground detector.
Here are two samples:
AppChecker appChecker = new AppChecker();
String packageName = appChecker.getForegroundApp();
Or regularly check:
AppChecker appChecker = new AppChecker();
appChecker
.when("com.other.app", new AppChecker.Listener() {
#Override
public void onForeground(String packageName) {
// do something
}
)
.when("com.my.app", new AppChecker.Listener() {
#Override
public void onForeground(String packageName) {
// do something
}
)
.other(new AppChecker.Listener() {
#Override
public void onForeground(String packageName) {
// do something
}
)
.timeout(1000)
.start(this);
Google limited this functionality for system apps only. As been reported in a bug ticket, you will need the REAL_GET_TASKS permission to access there.
Applications must now have ...permission.REAL_GET_TASKS to be able to
get process information for all applications. Only the process
information for the calling application will be returned if the app
doesn't have the permission. Privileges apps will temporarily be able
to get process information for all applications if they don't have the
new permission, but have deprecated ...permission.GET_TASKS Also,only
system apps can acquire the REAL_GET_TASKS permission.
Just throwing out a potential optimization to what I imagine is a heavily copy-pasted bit of code for detecting the top-most application on Android M.
This
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager)this.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();
}
}
}
Can be simplified to this
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) context.getSystemService(
Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> appStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
time - 1000 * 1000, time);
if (appStatsList != null && !appStatsList.isEmpty()) {
currentApp = Collections.max(appStatsList, (o1, o2) ->
Long.compare(o1.getLastTimeUsed(), o2.getLastTimeUsed())).getPackageName();
}
}
I found myself using this code in a 2 second loop, and wondered why I was using a complex solution that was O(n*log(n)) when a more simple solution was available in Collections.max() which is O(n).
public class AccessibilityDetectingService extends AccessibilityService {
#Override
protected void onServiceConnected() {
super.onServiceConnected();
//Configure these here for compatibility with API 13 and below.
AccessibilityServiceInfo config = new AccessibilityServiceInfo();
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
if (Build.VERSION.SDK_INT >= 16)
//Just in case this helps
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
setServiceInfo(config);
}
#Override
public void onAccessibilityEvent(final AccessibilityEvent event) {
if (event == null ) {
return;
} else if(event.getPackageName() == null && event.getClassName() == null){
return;
}
if (activityInfo != null){
Log.d("CurrentActivity", componentName.flattenToShortString());
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
#Override
public void onInterrupt() {
}
}
}//`enter code here`uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.GET_TASKS" />
Then start the service and app accessibility on in your device
setting->accessibility->App
on that service.
Please try to use getRunningServices() instead of getRunningAppProcesses() method.
ActivityManager mActivityManager = (ActivityManager) getSy stemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> appProcessInfoList = mActivityManager.getRunningServices(Integer.MAX_VALUE);
It is easy to get a list of running tasks from the ActivityManager service on Android L, and the current active task is returned first. But it don't work on Android M any more, the return list only contains my app task. Is there any way to settle it?
My code:
List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfos = activityManager.getRunningAppProcesses();
for (int i = 0; i < runningAppProcessInfos.size(); i++) {
ActivityManager.RunningAppProcessInfo runningAppProcessInfo = runningAppProcessInfos.get(i);
if (runningAppProcessInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return runningAppProcessInfo.pkgList[0];
}
}
you can use below code and get the current foreground activity package name.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) 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) getBaseContext().getSystemService(ACTIVITY_SERVICE);
currentApp = am.getRunningTasks(1).get(0).topActivity .getPackageName();
}
Edit
Add this permission in to Manifest file.
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
Note
Make sure you need to configure custom setting in your device to obtain the output you can config it with Setting > Security > Apps with usage access > Then enable your app permission
Please try this lines in Android M. This worked for me
String packageName = ProcessManager.getRunningForegroundApps(getApplicationContext()).get(0).getPackageName();
check below link for other android platform support.
https://stackoverflow.com/a/36660429/4554069