You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:50:08