I developed this app that needs to send data to Firestore when user press a button and ends when user stop it (by pressing another button). The data must be sent even if the user is doing other things or even if the user leavs the phone in standby for hours (so i need to avoid Doze and App Standby).
I used a service to achieve this and just one thing seems to work in the wrong way.
Service
public class MyService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
// vars declaration
private Date date = null;
// get every X seconds
public static final long DEFAULT_SYNC_INTERVAL = 60000;
private Runnable runnableService = new Runnable() {
@Override
public void run() {
class GetDataTask extends AsyncTask<String, Void, List<Data>> {
@Override
protected void onPreExecute() {
super.onPreExecute();
if(getPositionData.isCancelled()){
return;
}
}
@SuppressLint({"MissingPermission", "HardwareIds"})
@Override
protected List<Data> doInBackground(String... v) {
// skipping get Timestamp code
// skipping get position code
myPos = new Data(position.getId(), latitude, longitude, timestamp);
// Insert data into Firebase
documentReference = firebaseFirestore.collection("data").document();
Map<String, Object> data = new HashMap<>();
data.put("lat", myPos.getLat());
data.put("date", myPos.getDate().toString());
documentReference.set(data).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i("data", "data added.\n");
}
});
Toast.makeText(DataPollService.this, "" +
"ID: " + myPos.getImei()
+ " Latitude: " + myPos.getLat()
+ " Longitude " + myPos.getLng()
+ " Date: " + myPos.getDate()
, Toast.LENGTH_SHORT).show();
}
}
}, Looper.getMainLooper());
positionsList.add(myPos);
return positionsList;
}
protected void onPostExecute(List<Data> result) {
Position.getInstance().setPositions(result);
}
}
// RUN TASK
getPositionData = new GetDataTask();
getPositionData.execute(position.getId());
handler.postDelayed(runnableService, DEFAULT_SYNC_INTERVAL);
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ksurf)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
handler = new Handler();
handler.post(runnableService);
return START_NOT_STICKY;
}
// onBind
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
Log.d("show", "onDestroy");
handler.removeCallbacks(runnableService);
stopSelf();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
In MainActivity starting the service like this:
Intent serviceIntent = new Intent(this, MyService.class);
serviceIntent.putExtra("inputExtra", "run");
ContextCompat.startForegroundService(this, serviceIntent);
If I don't use the phone and let the app sending data in background, the data are not sent to Firebase until I open the app back again. The service is not stopped, I just need to open the app in order to send data to firebase! I read about Firebase Cloud Messaging but I didn't understand if I need them for my purpose. What am I doing wrong?