Android onTaskRemoved() call to webservice
Asked Answered
C

2

4

Good day.I have horrible situation.I am creating an location share logic within session.I keep that session on server on the mysql.When android hits on that activity,i insert accordingly user information.When android leaves the activity ofcourse i delete that column so the session is abandoned for opposite side.All is great until one issue.Android does not provide an callback for app being swiped from recents,meanging app was killed completelly.I have found an work around there.I am using an service and starting service as soon as it reaches my desired activity.In service i have simple thing called onTaskRemoved() which notifies me as soon as the app was killed by swiping it from recents.All good until the point where i want to call to my server in order to remove the column.The call will not just get through,i will never receive any response there,but in onDestroy() everything working as expected.Actually here is the code

 @Override
public void onTaskRemoved(Intent rootIntent) {
    destroySession();
    super.onTaskRemoved(rootIntent);
}

private void destroySession() {
    Log.d("Fsafasfsafasfas", "destroySession: " + opponentId + " my user id" + sharedHelper.getUserId());
    Call<ResponseBody> locationCall = Retrofit.getInstance().getInkService().requestFriendLocation(sharedHelper.getUserId(), opponentId, "", "", Constants.LOCATION_REQUEST_TYPE_DELETE);
    locationCall.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if (response == null) {
                destroySession();
                return;
            }
            if (response.body() == null) {
                destroySession();
                return;
            }
            try {
                String responseBody = response.body().string();
                Log.d("Fsafasfsafasfas", "onResponse: " + responseBody);
                JSONObject jsonObject = new JSONObject(responseBody);
                boolean success = jsonObject.optBoolean("success");
                if (success) {
                    stopSelf();
                } else {
                    destroySession();
                }
            } catch (IOException e) {
                stopSelf();
                e.printStackTrace();
            } catch (JSONException e) {
                stopSelf();
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            destroySession();
        }
    });
}

The call will never get through i guess as the only log which is printed,is the id's logs and nothing more..Anyone have a clue whats going on?and how can i handle this situation?

Clotilda answered 17/8, 2016 at 14:13 Comment(2)
Hello, did you get any fix for this issue ? thank you.Ottillia
not yet :( coudl not get it throughClotilda
E
1

I solved this by canceling the strict mode of the thread policy. So http requests can be done from the main thread.

 StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
 StrictMode.setThreadPolicy(policy);

This is not recommended in regular situation, but when the app crashes or closed i guess its ok for sending one http request.

Echevarria answered 11/11, 2020 at 14:13 Comment(0)
E
6
/**
 * Created by Parag on 01/05/2017.
 */

public class AppService extends android.app.Service {
    public static final String TAG=AppService.class.getName();
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Bundle bundle=intent.getExtras();
        if(bundle!=null){
            final String logout=bundle.getString("logout");
            final String driverLoginId=bundle.getString("driverLoginId");
            if(logout!=null&&driverLoginId!=null){
                Toast.makeText(this, "logging out", Toast.LENGTH_SHORT).show();
                Log.e(TAG,"Logging out");
                Log.e(TAG,"Inside driverLogout "+driverLoginId);
                Call<LogoutResponse> call = RestHandler.getApiService().driverLogout(driverLoginId);
                call.enqueue(new Callback<LogoutResponse>() {
                    @Override
                    public void onResponse(Call<LogoutResponse> call, Response<LogoutResponse> response) {
                        //close the service on receiving response from API
                        Log.e("Response : ",response.body().getStatus()+"");
                        AppService.this.stopSelf();
                    }
                    @Override
                    public void onFailure(Call<LogoutResponse> call, Throwable t) {
                        //close the service on receiving response from API
                        AppService.this.stopSelf();
                    }
                });

            }else{
                //Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
                Log.e(TAG,"DriverLoginId : "+driverLoginId);
                Log.e(TAG,"Logout : "+logout);
            }
        }else{
            //Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
            Log.e(TAG,"Service Start");
        }
        return super.onStartCommand(intent,flags,startId);
    }

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

    @Override
    public void onTaskRemoved(Intent rootIntent) {

        Log.e(TAG,"Service Stop");
        UserLocalStore userLocalStore=new UserLocalStore(AppService.this);
        Log.e("USER DATA :",userLocalStore.fetchUserData().toString());
        Intent restartServiceTask = new Intent(getApplicationContext(),this.getClass());
        restartServiceTask.setPackage(getPackageName());
        restartServiceTask.putExtra("logout","true");
        restartServiceTask.putExtra("driverLoginId",userLocalStore.fetchUserData().getUserId());
        PendingIntent restartPendingIntent =PendingIntent.getService(getApplicationContext(), 1,restartServiceTask, PendingIntent.FLAG_ONE_SHOT);
        AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        myAlarmService.set(
                AlarmManager.ELAPSED_REALTIME,
                SystemClock.elapsedRealtime() + 1000,
                restartPendingIntent);
        super.onTaskRemoved(rootIntent);
    }


}

I was also facing the same issue of not being able to make any API calls from onTaskRemoved method. So, I also researched a lot but found no solution. So, I finally got an idea of restarting the web service with some extras placed inside the intent. In this manner you can differentiate when the service is restarted to execute your API call.

Ethanol answered 3/5, 2017 at 12:41 Comment(3)
It helped me. but I first checked also if intent is not null then do stuff. Here is my code: @Override public int onStartCommand(Intent intent, int flags, int startId) { if(intent!=null) { Bundle bundle = intent.getExtras(); if (bundle != null) { final String logout = bundle.getString("logout"); if (logout != null) { logoutAndStopServiceRightAway(); return START_NOT_STICKY; } } } return START_STICKY; }Describe
For some reason the code is not working on my oneplus 5 running android 10 while on my tablet samsung tab 7 running 7.1.1 it's working okHomogenesis
Same here. In android 8 the service is restarted but the intent extras are null.Echevarria
E
1

I solved this by canceling the strict mode of the thread policy. So http requests can be done from the main thread.

 StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
 StrictMode.setThreadPolicy(policy);

This is not recommended in regular situation, but when the app crashes or closed i guess its ok for sending one http request.

Echevarria answered 11/11, 2020 at 14:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.