Android Automotive 访问传感器数据

419 阅读2分钟

版权声明

凡未经作者授权,任何媒体、网站及个人不得转载、复制、重制、改动、展示或使用局部或全部的内容或服务。如果已转载,请自行删除。同时,我们保留进一步追究相关行为主体的法律责任的权利。

© 2023 小酥肉不加辣,All rights reserved.

前言

如果你还不知道如何开始在 Android Automotive OS 上开发车机应用,请阅读我的另一篇文章《如何开始在 Android Automotive OS 上开发应用》。另外,也可以订阅我的车机开发专栏,及时阅读我的最新文章。

本文主要讲述如何访问汽车传感器数据。

正文

假设我们已经搭建好开发环境,并已经新建一个空白的 Android Automotive 项目。

第一步,我们需要在模块构建文件中添加一个库引用:

android {
    ...
    
    useLibrary 'android.car'
    
    ...
}

然后,我们需要声明一个 Car 对象,它将负责和汽车建立连接并获取具体的汽车管理类:

class MainActivity : AppCompatActivity() {

    private lateinit var car : Car

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

现在我们已准备好创建 Car 对象并与汽车服务建立连接。

在初始化之前,我们应该检查系统是否支持汽车功能。否则,我们对 Car API 的调用可能会抛出异常。

在此之后,我们可以使用 Car API 提供的静态方法 createCar() 初始化 Car 对象,并在其中两个函数回调中处理建立连接成功和失败的逻辑。

override fun onCreate(savedInstanceState: Bundle?) {
    initCar()
}
    
private fun initCar() {
    if (!packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
        return
    }

    if(::car.isInitialized) {
        return
    }

    car = Car.createCar(this, object : ServiceConnection {
        override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
            onCarServiceReady()
        }

        override fun onServiceDisconnected(componentName: ComponentName) {
            // on failure callback
        }
    })
}

private fun onCarServiceReady() {
    // Do something
}

下一步是建立一个与汽车服务的连接,并让我们的应用程序在 Activity 生命周期中正确地管理它。 实现此目的的最佳方法是在 onResume()onPause() 中调用适当的方法。

...

override fun onResume() {
    super.onResume()
    if (!car.isConnected && !car.isConnecting) {
        car.connect()
    }
}

override fun onPause() {
    if(car.isConnected) {
        car.disconnect()
    }
    super.onPause()
}

...

现在打开模拟器,看一下有哪些传感器数据

Image 2023-3-17 at 13.33.jpg

以车辆速度为例,我们可以尝试从速度传感器收集数据。让我们创建一个名为 watchSpeedSensor() 的方法,并使用 Car.SENSOR_SERVICE 初始化 CarSensorManager。然后注册一个监听器来接收传感器数据。

private fun watchSpeedSensor() {
    val sensorManager = car.getCarManager(Car.SENSOR_SERVICE) as CarSensorManager
    sensorManager.registerListener(
        { carSensorEvent ->
            Log.d("MainActivity", "Speed: ${carSensorEvent.floatValues[0]}")
        },
        CarSensorManager.SENSOR_TYPE_CAR_SPEED,
        CarSensorManager.SENSOR_RATE_NORMAL
    )
}

当前的代码还不能运行,因为需要申请特定的权限才可以正常使用,以下列出所有的传感器数据及对应的权限:

SensorPermission
SpeedPERMISSION_SPEED
GearPERMISSION_POWERTRAIN
Night modePERMISSION_EXTERIOR_ENVIRONMENT
Fuel levelPERMISSION_ENERGY
ABSPERMISSION_CAR_DYNAMICS_STATE

现在,我们在 AndroidManifest.xml 文件中添加一行:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.car">
    ...
    
    <uses-permission android:name="android.car.permission.CAR_SPEED" />

    ...

</manifest>

下一步,在连接之前检查权限是否已经授权

class MainActivity : AppCompatActivity() {
    
    private lateinit var car : Car
    private val permissions = arrayOf(Car.PERMISSION_SPEED)
    
    ...

    override fun onResume() {
        super.onResume()
	if(checkSelfPermission(permissions[0]) == PackageManager.PERMISSION_GRANTED) {
	    if (car?.isConnected == false && car?.isConnecting == false) {
	        car?.connect()
	    }
	} else {
	    requestPermissions(permissions, 0)
	}
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
	super.onRequestPermissionsResult(requestCode, permissions, grantResults)
	if (permissions[0] == Car.PERMISSION_SPEED && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
	    if (!car.isConnected && !car.isConnecting) {
	        car.connect()
	    }
	}
    }

    private fun onCarServiceReady() {
        watchSpeedSensor()
    }

    private fun watchSpeedSensor() {
	val sensorManager = car.getCarManager(Car.SENSOR_SERVICE) as CarSensorManager
	sensorManager.registerListener(
	    { carSensorEvent ->
	        Log.d("MainActivity", "Speed: ${carSensorEvent.floatValues[0]}")
            },
	    CarSensorManager.SENSOR_TYPE_CAR_SPEED,
	    CarSensorManager.SENSOR_RATE_NORMAL
	)
    }
}

运行之后,查看结果:

D/MainActivity: Speed: 1.0
D/MainActivity: Speed: 2.0
D/MainActivity: Speed: 3.0
D/MainActivity: Speed: 4.0
D/MainActivity: Speed: 5.0
D/MainActivity: Speed: 6.0
D/MainActivity: Speed: 7.0
D/MainActivity: Speed: 8.0
D/MainActivity: Speed: 9.0
D/MainActivity: Speed: 10.0
D/MainActivity: Speed: 11.0
D/MainActivity: Speed: 10.0
D/MainActivity: Speed: 11.0
D/MainActivity: Speed: 12.0
D/MainActivity: Speed: 13.0
D/MainActivity: Speed: 14.0
D/MainActivity: Speed: 15.0
D/MainActivity: Speed: 16.0

好了,现在你的 App 可以读取传感器的数据了。