20

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?

TheCodeArtist
  • 21,479
  • 4
  • 69
  • 130
Mr Pablo
  • 4,109
  • 8
  • 51
  • 104
  • 1
    I believe you can only make you app a system app if the device is rooted. You may want to consider making your app a home screen replacement, like a kiosk mode application. See my answer [here](http://stackoverflow.com/questions/16657300/disable-all-home-button-and-task-bar-features-on-nexus-7/16657359#16657359). – TronicZomB Aug 16 '13 at 15:03

7 Answers7

15
  • 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"/>
Tanasis
  • 795
  • 1
  • 9
  • 21
  • Nice answer, so will this way keep the app running even if it's invisible (another app is open)? – Dania Feb 05 '16 at 17:15
  • 1
    Thx. If it is not running at all or running in the background, it will restore it, i.e. bring it to the foreground. – Tanasis Feb 07 '16 at 14:33
  • Good answer, BUT: the only problem I have is when getting email notification, for example, I can select the email and it gets the foreground app. How I disable it? – Meir Feb 04 '18 at 08:19
  • Looks like the app AutoStart and Stay no longer exists unfortunately – FlorianB Nov 29 '18 at 07:43
  • 1
    @Tanasis sir, How to declare activityManager ? – Jamebes Nov 25 '22 at 11:03
  • activityManager didn't declared. code doesn't work. add: final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); – Fəqan Çələbizadə Dec 27 '22 at 12:08
3

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?

Community
  • 1
  • 1
Thkru
  • 4,218
  • 2
  • 18
  • 37
  • 1
    This isn't what the OP was after. He wants to keep his app running permanently, this will just keep the screen on while his app is running but users of the device will be able to go to other apps – Boardy Aug 16 '13 at 15:27
  • But once it runs, it should exactly run endlessly? Otherwise it might be an option to handle OnDestroy and some broadcastReceivers to start the app if its not in the foreground. – Thkru Aug 16 '13 at 15:32
  • There would be nothing stopping the user though pressing the home button and then using other apps that might be installed on the device, therefore putting the OP app into the background. – Boardy Aug 16 '13 at 15:46
  • Thomas - thank you for your input, but like Broady said, you misunderstood. Keeping the screen on is part of my app, but it a different issue to what I need to fix. Sadly, even with your code, the app could still be closed if the system needs the memory – Mr Pablo Aug 19 '13 at 09:12
2

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.

Boardy
  • 35,417
  • 104
  • 256
  • 447
  • 1
    Something the OP might also want to keep in mind is there is a potential to have issues (I did at least) after a boot with a custom home replacement. [This is what I experienced and how I fixed it.](http://stackoverflow.com/questions/17372781/home-launcher-issue-with-fragments-after-reboot) – TronicZomB Aug 16 '13 at 15:34
2

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);
}
1

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

Yann G
  • 111
  • 1
  • 2
0

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.

nlt
  • 555
  • 7
  • 11
0

You may try startLockTask(); For More info, visit here

Umasankar
  • 495
  • 7
  • 6