3. 监听车辆属性变化

任务说明

在Android Car服务中,车辆属性(如车速、挡位、充电状态等)由CarPropertyService统一管理。本案例实现一个可独立运行的监听模块:注册CarPropertyEventCallback,实时接收指定属性ID的变化回调,并将属性值变化打印到日志中,同时提供手动取消注册的入口。

环境与依赖

  • Android 10+(API 29+),系统签名或具备android.car.permission.CAR_INFO权限
  • 依赖android.car.Car、android.car.VehiclePropertyIds、android.car.property.CarPropertyManager
  • 需在Android Studio中创建Car App工程,并在AndroidManifest.xml中声明权限:
<uses-permission android:name="android.car.permission.CAR_INFO" />
<uses-permission android:name="android.car.permission.CAR_SPEED" />

关键完整代码

import android.car.Car;
import android.car.CarInfoManager;
import android.car.VehiclePropertyIds;
import android.car.property.CarPropertyEventCallback;
import android.car.property.CarPropertyManager;
import android.car.property.PropertyEvent;
import android.content.Context;
import android.util.Log;
import java.util.List;

public class VehiclePropertyListener {
    private static final String TAG = "VehiclePropListener";
    private final Context context;
    private Car car;
    private CarPropertyManager propertyManager;
    private CarPropertyEventCallback callback;
    private boolean isRegistered = false;

    // 监听的车速属性ID(单位:m/s)
    private static final int PROPERTY_ID = VehiclePropertyIds.PERF_VEHICLE_SPEED;

    public VehiclePropertyListener(Context context) {
        this.context = context;
    }

    /** 连接Car服务并注册监听,需在Car服务可用后调用 */
    public void startListening() {
        if (car == null) {
            car = Car.createCar(context, (Car car) -> {
                if (car != null) {
                    this.car = car;
                    propertyManager = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE);
                    registerCallback();
                } else {
                    Log.e(TAG, "Car service connection failed");
                }
            });
        } else {
            registerCallback();
        }
    }

    private void registerCallback() {
        if (propertyManager == null || isRegistered) return;

        callback = new CarPropertyEventCallback() {
            @Override
            public void onChangeEvent(CarPropertyValue value) {
                // 实时处理属性变化
                float speed = (float) value.getValue();
                Log.i(TAG, "Speed changed: " + speed + " m/s (" + (speed * 3.6) + " km/h)");
            }

            @Override
            public void onErrorEvent(int propertyId, int zone) {
                Log.e(TAG, "Error on property: " + propertyId + ", zone: " + zone);
            }
        };

        // 注册监听,仅监听PERF_VEHICLE_SPEED属性
        propertyManager.registerPropertyCallback(PROPERTY_ID, callback);
        isRegistered = true;
        Log.i(TAG, "Listener registered for property: " + PROPERTY_ID);
    }

    /** 取消注册并断开Car服务连接 */
    public void stopListening() {
        if (propertyManager != null && callback != null && isRegistered) {
            propertyManager.unregisterPropertyCallback(PROPERTY_ID, callback);
            isRegistered = false;
            Log.i(TAG, "Listener unregistered");
        }
        if (car != null) {
            car.disconnect();
            car = null;
            propertyManager = null;
        }
    }
}

调用方式

// 在Activity或Service中
VehiclePropertyListener listener = new VehiclePropertyListener(context);
listener.startListening();   // 开始监听

// 页面销毁或不再需要时
listener.stopListening();    // 停止监听并释放资源

验证方法

  1. 将应用部署到支持Car服务的模拟器或实车(需系统签名)
  2. 启动应用,调用startListening()后观察Logcat:
adb logcat -s VehiclePropListener:I
  1. 模拟车辆速度变化(实车行驶或模拟器发送属性变化事件),预期看到类似日志:
VehiclePropListener: Listener registered for property: 291
VehiclePropListener: Speed changed: 10.5 m/s (37.8 km/h)

通过条件:日志中出现Listener registered,且车辆速度变化时能持续打印Speed changed日志;调用stopListening()后不再收到变化回调。

常见问题

  • 权限不足:若未使用系统签名或缺少CAR_SPEED权限,注册回调会抛出SecurityException,需在registerCallback()中捕获处理。
  • 属性ID不匹配:不同车型对PERF_VEHICLE_SPEED的支持可能不同,可改用VehiclePropertyIds.SPEED(需额外权限)或先通过getPropertyList()确认可用属性。
  • 回调不触发:确认车辆实际运动且属性值发生变化;部分模拟器需手动注入属性变化事件。