Android Request to server before application compeletly closed

1.2k views Asked by At

I have just one Activity , when user close the application (from os clear list of recent apps) I want to send a request to my server api and change user status. so I make IntentService and call it in my onDestroy() method of activity, but it dosn't work. how do it? is there any way else to do this(send request to server before application killed compeletly)? my code :

Activity:

@Override
protected void onDestroy() {
    Intent intent = new Intent(this, MakeOfflineIntentService.class);
    intent.putExtra(Variables.INTENT_TOKEN, Token);
    intent.setAction("ACTION_MAKE_OFFLINE");
    startService(intent);
    super.onDestroy();
}

and in my IntentService:

public class MakeOfflineIntentService extends IntentService {

private static final String ACTION_MAKE_OFFLINE = "ACTION_MAKE_OFFLINE";

private static final String EXTRA_TOKEN = Variables.INTENT_TOKEN;

public MakeOfflineIntentService() {
    super("MakeOfflineIntentService");
}

public static void startActionFoo(Context context, String param1) {
    Intent intent = new Intent(context, MakeOfflineIntentService.class);
    intent.setAction(ACTION_MAKE_OFFLINE);
    intent.putExtra(EXTRA_TOKEN, param1);
    context.startService(intent);
}

@Override
protected void onHandleIntent(Intent intent) {
    if (intent != null) {
        final String action = intent.getAction();
        if (ACTION_MAKE_OFFLINE.equals(action)) {
            final String param1 = intent.getStringExtra(EXTRA_TOKEN);
            retrofitBaseInformationChange(param1,Variables.OFFLINE,1);
        }
    }
}

private void retrofitBaseInformationChange(final String Token, final int online, int vehicle){
    RetrofitCallServer retrofitCallServer = new RetrofitCallServer(WebServiceUrls.RETROFIT_INFORMATION_CHEETAH_MAN);
    OnCallBackRetrofit onCallBackRetrofit = retrofitCallServer.getResponse();

    Call<OBRbaseInfromationChange> call = onCallBackRetrofit.askBaseInformationChange(Token,online,vehicle);
    call.enqueue(new Callback<OBRbaseInfromationChange>() {

        @Override
        public void onResponse(Call<OBRbaseInfromationChange> call, Response<OBRbaseInfromationChange> response) {
            /*response gotten maybe success or not*/
            if (response.isSuccessful()){
                OBRbaseInfromationChange obr = response.body();
                if(obr.code == 200){
                    Log.i(Variables.APP_TAG,"BaseInformationChange successful");
                }
                else{
                    Log.i(Variables.APP_TAG,"BaseInformationChange error code: "+obr.code);
                }
            }// end if response successful
            else {
                Log.i(Variables.APP_TAG,"BaseInformationChange not Successful: "+response.code());
            }
        }

        @Override
        public void onFailure(Call<OBRbaseInfromationChange> call, Throwable t) {
            /*our request not sent or conversion problem*/
            Log.i(Variables.APP_TAG,"onFailure BaseInformationChange: "+t.getMessage());
        }

    });
}
// end retrofitBaseInformationChange()

}

and finally here is in my manifest:

<service
        android:name=".Services.MakeOfflineIntentService"
        android:exported="false"
        android:stopWithTask="false"/>
2

There are 2 answers

2
Grisgram On BEST ANSWER

Have you tried to return START_STICKY in the onStartCommand override?

After you sent your request you can then call stopService to stop yourself.

As far as I know, even sticky services might be "recreated" when you kill the app. So maybe, an Intent is not the best way to use here.

I'd go with SharedPreferences here:

  • The onCreate of your app sets the key "app_offline" to "false"

  • The onDestroy sets this key to "true" and starts the service

  • The service is START_STICKY and when it finds the "app_offline" as true, sends its request, updates "app_offline" to false (resets it) and then performs a self-shutdown.

Something like that. Hope this helps, cheers, Gris

0
Mohad Hadi On

thanks for Grisgram answer, I solve the issue and paste my code here for more complete answer :

I make a variable in SharedPreferences name IS_APP_CLOSED. when application open in onCreate :

saveL.saveInLocalStorage(Variables.IS_APP_CLOSED,false);
    startServiceToMakeOffline();

method startServiceToMakeOffline() is :

private void startServiceToMakeOffline(){
    Intent intent= new Intent(this, MakeOfflineService.class);
    startService(intent);
}

in onDestroy of this activity :

@Override
protected void onDestroy() {
    saveL.saveInLocalStorage(Variables.IS_APP_CLOSED,true);
    super.onDestroy();
}

and here is my service class :

public class MakeOfflineService extends Service {

private boolean isAppClosed = false;

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

    loadInfoFromLocalStorage();
    if(isAppClosed){
        askServer();
    }

    return Service.START_STICKY;

}

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

private void loadInfoFromLocalStorage() {
    SharedPreferences prefs = getApplicationContext().getSharedPreferences(Variables.CHEETAH_NORMAL, 0);
    isAppClosed     = prefs.getBoolean(Variables.IS_APP_CLOSED, false);
    prefs = null;
}
// end loadInfoFromLocalStorage()


private void askServer() {
    //TODO: request server than when result gotten:
    stopSelf();
}
}

and here is my manifest :

<service
        android:name=".Services.MakeOfflineService"
        android:stopWithTask="false"/>