How to Make an Android App to Always Run in Background

How to make an android app to always run in background?

You have to start a service in your Application class to run it always.
If you do that, your service will be always running. Even though user terminates your app from task manager or force stop your app, it will start running again.

Create a service:

public class YourService extends Service {

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// do your jobs here
return super.onStartCommand(intent, flags, startId);
}
}

Create an Application class and start your service:

public class App extends Application {

@Override
public void onCreate() {
super.onCreate();

startService(new Intent(this, YourService.class));
}
}

Add "name" attribute into the "application" tag of your AndroidManifest.xml

android:name=".App"

Also, don't forget to add your service in the "application" tag of your AndroidManifest.xml

<service android:name=".YourService"/>

And also this permission request in the "manifest" tag (if API level 28 or higher):

<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

UPDATE

After Android Oreo, Google introduced some background limitations. Therefore, this solution above won't work probably. When a user kills your app from task manager, Android System will kill your service as well. If you want to run a service which is always alive in the background. You have to run a foreground service with showing an ongoing notification. So, edit your service like below.

public class YourService extends Service {

private static final int NOTIF_ID = 1;
private static final String NOTIF_CHANNEL_ID = "Channel_Id";

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId){

// do your jobs here

startForeground();

return super.onStartCommand(intent, flags, startId);
}

private void startForeground() {
Intent notificationIntent = new Intent(this, MainActivity.class);

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);

startForeground(NOTIF_ID, new NotificationCompat.Builder(this,
NOTIF_CHANNEL_ID) // don't forget create a notification channel first
.setOngoing(true)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText("Service is running background")
.setContentIntent(pendingIntent)
.build());
}
}

EDIT: RESTRICTED OEMS

Unfortunately, some OEMs (Xiaomi, OnePlus, Samsung, Huawei etc.) restrict background operations due to provide longer battery life. There is no proper solution for these OEMs. Users need to allow some special permissions that are specific for OEMs or they need to add your app into whitelisted app list by device settings. You can find more detail information from https://dontkillmyapp.com/.

If background operations are an obligation for you, you need to explain it to your users why your feature is not working and how they can enable your feature by allowing those permissions. I suggest you to use AutoStarter library (https://github.com/judemanutd/AutoStarter) in order to redirect your users regarding permissions page easily from your app.

By the way, if you need to run some periodic work instead of having continuous background job. You better take a look WorkManager (https://developer.android.com/topic/libraries/architecture/workmanager)

Let app run in background in android

This is part of the new App Standby feature introduced with API 23 (Marshmallow) alongside Doze Battery Optimization aimed to optimize power and resource usage while the app is in background (App Standby) or when the device has long been in sleep (Doze).

Following is the explanation from the Android Developer's site page:

Specifically, in the App Standby mode, the system determines that an app is idle when the user is not actively using it. The system makes this determination when the user does not touch the app for a certain period of time and none of the following conditions applies:

  • The user explicitly launches the app.
  • The app has a process currently in the foreground (either as an activity or foreground service, or in use by another activity or foreground service).
  • The app generates a notification that users see on the lock screen or in the notification tray.
  • The app is an active device admin app (for example, a device policy controller). Although they generally run in the background, device admin apps never enter App Standby because they must remain available to receive policy from a server at any time.

When the user plugs the device into a power supply, the system releases apps from the standby state, allowing them to freely access the network and to execute any pending jobs and syncs. If the device is idle for long periods of time, the system allows idle apps network access around once a day.

So, this means that starting from API 23 (Marshmallow), the device may actively put your app on standby, preventing network access (say for task like sync) and limiting (or disabling) background executions. Now, for most of the apps this behavior is fine or you could easily optimize for such behavior, but for some apps out there this may cause some unexpected behavior, especially for apps that have been poorly optimized or use non-standard sync strategies or some other means of background sync/execution.
So to circumvent that, the user can explicitly mark the app as non-optimized and the system will fallback and not put the app to standby, although this leads to a poorer user experience and you should not be doing this for regular apps that could be optimized.

How to make an Android app only run background services, and not be launcheable?

You said you didn't want to use a translucent Activity, but that seems to be the best way to do this:

1- In your Manifest, set the Activity theme to Theme.Translucent.NoTitleBar.

2- Don't bother with a layout for your Activity, and don't call setContentView().

3- In your Activity's onCreate(), start your Service with startService().

4- Exit the Activity with finish() once you've started the Service.

In other words, your Activity doesn't have to be visible; it can simply make sure your Service is running and then exit, which sounds like what you want.

how to hide luncher icon :

PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class); // activity which is first time open in manifiest file which is declare as <category android:name="android.intent.category.LAUNCHER" />
p.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

Hide open button couldn't be done , because we are talking about an application and not a google library

how to unhide icon :

PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class);
p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);

IMPORTANT: It's somehow tricky if you need to do something with main activity in your app when it's hidden. you will face an ActivityNotFoundException. to make it work, you should unhide icon before doing anything to your main activity and hide it again after you are finished.

How to make an android app run in background when the screen sleeps?

You need to make use of Service to get location updates even if screen sleep or your app is not open.

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class MyLocationService extends Service
{
private static final String TAG = "MyLocationService";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 3000;
private static final float LOCATION_DISTANCE = 10f;

LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};

@Override
public IBinder onBind(Intent arg0)
{
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}

@Override
public void onCreate()
{
Log.e(TAG, "onCreate");
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}

@Override
public void onDestroy()
{
Log.e(TAG, "onDestroy");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}

private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}

// create LocationListener class to get location updates
private class LocationListener implements android.location.LocationListener
{
Location mLastLocation;

public LocationListener(String provider)
{
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}

@Override
public void onLocationChanged(Location location)
{
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
}

@Override
public void onProviderDisabled(String provider)
{
Log.e(TAG, "onProviderDisabled: " + provider);
}

@Override
public void onProviderEnabled(String provider)
{
Log.e(TAG, "onProviderEnabled: " + provider);
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.e(TAG, "onStatusChanged: " + provider);
}
}
}

Add MyLocationService into your AndroidManifest.xml also:

<service android:name=".MyLocationService" android:process=":mylocation_service" />

Don't forgot to add below two permissions in your AndroidManifest.xml file:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Start Service from an activity:

You can start a service from an activity or other application component by passing an Intent (specifying the service to start) to startService(). The Android system calls the service's onStartCommand() method and passes it the Intent.

Intent intent = new Intent(this, MyLocationService.class);
startService(intent);

Update:

You need to hold partial wake lock to run service even after device screen off.

If you hold a partial wake lock, the CPU will continue to run, regardless of any display timeouts or the state of the screen and even after the user presses the power button.

To acquire wake lock:

PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();

To release it:

wakeLock.release();

Can an android app run in background continuously?

You cannot guarantee that the system won't close the service when it needs ram. Also there is doze to worry about (I don't know the exact interaction). Best you can do is start the service with START_STICKY, and the os will restart it as soon as it can.

As a solution you can look into AlarmManager, although I understand this is used more for scheduling one time operations.

Another thing to look into is the job scheduler class. If you need to support api lower than 21, there is also an open source implementation by firebase



Related Topics



Leave a reply



Submit