i set a service that checks if a specific process is running in time intervals by using:
appsList = am.getRunningAppProcesses();
i saved its name and id with:
s = pross.processName;
i=pross.pid;
i launch the default launcher with:
Intent intent = null;
final PackageManager pManager = context.getPackageManager();
for (final ResolveInfo resolveInfo:pManager.queryIntentActivities(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),pManager.MATCH_DEFAULT_ONLY ))
{
if(!context.getPackageName().equals(resolveInfo.activityInfo.packageName))
{
intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
break;
}
}
context.startActivity(intent);
than kill the process with :
mActivityManager.killBackgroundProcesses(s);
it all works fine but the problem is that its doing the whole calling the launcher and closing the process twice.
it's like the process is still running the second time the service checks if its running.
any idea how to solve this?
I think we can not kill any other process. System not allow to do that without root access.
Related
I'm creating an app that turns on another application whenever the user gets a phone call and turns that application off when the phone call ends.
This is my code:
public class MyPhoneReceiver extends BroadcastReceiver {
#Override
public void onReceive( Context context, Intent intent ) {
final String PROXIMITY_SERVICE_PACKAGE_NAME = "package_name";
Bundle extras = intent.getExtras();
String state = extras.getString( TelephonyManager.EXTRA_STATE );
if (state.equals( TelephonyManager.EXTRA_STATE_RINGING ) ) {
PackageManager packageManager = context.getPackageManager();
context.startActivity( packageManager.getLaunchIntentForPackage(
PROXIMITY_SERVICE_PACKAGE_NAME ) );
}
if ( state.equals(TelephonyManager.EXTRA_STATE_IDLE ) ) {
killProcess(context, PROXIMITY_SERVICE_PACKAGE_NAME);
}
}
The killProcess method is currently implemented this way:
private void killProcess(Context context, String packageName)
{
ActivityManager am = (ActivityManager)context.getSystemService(Activity.ACTIVITY_SERVICE);
am.killBackgroundProcesses(packageName);
}
I also ask for permission to kill background applications in the manifest:
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
The opening of the app is working, but the closing of the app doesn't.
I know I reach the code in killProcess, but it doesn't kill the app.
Is this a problem with permissions? Am I not allowed to kill another process? not even a process I created?
Or maybe, from what I know about the process I'm running, it creates a service that does all the work for it. Maybe the problem is that the service does not terminate?
Is there any way to terminate this process and all the services and sub processes that are related to it (like for example when you do FORCE STOP in settings)?
Thanks.
Yes you can kill any process.
Find the app process ID
Kill it.
Once you have the app process ID, just pass in this function:
Process.killProcess( APP-PROCESS-ID )
Note that the process class, should be imported from Android:
import android.os.Process
You can also try this if you know the package name of the app:
ActivityManager am = (ActivityManager)
getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
am.killBackgroundProcesses("app-package-name");
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.
How i can kill service that is started from my application
Code for start service:
startService(new Intent(getApplicationContext(),MyService.class);
I need kill service proccess, don't stop with stopService() method.
you could try using:
public void stopService(Context context) {
final PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(
YourActivity.this.getPackageName(),
YourService.class.getName());
packageManager.setComponentEnabledSetting(componentName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
if (YourService.intentVariable != null) {
stopService(YourService.intentVariable);
}
}
write a stopService method and in it use the package manager to stop the service you want to, and experiment with the package manager.
Services don't have processes of their own. The execute on the UI thread just like an Activity does. There's no process to end, unless you started your own via Thread or AsyncTask. In that case, you need to keep an instance around and force them to end yourself in your service's onDestroy function.
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);
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);