I'm trying to write a UI Automation test and I'm trying to speed it up. At one point of the test, I need to close all recent apps on a device. I can do this via UiAutomator (currently doing it that way) but this isnt the part of the test I'm focusing on so I was wondering if this is doable via an intent call?
Based on the file structure, I would prefer not to add new classes, change activity code (b/c only needed for testing), or change permissions too badly.
I want to doing something along the line of:
Intent closeIntent = new Intent(context, null);
closeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(closeIntent);
Android isnt okay with the null class parameter.
I've looked at the following but none of them are what I really want:
Finish all activities at a time
Intent data not clearing when user presses back button then recent apps button
https://gist.github.com/anonymous/9884978
Thanks in advance!
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (int i = 0; i < tasks.size(); i++) {
Log.d("Running task", "Running task: " + tasks.get(i).baseActivity.toShortString() + "\t\t ID: " + tasks.get(i).id);
String packageName = processus.processName.split(":")[0];
if (!getPackageName().equals(packageName) && !tasks.contains(packageName)) {
am.killBackgroundProcesses(packageName);
}
}
Hope this will help you out.....
Related
I am creating a custom launcher in android application and , I want to track actual time which application is opened.
suppose i open Facebook for 10 minute and I went ideal for 5 minute how to calculate 5 minute which is used by user.
Thanks
You can define two buttons to start and stop your service. Fire an intent on Start button something like this:
Intent startServiceIntent = new Intent();
startServiceIntent.setClass(this, MainService.class);
startServiceIntent.setComponent(new ComponentName(this, MainService.class));
bindService(startServiceIntent, mConnection, Context.BIND_AUTO_CREATE);
In the service, you can define broadcast receivers to detect screen on-off events.
private BroadcastReceiver screenWakeUp = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (intent.getAction().equals("android.intent.action.SCREEN_ON")) {
isRunningForegroundAppsThread = true;
isScreenOn = true;
startThread();
}
}
};
From here, you can start a thread which constantly runs inside a loop and checks whether the application being used by the user has changed meanwhile. If it has, you may update time for that app in the map else you can just continue. At the SCREEN_OFF event, you may stop the thread as user is no more using the phone.
You can retrieve the application name using this:
ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
PackageManager pm = mContext.getPackageManager();
ApplicationInfo af = null;
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
// String activity = taskInfo.get(0).topActivity.getClassName();
ComponentName c = taskInfo.get(0).topActivity;
String packageName = c.getPackageName();
try {
af = pm.getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String app_Name_current = (String) pm.getApplicationLabel(af);
It solely depends on your requirement, and if needed the time can be stored in a DB. Also, this records just the time for apps which require screen to be ON, so you'll have to separately maintain time for background apps and store that in a separate map maybe. At the end, when you press the stop button, you can display the results in a listview or whatever UI element you consider suitable for this.
I know this is not complete code, but I guess it gives you an idea of how to go about it. Also, I'd say that though this might solve the problem, but it's not a good way of achieving the same, as PackageManager objects are heavyweight and dealing with them continuously is expensive operation.
The above approach only works on pre-L devices as ActivityManager has been deprecated in API level 21. So you have to use UsageStats class for Lollypop devices.
I have a button in a service where the user clicks on it the recent apps dialog will appear, but I don't know a proper way to achieve that, can anyone help?
ActivityManager has method getrunningtasks() .
ActivityManager activity_manager = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
then call the getRunningtasks() to get a list of the current Running tasks :
List<RunningTaskInfo> recentTasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (int i = 0; i < recentTasks.size(); i++) {
Log.d("Executed app",
"Application executed : "
+ recentTasks.get(i).baseActivity.toShortString()
+ "\t\t ID: " + recentTasks.get(i).id + "");
}
and please add the permission to get the running tasks in your manifest file like the following :
<uses-permission android:name="android.permission.GET_TASKS"/>
Hope that helps .
Recent apps can be opened using the TOGGLE_RECENTS Intent.
Intent intent = new Intent ("com.android.systemui.recent.action.TOGGLE_RECENTS");
intent.setComponent (new ComponentName ("com.android.systemui", "com.android.systemui.recent.RecentsActivity");
startActivity (intent);
You can make your own dialog to show recent apps
ActivityManager am = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
then you can get all running apps with
getRunningTasks
Is there a way for an Activity to find out who (i.e. class name) has sent an Intent? I'm looking for a generic way for my Activity to respond to a received intent by sending one back to the sender, whoever that may be.
There may be another way, but the only solution I know of is having Activity A invoke Activity B via startActivityForResult(). Then Activity B can use getCallingActivity() to retrieve Activity A's identity.
Is it an external app you receive the intent from? You could use the getReferrer() method of the activity class
A simple example: I opened google map app to share some location with my app by using the share option of google maps. Then my app opens and this method call in the Activity:
this.getReferrer().getHost()
will return:
com.google.android.apps.maps
see documentation here: https://developer.android.com/reference/android/app/Activity.html#getReferrer()
Note that this requires API 22. For older Android versions see answer from ajwillliams
A technique I use is to require the application sending the relevant Intent to add a PendingIntent as a Parcelable extra; the PendingIntent can be of any type (service, broadcast, etc.). The only thing my service does is call PendingIntent.getCreatorUid() and getCreatorPackage(); this information is populated when the PendingIntent is created and cannot be forged by the app so I can get the info about an Intent's sender.
Only caveat is that solution only works from Jellybean and later which is my case.
Hope this helps,
This isn't incredibly direct but you can get a list of the recent tasks from ActivityManager. So the caller would essentially be the task before yours and you can fetch info on that task.
Example usage:
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(10000,ActivityManager.RECENT_WITH_EXCLUDED);
The above will return a list of all the tasks from most recent (yours) to the limit specified. See docs here for the type of info you can get from a RecentTaskInfo object.
Generally you don't need to know this. If the calling activity uses startActivityForResult(Intent, int), the callee can use setResult(int, Intent) to specify an Intent to send back to the caller. The caller will receive this Intent in its onActivityResult(int, int, Intent) method.
Based on your question, since you want to send an intent back to the sender startActivityForResult is a better choice than what I am going to suggest. But I needed to start activity B when a notification is clicked by the user and execute some code in activity B only if the sender activity is activity A. This is how I did it quite simply.
Inside Activity A:
String senderName = this.getClass().getSimpleName();
Intent clickIntent = new Intent(ActivityA.this, ActivityB.class);
clickIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
clickIntent.putExtra("SENDER_CLASS_NAME", senderName);
//I use PendingIntent to start Activity B but you can use what you like such as this.startActivity(clickIntent);
PendingIntent.getActivity(ActivityA.this, NOTIFICATION_ID, clickIntent, PendingIntent.FLAG_ONE_SHOT);
Inside Activity B:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
if(bundle.containsKey("SENDER_CLASS_NAME")){
String senderName = bundle.getString("SENDER_CLASS_NAME");
//Execute some code
Log.d("GCM", "Notifications clicked");
}
}
}
}
In my case, neither the accepted here and another most voted answer works perfectly.
Activity.getCallerActivity() works only for the sender which starts your activity by startActivityForResult, meaning that if the sender is also in your app and you have full control, it works, but not every external app starts others in that way.
Another most voted answer provides the solution for external app, but it too has issue. First I would prefer getAuthority() instead of getHost(), secondly, if the sender is a browser kind of app, like Chrome, both host and authority will give you the browsing web page's address host, such as www.google.com, instead of the app itself. So it depends on how you define 'sender', if you need to find out which web page starts you, the authority/host is good enough, but if you need to find out which app starts you, I am afraid authority/host can be trusted only when getScheme() gives you android-app instead of http.
Use UsageStatsManager and the old RecentTaskInfo to get the intent sender for OnCreate or onNewIntent:
public static String getTopMostThirdPartyPackage(Context context) {
String thisPak = null, tmp, top = null;
try {
thisPak = context.getPackageName();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
UsageStatsManager man = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
long now = System.currentTimeMillis();
UsageEvents uEvts = man.queryEvents(now - 5000,now); // query in 5 sec
UsageEvents.Event e = new UsageEvents.Event();
while (uEvts.getNextEvent(e)){
tmp = e.getPackageName();
if (!thisPak.equals(tmp)) {
top = tmp;
break;
}
}
} else {
ActivityManager man = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> tasks = man.getRecentTasks(3, 0);
for(ActivityManager.RecentTaskInfo info:tasks) {
tmp = info.baseIntent.getComponent().getPackageName();
if (!thisPak.equals(tmp)) {
top = tmp;
break;
}
}
}
} catch (Exception e) {
}
return top;
}
permissions :
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.GET_TASKS" />
intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
When I get a message I need to bring the activity to front. I use the following code:
public void BringToFront()
{
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
intent.setClass(getApplicationContext(), getClass());
startActivity(intent);
}
When I get the activity on top the previous data is lost, even though the activity was not killed by the OS. Is there a way to get the activity back without losing the data or I need to recover the data anyway?
Thanks
Your code doesn't work. Your Activity is only active when it's in front. If it's not in front, it can't process so your method will never be called. An Activity should always save the data it wants to keep, either in onSaveInstanceState or when the data is changed. There's many ways to save data between activities.
If you want your activity to be in front, you'll have to close all activities that are on top of it. If you need these activities again, you should have them save their data, and start them again with the new data.
I suggest you read the documentation on how Activities work....
Just use this method in your activity as per your situation. it will work.
protected void moveToFront() {
if (Build.VERSION.SDK_INT >= 11) { // honeycomb
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningTaskInfo> recentTasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (int i = 0; i < recentTasks.size(); i++)
{
Log.d("Executed app", "Application executed : "
+recentTasks.get(i).baseActivity.toShortString()
+ "\t\t ID: "+recentTasks.get(i).id+"");
// bring to front
if (recentTasks.get(i).baseActivity.toShortString().indexOf("Your app pckg name") > -1) {
activityManager.moveTaskToFront(recentTasks.get(i).id, ActivityManager.MOVE_TASK_WITH_HOME);
}
}
}
}
Also you need to add below permission in manifest.
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
Is there a way for an Activity to find out who (i.e. class name) has sent an Intent? I'm looking for a generic way for my Activity to respond to a received intent by sending one back to the sender, whoever that may be.
There may be another way, but the only solution I know of is having Activity A invoke Activity B via startActivityForResult(). Then Activity B can use getCallingActivity() to retrieve Activity A's identity.
Is it an external app you receive the intent from? You could use the getReferrer() method of the activity class
A simple example: I opened google map app to share some location with my app by using the share option of google maps. Then my app opens and this method call in the Activity:
this.getReferrer().getHost()
will return:
com.google.android.apps.maps
see documentation here: https://developer.android.com/reference/android/app/Activity.html#getReferrer()
Note that this requires API 22. For older Android versions see answer from ajwillliams
A technique I use is to require the application sending the relevant Intent to add a PendingIntent as a Parcelable extra; the PendingIntent can be of any type (service, broadcast, etc.). The only thing my service does is call PendingIntent.getCreatorUid() and getCreatorPackage(); this information is populated when the PendingIntent is created and cannot be forged by the app so I can get the info about an Intent's sender.
Only caveat is that solution only works from Jellybean and later which is my case.
Hope this helps,
This isn't incredibly direct but you can get a list of the recent tasks from ActivityManager. So the caller would essentially be the task before yours and you can fetch info on that task.
Example usage:
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(10000,ActivityManager.RECENT_WITH_EXCLUDED);
The above will return a list of all the tasks from most recent (yours) to the limit specified. See docs here for the type of info you can get from a RecentTaskInfo object.
Generally you don't need to know this. If the calling activity uses startActivityForResult(Intent, int), the callee can use setResult(int, Intent) to specify an Intent to send back to the caller. The caller will receive this Intent in its onActivityResult(int, int, Intent) method.
Based on your question, since you want to send an intent back to the sender startActivityForResult is a better choice than what I am going to suggest. But I needed to start activity B when a notification is clicked by the user and execute some code in activity B only if the sender activity is activity A. This is how I did it quite simply.
Inside Activity A:
String senderName = this.getClass().getSimpleName();
Intent clickIntent = new Intent(ActivityA.this, ActivityB.class);
clickIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
clickIntent.putExtra("SENDER_CLASS_NAME", senderName);
//I use PendingIntent to start Activity B but you can use what you like such as this.startActivity(clickIntent);
PendingIntent.getActivity(ActivityA.this, NOTIFICATION_ID, clickIntent, PendingIntent.FLAG_ONE_SHOT);
Inside Activity B:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
if(bundle.containsKey("SENDER_CLASS_NAME")){
String senderName = bundle.getString("SENDER_CLASS_NAME");
//Execute some code
Log.d("GCM", "Notifications clicked");
}
}
}
}
In my case, neither the accepted here and another most voted answer works perfectly.
Activity.getCallerActivity() works only for the sender which starts your activity by startActivityForResult, meaning that if the sender is also in your app and you have full control, it works, but not every external app starts others in that way.
Another most voted answer provides the solution for external app, but it too has issue. First I would prefer getAuthority() instead of getHost(), secondly, if the sender is a browser kind of app, like Chrome, both host and authority will give you the browsing web page's address host, such as www.google.com, instead of the app itself. So it depends on how you define 'sender', if you need to find out which web page starts you, the authority/host is good enough, but if you need to find out which app starts you, I am afraid authority/host can be trusted only when getScheme() gives you android-app instead of http.
Use UsageStatsManager and the old RecentTaskInfo to get the intent sender for OnCreate or onNewIntent:
public static String getTopMostThirdPartyPackage(Context context) {
String thisPak = null, tmp, top = null;
try {
thisPak = context.getPackageName();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
UsageStatsManager man = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
long now = System.currentTimeMillis();
UsageEvents uEvts = man.queryEvents(now - 5000,now); // query in 5 sec
UsageEvents.Event e = new UsageEvents.Event();
while (uEvts.getNextEvent(e)){
tmp = e.getPackageName();
if (!thisPak.equals(tmp)) {
top = tmp;
break;
}
}
} else {
ActivityManager man = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> tasks = man.getRecentTasks(3, 0);
for(ActivityManager.RecentTaskInfo info:tasks) {
tmp = info.baseIntent.getComponent().getPackageName();
if (!thisPak.equals(tmp)) {
top = tmp;
break;
}
}
}
} catch (Exception e) {
}
return top;
}
permissions :
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.GET_TASKS" />
intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);