我有一个带有LoginScreen的应用程序。该应用程序还会在一段时间后注销用户。我使用AlarmManager和BroadcastReceiver来执行此操作。 但是在我的BroadcastReceiver.onReceive()中我需要知道我的应用程序是否在前台!!
我找到了这样的来源:
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;
}
它适用于我的API 21设备...但它总是在我的API 18设备上带来错误!!
问题1是:我该怎么办API18设备?
问题2是:如果我使用此应用程序访问PlayStore,我是否会收到Google的拒绝? 因为谷歌说here
注意:此方法仅用于调试或构建面向用户的流程管理UI。
来自here的一条评论说“拒绝”
更新
更清楚一点: 例如,5分钟后,广播接收器获得BroadcastReceiver.onReceive()。现在必须调用LoginActivity,用户必须再次登录才能使用App。
但如果用户在Foreground中有我的应用程序不(因为他此时正在使用地图或电子邮件),则不应在Foreground中弹出登录活动,因此我将其发送到背景中
moveTaskToBack(true);
但是,当BroadcastReceiver.onReceive()出现时,我想找到一种方法来清楚地找出我在后台或前景中的应用程序。
答案 0 :(得分:0)
在您的应用程序中使用一些EventBus。也许来自GreenRobot。
在您的BroadcastReceiver中,只发送一个时间已过的事件,然后在您的活动注册表中发送此事件。如果某些活动可见且处于活动状态 - 它将接收该事件,然后您可以注销您的用户。您不必检查您的应用是否处于后台,因为当您在适当的时间从EventBus注册和取消注册您的活动时,他们只会在前景中做出反应。
在取消注册时注册的正确时间我指的是onResume和onPause方法(或onCreate / onDestroy)。
PS。使用此解决方案,您不应该被Play商店拒绝。
答案 1 :(得分:0)
经过多年的调查,我找到了解决我的特殊问题的方法。
灵感来自this Answer你开始使用这样的ActivityLifecycleCallbacks:
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;
}
}
}
接收AlarmManager的我的BroadcastReceiver如下所示:
public class LogoutReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ContextUtils.appIsInBackground = MyLifecycleHandler.isApplicationInBackground();
EventBus.getDefault().post(new AutoLogoutEvent());
}
}
ContextUtils()只要在调用Receiver以供日后使用时,只需保留Moment中的值。
捕获AutoLogoutEvent()并调用此Intent函数:
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);
}
特别之处:如果应用程序处于后台,则KITKAT(API19)之前的Android版本无法启动活动。所以我必须设置回 ContextUtils.appIsInBackground ,因为如果不是这样,并且你试图在这个时刻将应用程序返回到前景,则调用Activity的onCreate()但是具有错误的值并且应用程序第一次来到Foreground ...你必须点击两次。这里的活动:
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();
}
}
....
}
所以这适用于 ME 。愿你找到更好的解决方案......请让我知道!!!