steveliles/Foredroid

App became Background when request permission.

Opened this issue · 7 comments

When I request permission, App became Background.
screen shot 2017-05-13 at 15 53 04

package com.sjl.foreground.demo;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.sjl.foreground.Foreground;

import java.util.ArrayList;
import java.util.List;

public abstract class DemoActivity extends ActionBarActivity implements Foreground.Listener {

    private Foreground.Binding listenerBinding;

    protected abstract void startAnotherActivity();

    public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //startAnotherActivity();
                //composeEmail(new String[]{"asdasd"},"asdas");
                ActivityCompat.requestPermissions(DemoActivity.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        1);
            }
        });

        listenerBinding = Foreground.get(getApplication()).addListener(this);
    }

    public void composeEmail(String[] addresses, String subject) {
        Intent intent = new Intent(Intent.ACTION_SENDTO);
        intent.setData(Uri.parse("mailto:")); // only email apps should handle this
        intent.putExtra(Intent.EXTRA_EMAIL, addresses);
        intent.putExtra(Intent.EXTRA_SUBJECT, subject);
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivity(intent);
        }
    }

    private  boolean checkAndRequestPermissions() {
        int permissionSendMessage = ContextCompat.checkSelfPermission(this,
                Manifest.permission.SEND_SMS);
        int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
        List<String> listPermissionsNeeded = new ArrayList<>();
        if (locationPermission != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.SEND_SMS);
        }
        if (!listPermissionsNeeded.isEmpty()) {
            ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
            return false;
        }
        return true;
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();

        // not strictly necessary as Foreground only holds a weak reference
        // to the listener to defensively prevent leaks, but its always better
        // to be explicit and WR's play monkey with the Garbage Collector
        listenerBinding.unbind();
    }

    @Override
    public void onBecameForeground() {
        Log.d(Foreground.TAG, getClass().getName() + " became foreground");
    }

    @Override
    public void onBecameBackground() {
        Log.d(Foreground.TAG, getClass().getName() + " went background");
    }

}

hm, but that's a system modal dialog not an app dialog, so to be fair your app is not in the foreground right now ...

Do you have a solution to this problem? Because the user still thinks it is on the foreground

The reason for this problem is that:
This library use onPause hack way to listen the application enter foreground or background switch, for compat some edge cases (like receive a phone call). But some times, it couse logical confusion in other scenes.

When request permissions, the activity will call onPause, don't not call onStop(Because the activity is still visiable.). But you can't listen system callbacks.

The solution is, only use onStop (not onPause) to handle the logic.
Please see the discuss on #15.

@TakWolf I know this library is not perfect, but I'm also not convinced there's a logical confusion.

I think that as far as the system is concerned the app is in the background - both in the permissions case and the phone call case - because the foreground UI in both cases is not a UI controlled by the app, and the app has been told to pause. The purpose of this library is to tell you when the system thinks the app is in the background, so it seems to me that it is behaving correctly.

That said, I am quite sympathetic to Sammy's case where a permission request is being handled, and actually in that case there is something you can do about it:

@chihung93 You could use the fact that you know when a call to ActivityCompat.requestPermissions is in flight (because you call it) and you know when it completes (because you get called back on onRequestPermissionsResult) ... so ...

  • set a flag in your app when you're about to request permissions
  • unset it again when you receive the callback
  • check that flag before doing whatever it is you only want to do when the app is background

@steveliles : thank you for your help .
I think you are right even though the user does not understand this case, because the dialog is of the system .
Anyway thank you for taking the time to write this library.

@TakWolf : I found a lib to avoid this issue .You should try it , maybe it suits your situation.
P.s : It's work for me.

https://github.com/jenzz/RxAppState

@chihung93 Thanks for the offer, I will try to use it.