Kill another app and all its services programmatically in android - android

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");

Related

How to execute some event if RN has been killed?

Not sure if I understand correctly but according to this link
Deliver silent notifications and wake up your app in the background on the user's device.
It sounded to me that it's possible to perform some action even if the app has been killed.
Currently I'm using OneSignal as below:
OneSignal.addEventListener('received', this.onReceived);
onReceived(store, notification) {
store.dispatch(receivedNotification({ notification }));
}
However the above will only be able to dispatch action if the app is in background or foreground, but once the app been killed, despite receiving notification successfully, onReceived event will not be fired.
So my question is whether is it possible to "wake" my RN app in the background and dispatch a redux action?
There is no event that you can catch before app is killed. You also cannot prevent the user from killing your app. And once it is killed you cannot 'wake' it up, as your code is not running. You can only do such tasks when the app is in the background/foreground.
Yes, it is possible you can execute some event if RN has been killed.
now the question is how basically I am also using react-native and I have got some challenges also, I also want to execute some event if RN has been killed, but I did not get any answer actually my concern is to open an app which can and show a call screen when calling notification is received so I dig a lot and I found a solution,
first I created a bridge connection between javascript to java and then write a wakeful service which gets called every time when we receive notification and then I call my background intent service and in this service I wake up my activity and set some flags which help me to open screen when screen is lock depends on the conditions
// receiver Service //
public class MessagingService extends WakefulBroadcastReceiver {
private static final String TAG = "FirebaseService";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, String.valueOf(!isAppOnForeground(context)));
if (intent.getExtras() != null) {
if (!isAppOnForeground((context))) {
//This get called every time you receive notification
}
}
}
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}

How to know in BroadcastReceiver if App is running on foreground?

I am working in application that needs make a synchronization every night. I use Alarm Manager that calls a BroadcastReceiver at the hour that I want. The problem is that I cant make a synchronization if the application is running in foreground to avoid losing data. So I need to know in Broadcast Receiver if the app is running in foreground to cancel this synchronization.
I tried solutions that I found in StackOverflow:
Checking if an Android application is running in the background
But this parameter is always false in BroadcastReceiver, but true in activites.
Can anyone tell me which is the problem? What am I doing bad?
Really thanks!
Try this way hope this works for you
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (isAppForground(context)) {
// App is in Foreground
} else {
// App is in Background
}
}
public boolean isAppForground(Context mContext) {
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(mContext.getPackageName())) {
return false;
}
}
return true;
}
}
Add this permission
<uses-permission android:name="android.permission.GET_TASKS" />
What do you mean by "the application is running in foreground"?
If you mean there is an Activity currently displayed on the screen, then the easiest way would be to make a base Activity class that sets a global boolean in your `Application' class.
Custom Application class:
public class MyApp extends Application
{
public boolean isInForeground = false;
}
Custom base Activity class:
abstract public class ABaseActivity extends Activity
{
#Override
protected void onResume()
{
super.onResume();
((MyApp)getApplication()).isInForeground = true;
}
#Override
protected void onPause()
{
super.onPause();
((MyApp)getApplication()).isInForeground = false;
}
}
I assume you are not synchronising from your BroadcastReceiver - you should instead be launching a Service to do the synchronisation. Otherwise the system might kill your app - you must not be doing any long-running tasks in a BroadcastReceiver.
So before you launch your sync service, check the application boolean to see if your app is "in foreground". Alternatively, move the check inside the sync service, which has the advantage of making the BroadcastReceiver even simpler (I am always in favour of trying to make the receivers have as little logic as possible).
This method has the advantages that it is simple to use, understand, and requires no extra permissions.
in case you don't want to do anything if app in foreground you could simply turn off the receiver on your activity onStart method:
ComponentName receiver = new ComponentName(context, MyReceiver.class);
context.getPackageManager().setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
and you could turn it on onStop method:
ComponentName receiver = new ComponentName(context, MyReceiver.class);
context.getPackageManager().setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
and if receiver is turned off, no alarms will come to it, and your code will not be executed
That method tells you whether any of your activities in your app are currently in the foreground. If you check your MyApplication.isActivityVisible() method from the broadcast receiver, then that should work fine. If its returning false, then maybes no activities are showing.

why does it kill the app twice?

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.

How to keep a foreground app running 24/7?

I am looking into how to keep my Android app running in the foreground.
It will be a privately distributed app, so I can do anything possible to make sure it runs constantly on the device (HDMI TV Stick)
So, how can I make sure that the app stays running no matter what? The app is pretty light weight in terms of resource usage, so having it run 24/7 should hopefully not be a problem.
I read about the persistent parameter in the manifest, but it looks like it might only apply to system apps?
Should I make my app a system app? How would I do that and would it help?
If you want an external app use: Autostart and StaY!
If you want to do this programmatically you can use a service that polls every "x" milliseconds to see if your app is in the foreground. If it is not, it will start/bring your app in the foreground. Do it like this:
public class PersistService extends Service {
private static final int INTERVAL = 3000; // poll every 3 secs
private static final string YOUR_APP_PACKAGE_NAME = "YOUR_APP_PACKAGE_NAME";
private static boolean stopTask;
private PowerManager.WakeLock mWakeLock;
#Override
public void onCreate() {
super.onCreate();
stopTask = false;
// Optional: Screen Always On Mode!
// Screen will never switch off this way
mWakeLock = null;
if (settings.pmode_scrn_on){
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "a_tag");
mWakeLock.acquire();
}
// Start your (polling) task
TimerTask task = new TimerTask() {
#Override
public void run() {
// If you wish to stop the task/polling
if (stopTask){
this.cancel();
}
// The first in the list of RunningTasks is always the foreground task.
RunningTaskInfo foregroundTaskInfo = activityManager.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
// Check foreground app: If it is not in the foreground... bring it!
if (!foregroundTaskPackageName.equals(YOUR_APP_PACKAGE_NAME)){
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(YOUR_APP_PACKAGE_NAME);
startActivity(LaunchIntent);
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task, 0, INTERVAL);
}
#Override
public void onDestroy(){
stopTask = true;
if (mWakeLock != null)
mWakeLock.release();
super.onDestroy();
}
}
The above code has also the "option" to force the Screen to stay always on! Of course you will need the following permissions:
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
and do not also forget to register your service:
<service android:name="YOURPACAKGE.PersistService"
android:enabled="true"/>
use this:
import android.os.PowerManager;
public class MyActivity extends Activity {
protected PowerManager.WakeLock mWakeLock;
/** Called when the activity is first created. */
#Override
public void onCreate(final Bundle icicle) {
setContentView(R.layout.main);
/* This code together with the one in onDestroy()
* will make the screen be always on until this Activity gets destroyed. */
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
this.mWakeLock.acquire();
}
#Override
public void onDestroy() {
this.mWakeLock.release();
super.onDestroy();
}
}
And in the manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Seen here: How do I keep the screen on in my App?
This is something not too easy to achieve as foreground apps are technically not supposed to be running non stop. Also if android is running out of memory it will start killing apps that pose the least risk which would then require the app to be restarted by the user.
As mentioned you could either make it a system app, but I think you do need to root the device or build your own ROM and make your app part of the ROM. Probably not the best solution for your needs though as few people will be able to flash a ROM on to their devices.
I think the easiest solution would be to put in the manifest that your app is a home screen replacement, i.e. a launcher app. I don't know the exact code from the top of my head but this would go into the application section within the android manifest. This would mean that as soon as the device boots, or the user presses the home button, they will be taken to your app.
I solved that issue by having a sticky service running that relaunches the app when the activity is getting closed.
//Your activity
#Override
public void onPause() {
super.onPause();
if (yourservice != null) {
yourservice.validateActivityOnPause();
}
}
and in the validateActivityOnPause() have something like:
//Your service
public void validateLynxActivityOnPause() {
//Do some stuff here
Intent startActivityIntent = new Intent(this, LynxActivity.class);
startActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(startActivityIntent);
}
Now that activityManager.getRunningAppProcesses() is deprecated( as of API21 ), you will want to replace :
RunningTaskInfo foregroundTaskInfo = activityManager.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
with:
List<ActivityManager.RunningAppProcessInfo> tasks = activityManager.getRunningAppProcesses();
String foregroundTaskPackageNameTest = tasks.get(0).processName;
do not forget to import List with:
import java.util.List;
As a side note, I am not sure about OP's way of keeping the screen always on. I'm not sure that it works the way he's done it, but more importantly, it is deprecated and very much advised against to be using Wake Locks as you need to add permissions, which opens the door to bugs. Rather, it is generally better practice to use Window manager flags:
https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_KEEP_SCREEN_ON
You could make your app become a launcher, by adding 2 following category tags into <intent-filter> tags:
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.HOME"/>
then you should always check if there's another app run on top, run following code to direct user to our app:
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
I have tried this solution, but it cannot hide apps that draw on top, like Facebook Messenger chat head.
You may try startLockTask();
For More info, visit here

Trying to read preferences upon BOOT_COMPLETED

I am setting an alarm from my app, and when rebooting, I see I need to reset the alarm since it does not survive reboots. I created a broadcast receiver to receive BOOT_COMPLETED and this works so my manifest must be correct.
When I try this line of code below I get in trouble. I need to retrieve the time that I need to set the alarm to but it looks like I cannot access the prefs of my app (called S) because my app has never started. NullPointerException :
if ( S.prefs.getBoolean(S.SCHEDULEDSTATUS, false) == true ) { }
I suppose it should be obvious that I cannot read a public static final of an activity that has not been created.
Do I have to store my alarm time in a file or am I missing something here?
You have to access it via the context you get in your reciever:
public void onReceive(Context con, Intent intent) {
final SharedPreferences settings = con.getSharedPreferences(PREFS, 0);
boolean boolValue = settings.getBoolean(BOOL, false);
}

Categories

Resources