Issue
I have an App with a LoginScreen. The App also logout the User after a certain amount of time. I use a AlarmManager and a BroadcastReceiver for doing this. But in my BroadcastReceiver.onReceive() i need to know is my App in foreground or not!!
I've found some source like this:
private boolean isAppInBackground(){
boolean retValue = true;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String activeProcess : processInfo.pkgList) {
if (activeProcess.equals(context.getPackageName())) {
retValue = false;
}
}
}
}
return retValue;
}
it works on my API 21 Device... but it always brings false at my API 18 Device!!
Question 1 is: what can I do for a API18 Device?
Question 2 is: Will I get a reject from Google if I go to the PlayStore with this App?? Because Google said here
Note: this method is only intended for debugging or building a user-facing process management UI.
And one Comment from here said something from "reject"
UPDATE:
To be a bit more clear: For Example after 5 minutes the Broadcast Receiver get's BroadcastReceiver.onReceive(). Now the LoginActivity has to be called and the User must login again to use the App.
But if the User has my App not in Foreground (because he is using Maps or EMail at this Time) the Login Activity should NOT popup in Foreground so i send it in Background with
moveTaskToBack(true);
But i look for a way to clearly find out is my app in Background or Foreground in the Moment when BroadcastReceiver.onReceive() comes up.
Solution
After Years of investigation i found a Solution for MY special Problem.
Inspired by this Answer u start using ActivityLifecycleCallbacks like this:
public class MyLifecycleHandler implements Application.ActivityLifecycleCallbacks {
private static ActivityNames activityNameList = new ActivityNames();
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
activityNameList.add(activity.getLocalClassName().hashCode());
}
@Override
public void onActivityDestroyed(Activity activity) {
activityNameList.remove(activity.getLocalClassName().hashCode());
}
@Override
public void onActivityResumed(Activity activity) {
activityNameList.add(activity.getLocalClassName().hashCode());
}
@Override
public void onActivityPaused(Activity activity) {
activityNameList.remove(activity.getLocalClassName().hashCode());
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
activityNameList.remove(activity.getLocalClassName().hashCode());
}
@Override
public void onActivityStarted(Activity activity) {
activityNameList.add(activity.getLocalClassName().hashCode());
}
@Override
public void onActivityStopped(Activity activity) {
activityNameList.remove(activity.getLocalClassName().hashCode());
}
public static boolean isApplicationInBackground() {
return activityNameList.isApplicationInBackground();
}
private static class ActivityNames {
private List<Integer> nameList;
void add(int value){
if(nameList == null){
nameList = new ArrayList<>();
}
if(nameList.contains(value)) return;
nameList.add(value);
}
void remove(Integer value){
if(nameList == null || nameList.size() < 1) return;
nameList.remove(value);
}
boolean isApplicationInBackground(){
if(nameList == null) return true;
if(nameList.size() == 0) return true;
return false;
}
}
}
My BroadcastReceiver to receive the AlarmManager looks like this:
public class LogoutReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ContextUtils.appIsInBackground = MyLifecycleHandler.isApplicationInBackground();
EventBus.getDefault().post(new AutoLogoutEvent());
}
}
ContextUtils() just hold the Value in the Moment when the Receiver gets called for later use.
AutoLogoutEvent() is catched and calls this Intent Function:
public void showAuthentication(Activity context) {
Intent i = new Intent(context, LoginActivity.class);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
ContextUtils.appIsInBackground = false;
}
context.startActivity(i);
}
Special here: Android Versions prior KITKAT (API19) didn't start the Activity if the App is in Background. So i have to set back this ContextUtils.appIsInBackground because if not so, and you try to get Back the App to Foreground in this Moment the onCreate() of the Activity is called but has the wrong Value and the App comes not to Foreground the first time... you have to click twice. Here the Activity:
public class LoginActivity extends MosbyActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
boolean appIsInBackground = false;
appIsInBackground = ContextUtils.appIsInBackground;
ContextUtils.appIsInBackground = false;
if(appIsInBackground){
moveTaskToBack(true);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, new LoginFragment())
.commit();
}
}
....
}
so this WORKS for ME. May you find a better Solution... Please let me know!!!
Answered By - HowardS
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.