I have been struggling with this problem for several weeks , I believe the android OS restrict an app which is in the background this means the app cant access to gps after one or two hours when it is in the background . may be because of less battery usage .
the solution I am using is this :
this is BaseActivity which is used for every activity :
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
@Override
protected void onResume() {
MyApplication.activityResumed();
super.onResume();
}
}
here is MyApplication class :
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void setVisibilityTrue() {
activityVisible = true;
}
public static void activityResumed() {
boolean isScreenOn = true;
// isScreenOn() method is deprecated API level 21. You should use isInteractive instead:
PowerManager pm = (PowerManager) MyApplication.getInstance().getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
isScreenOn = pm.isInteractive();
} else {
isScreenOn = pm.isScreenOn();
}
if (isScreenOn) {
activityVisible = true;
}
}
public static void activityPaused() {
boolean isScreenOn = true;
PowerManager pm = (PowerManager) MyApplication.getInstance().getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
isScreenOn = pm.isInteractive();
} else {
isScreenOn = pm.isScreenOn();
}
if (isScreenOn) {
activityVisible = false;
}
}
private static boolean activityVisible;
}
when app is in the background we bring it to foreground , with a timer every 30 seconds we check if app screen is locked or not if it is locked we open the app :
private void bringApplicationToFront(Context context) {
/**
* check if motitor screen is Off/On
* */
boolean isScreenOn = true;
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
isScreenOn = pm.isInteractive();
} else {
isScreenOn = pm.isScreenOn();
}
if (!isScreenOn) {
/**
* check if app is fore/back ground
* */
boolean isInForeBackground = false;
try {
isInForeBackground = MyApplication.isActivityVisible();
} catch (Exception e) {
e.printStackTrace();
}
if (!isInForeBackground) {
Intent notificationIntent = new Intent(context, ActivitySplash.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
try {
pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
}
}
the tricky part is when app is in the background and screen is locked the onPause() is called after reopening the app (bring it to foreground) means
activityVisible is set to false (means not visible which is not true), actually it is correct but it is not what I wanted , to solve this problem I never let the activityVisible to be set when screen is locked and when app is reopened in splash I set the activityVisible to true.
I think if the app comes to foreground its priority is high then it can use gps all the time .
I hope I could explain my solution properly .
All the best ...