检测用户何时启动或结束 Activity

您可能需要设计应用以确定用户何时启动或停止特定 Activity(例如步行、骑车或驾车)。例如,里程跟踪应用可以在用户开始驾车时开始跟踪里程,或者短信应用可以在用户停止驾车之前忽略所有会话。

Activity Recognition Transition API 可用于检测用户 Activity 的变化。您的应用订阅了相关 Activity 中的转换,并且该 API 仅在需要时通知您的应用。此页面介绍了如何使用 Activity Recognition Transition API(以下简称 Transition API)。

设置项目

要在应用中使用 Transition API,您必须在清单文件中声明依赖 Google Location and Activity Recognition API 12.0.0 或更高版本,并指定 com.google.android.gms.permission.ACTIVITY_RECOGNITION 权限。

  1. 要声明依赖该 API,请添加对 Google Maven 代码库的引用,并将 com.google.android.gms:play-services-location:12.0.0 的实现条目添加到应用 build.gradle 文件的 dependencies 部分。如需了解详情,请参阅设置 Google Play 服务
  2. 要指定 com.google.android.gms.permission.ACTIVITY_RECOGNITION 权限,请在应用清单中添加 <uses-permission> 元素,如下例所示:

     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                 package="com.example.myapp">
    
           <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
           …
         </manifest>
        

注册 Activity 转换更新

要开始接收有关 Activity 转换的通知,您必须实现以下两项:

要创建 ActivityTransitionRequest 对象,您必须创建 ActivityTransition 对象的列表,表示您要接收其相关通知的转换。ActivityTransition 对象包含以下数据:

以下代码展示了如何创建 ActivityTransition 对象的列表:

Kotlin

    val transitions = mutableListOf<ActivityTransition>()

    transitions +=
            ActivityTransition.Builder()
              .setActivityType(DetectedActivity.IN_VEHICLE)
              .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
              .build()

    transitions +=
            ActivityTransition.Builder()
              .setActivityType(DetectedActivity.IN_VEHICLE)
              .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
              .build()

    transitions +=
            ActivityTransition.Builder()
              .setActivityType(DetectedActivity.WALKING)
              .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
              .build()
    

Java

    List<ActivityTransition> transitions = new ArrayList<>();

    transitions.add(
            new ActivityTransition.Builder()
              .setActivityType(DetectedActivity.IN_VEHICLE)
              .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
              .build());

    transitions.add(
            new ActivityTransition.Builder()
              .setActivityType(DetectedActivity.IN_VEHICLE)
              .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
              .build());

    transitions.add(
            new ActivityTransition.Builder()
              .setActivityType(DetectedActivity.WALKING)
              .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
              .build());
    

您可以通过向 ActivityTransitionRequest 类传递 ActivityTransitions 的列表来创建 对象,如下例所示:

Kotlin

    val request = ActivityTransitionRequest(transitions)
    

Java

    ActivityTransitionRequest request = new ActivityTransitionRequest(transitions);
    

您可以通过将 ActivityTransitionRequest 的实例和 PendingIntent 对象传递到 requestActivityTransitionUpdates() 方法来注册 Activity 转换更新。requestActivityTransitionUpdates() 方法会返回 Task 对象,您可以检查此方法是否成功,如以下代码示例所示:

Kotlin

    // myPendingIntent is the instance of PendingIntent where the app receives callbacks.
    val task = ActivityRecognition.getClient(context)
            .requestActivityTransitionUpdates(request, myPendingIntent)

    task.addOnSuccessListener {
        // Handle success
    }

    task.addOnFailureListener { e: Exception ->
        // Handle error
    }
    

Java

    // myPendingIntent is the instance of PendingIntent where the app receives callbacks.
    Task<Void> task = ActivityRecognition.getClient(context)
              .requestActivityTransitionUpdates(request, myPendingIntent);

    task.addOnSuccessListener(
        new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void result) {
                // Handle success
            }
        }
    );

    task.addOnFailureListener(
        new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                // Handle error
            }
        }
    );
    

成功注册 Activity 转换更新后,您的应用会在已注册的 PendingIntent 中接收通知。

处理 Activity 转换事件

当发生请求的 Activity 转换时,您的应用会收到 Intent 回调。可以从 Intent 中提取 ActivityTransitionResult 对象,其中包括 ActivityTransitionEvent 对象的列表。这些事件按时间先后顺序排序,例如,如果应用在 ACTIVITY_TRANSITION_ENTERACTIVITY_TRANSITION_EXIT 转换时请求 IN_VEHICLE Activity 类型,那么它会在用户开始驾车时收到 ActivityTransitionEvent 对象,并在用户转换到其他任何 Activity 时收到另一个对象。

您可以通过创建 BroadcastReceiver 的子类并实现 onReceive() 方法来获取 Activity 转换事件列表,从而实现回调。如需了解详情,请参阅广播。以下示例展示了如何实现 onReceive() 方法:

Kotlin

    override fun onReceive(context: Context, intent: Intent) {
        if (ActivityTransitionResult.hasResult(intent)) {
            val result = ActivityTransitionResult.extractResult(intent)!!
            for (event in result.transitionEvents) {
                // chronological sequence of events....
            }
        }
    }
    

Java

    @Override
    public void onReceive(Context context, Intent intent) {
        if (ActivityTransitionResult.hasResult(intent)) {
            ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);
            for (ActivityTransitionEvent event : result.getTransitionEvents()) {
                // chronological sequence of events....
            }
        }
    }
    

取消注册 Activity 转换更新

您可以通过调用 ActivityRecognitionClientremoveActivityTransitionUpdates() 方法并将 PendingIntent 对象作为参数传递,以取消注册 Activity 转换更新,如下例所示:

Kotlin

    // myPendingIntent is the instance of PendingIntent where the app receives callbacks.
    val task = ActivityRecognition.getClient(context)
            .removeActivityTransitionUpdates(myPendingIntent)

    task.addOnSuccessListener {
        myPendingIntent.cancel()
    }

    task.addOnFailureListener { e: Exception ->
        Log.e("MYCOMPONENT", e.message)
    }
    

Java

    // myPendingIntent is the instance of PendingIntent where the app receives callbacks.
    Task<Void> task = ActivityRecognition.getClient(context)
            .removeActivityTransitionUpdates(myPendingIntent);

    task.addOnSuccessListener(
        new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void result) {
                myPendingIntent.cancel();
            }
        }
    );

    task.addOnFailureListener(
        new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                Log.e("MYCOMPONENT", e.getMessage());
            }
        }
    );