Activity Recognition API首次过渡异常:Android 8.1启动即触发事件
解决Android 8.1上Activity Transition首次启动触发初始事件的问题
我之前也碰到过一模一样的问题,这其实是Android 8.1(API Level 27)特有的行为差异:当你首次调用requestActivityTransitionUpdates()注册过渡监听时,系统会主动推送一个对应当前设备活跃状态的ENTER事件来同步初始状态;但在Android 6.0这类低版本系统中,只会在状态发生实际变化时才触发过渡事件,不会推送初始状态事件。
下面给你两种可行的解决方案,你可以根据业务需求选择:
方案1:简单忽略首次触发的初始事件
如果你只关心状态变化的事件,不需要同步初始状态,可以直接在逻辑里加个标记过滤第一个事件。
修改你的ServiceS类,添加一个全局标记变量:
// 在ServiceS类中添加全局变量 private static boolean isFirstTransitionEvent = true;
然后更新transitionArrived方法:
static void transitionArrived(final ActivityTransitionEvent event, final Context context){ // 过滤首次触发的初始事件 if (isFirstTransitionEvent) { isFirstTransitionEvent = false; Log.d("hmm: ", "忽略首次初始过渡事件: " + event.toString()); return; } Log.d("hmm: ", event.toString()); Toast.makeText(context, event.getActivityType() + "-" + event.getTransitionType(), Toast.LENGTH_LONG).show(); }
⚠️ 注意:如果你的服务可能被系统回收重启,建议把这个标记存到SharedPreferences里,避免重启后误过滤正常的状态变化事件。
方案2:先获取当前状态,过滤重复的初始ENTER事件
这个方案更严谨,适合需要初始状态但不想重复触发的场景:先主动获取当前设备的活动状态,收到过渡事件时判断是否是当前状态的重复ENTER,是就忽略。
首先在ServiceS里添加获取当前活动状态的方法和全局变量:
// 在ServiceS类中添加全局变量 private static int currentActivityType = -1; @SuppressLint("MissingPermission") private void fetchCurrentActivityState() { ActivityRecognition.getClient(this) .getCurrentActivity() .addOnSuccessListener(activityRecognitionResult -> { if (activityRecognitionResult != null && !activityRecognitionResult.getProbableActivities().isEmpty()) { // 取置信度最高的当前活动状态 DetectedActivity currentActivity = activityRecognitionResult.getProbableActivities().get(0); currentActivityType = currentActivity.getType(); Log.d("hmm: ", "当前检测到的活动状态: " + currentActivityType); } }) .addOnFailureListener(e -> Log.e("hmm: ", "获取当前活动状态失败", e)); }
然后在onStart方法里先获取当前状态,再注册过渡监听:
@Override public void onStart(Intent intent, int startId) { fetchCurrentActivityState(); // 先获取当前状态 if(transitionRequest==null) { transitionRequest = new ActivityTransitionRequest(transitions); } Task task = ActivityRecognition.getClient(this) .requestActivityTransitionUpdates(transitionRequest, activityPendingIntent); super.onStart(intent, startId); }
最后修改transitionArrived方法过滤重复事件:
static void transitionArrived(final ActivityTransitionEvent event, final Context context){ // 判断是否是当前状态的重复初始ENTER事件 if (currentActivityType != -1 && event.getTransitionType() == ActivityTransition.ACTIVITY_TRANSITION_ENTER && event.getActivityType() == currentActivityType) { Log.d("hmm: ", "忽略重复的初始ENTER事件: " + event.toString()); return; } Log.d("hmm: ", event.toString()); Toast.makeText(context, event.getActivityType() + "-" + event.getTransitionType(), Toast.LENGTH_LONG).show(); }
这个方案的优势是,即使服务被系统重启,也会重新获取当前状态,不会误过滤正常的状态切换事件。
内容的提问来源于stack exchange,提问作者ucanyiit
相关产品推荐
相关产品推荐

