I want to create an app that is constantly checking for location change and put the current location in the firebase (e.g. an app for runners).
Unfortunately the foregroundservice is being stopped or paused every time the device go into sleep mode.
For starters I wanted to create a foreground service that is continuously writing information to the base (that would be a time stamp or a simple string) every second. After some time it just stops writing to firebase without calling stopself().
The service is working fine on the emulator (even if put to sleep), but stops when tested on a real device – in my case Huawei, Android 8.1.0. What should I do to force service to run in every state of the device?
My MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "start");
startForegroundService(intent);
}
else {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "start");
startService(intent);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "stop");
startForegroundService(intent);
}
else {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "stop");
startService(intent);
}
}
}
MyService:
public class MyService extends Service {
int i =0;
private String CHANNEL_ID = "2345";
@Override
public void onCreate() {
super.onCreate();
}
public MyService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(1000, createNotification());
String action = intent.getExtras().getString("action");
switch (action){
case "start":
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
myfunction();
handler.postDelayed(this, 1000);
}
};
break;
case "stop":
stopfunction();
break;
}
handler.postDelayed(runnable, 1000);
return START_NOT_STICKY;
}
private void stopfunction() {
stopSelf();
}
private void myfunction() {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("locations");
myRef.child("location").setValue(i);
i++;
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
@RequiresApi(Build.VERSION_CODES.O)
private void createChannel(){
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, getString(R.string.infoTxt),
NotificationManager.IMPORTANCE_HIGH);
channel.setShowBadge(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
notificationManager.createNotificationChannel(channel);
}
private Notification createNotification(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
createChannel();
}
Intent notificationItent = new Intent(this, MainActivity.class);
notificationItent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(this, 0, notificationItent, 0);
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setColor(ContextCompat.getColor(this, android.R.color.background_dark))
.setContentIntent(intent)
.setSmallIcon(R.drawable.ic_launcher_background)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOnlyAlertOnce(true)
.setContentTitle("GPS Location")
.build();
}
}
I've tried everything: service, foreground service, broadcast receiver, jobSheduler, WorkerManager – nothing helped. Then I found it’s a new HUAWEI feature called “power-intensive app monitor “. It kills every app that runs in the background for a long time unless user gives special permissions to it. The path to do this: Settings -> Security & privacy -> Location services -> recent location requests: YOUR APP NAME -> Battery -> uncheck Power-intensive prompt, App launch: Manage manually: check all three positions: Auto-launch, secondary launch, run in background.
I don’t know is there a way to do this programmatically. I think the best way is to create a sort of help activity and explain the user what to do if application won’t work.