[英]How to set a mock sensor (accelerometer) in android device using programmatically
如何在 Android 设备上设置模拟传感器?
是否可以使用 Android API 设置模拟传感器,或者我们需要使用 NDK 和 JNI 还是使用第三方库?
谁能告诉我如何实现这个?
我需要模拟一个陀螺仪传感器,找不到方法,所以我决定自己做。 如果它对任何人有帮助,我会把它留在这里。 唯一的要求是:您的设备中必须有一个加速度计传感器。 如果这样做,您可以使用以下方法模拟加速度计或陀螺仪:
SensorData
。 这将等同于android.hardware.SensorEvent
。 您将从本课程中读取传感器事件。import android.hardware.SensorEvent;
public class SensorData {
public final long timestamp;
public final int sensorType;
public final float x;
public final float y;
public final float z;
public static SensorData from(SensorEvent event) {
final float[] values = event.values;
return new SensorData(
event.timestamp,
event.sensor.getType(),
values[0],
values[1],
values[2]
);
}
public SensorData(long timestamp, int sensorType, float x, float y, float z) {
this.timestamp = timestamp;
this.sensorType = sensorType;
this.x = x;
this.y = y;
this.z = z;
}
}
SensorDataListener
。 这将等同于android.hardware.SensorEventListener
。import android.hardware.Sensor;
public interface SensorDataListener {
void onSensorChanged(SensorData data);
void onAccuracyChanged(Sensor sensor, int accuracy);
}
SensorProvider
。 这将等同于android.hardware.SensorManager
。 你必须继承这个类来实现你的模拟。import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
public abstract class SensorProvider implements SensorEventListener {
protected final Context context;
protected final SensorManager manager;
protected SensorDataListener listener;
public SensorProvider(Context context) {
this.context = context;
this.manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
}
public void register(SensorDataListener listener, int sensorType, int delay) {
this.listener = listener;
manager.registerListener(this, manager.getDefaultSensor(sensorType), delay);
}
public void unregister() {
manager.unregisterListener(this);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public abstract bool contains(int sensorType);
}
4.1. 创建你的模拟。 在此示例中,加速度计值将是原始加速度计值的平方根,陀螺仪值将是原始加速度计值的平方。
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
public class MockSensorProvider extends SensorProvider {
public MockSensorProvider(Context context) {
super(context);
}
@Override
public bool contains(int sensorType) {
return sensorType == Sensor.TYPE_ACCELEROMETER ||
sensorType == Sensor.TYPE_GYROSCOPE;
}
@Override
public void onSensorChanged(SensorEvent event) {
final SensorDataListener listener = this.listener;
if (listener == null) return;
final float[] values = event.values;
final SensorData accData = SensorData(
event.timestamp,
Sensor.TYPE_ACCELEROMETER,
Math.sqrt(values[0]),
Math.sqrt(values[1]),
Math.sqrt(values[2])
);
listener.onSensorChanged(accData);
final SensorData gyrData = SensorData(
event.timestamp + 10,
Sensor.TYPE_GYROSCOPE,
values[0] * values[0],
values[1] * values[1],
values[2] * values[2]
);
listener.onSensorChanged(gyrData);
}
}
4.2. (可选)在SensorProvider
创建一个静态方法来获取当前提供者。
public abstract class SensorProvider implements SensorEventListener {
// ...
public static SensorProvider get(Context context) {
return new MockSensorProvider(context);
}
// ...
}
SensorProvider
:public class MainActivity extends AppCompatActivity implements SensorDataListener {
private SensorProvider provider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
provider = SensorProvider.get(this);
if (provider.contains(Sensor.TYPE_ACCELEROMETER)) {
provider.register(this, Sensor.TYPE_ACCELEROMETER, 20000);
}
if (provider.contains(Sensor.TYPE_GYROSCOPE)) {
provider.register(this, Sensor.TYPE_GYROSCOPE, 20000);
}
}
@Override
public void onDestroy() {
provider.unregister();
super.onDestroy();
}
@Override
public void onSensorChanged(SensorData data) {
Log.d("%d %.2f %.2f %.2f".format(data.timestamp, data.x, data.y, data.z));
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}
以前的答案给了我一个很好的起点,但我认为我已经找到了一种更简单的方法来实现相同的结果,而无需替换 java 类并且只修改实际的SensorEvent
(默认情况下感谢 java 的可变属性)。
使用存储的originalListener
创建CustomSensorEventListener
接口并继承自SensorEventListener
interface CustomSensorEventListener : SensorEventListener {
var originalListener: SensorEventListener?
}
在onSensorChanged
回调中根据需要修改传感器值。
override fun onSensorChanged(event: SensorEvent?) {
Log.d("TAG", "onSensorChanged: original value: ${event?.values?.joinToString()}")
event?.values?.forEachIndexed { index, value -> event.values[index] = value * value }
originalListener?.onSensorChanged(event)
}
然后像这样创建SystemSensorsManager
接口和实现:
interface SystemSensorsManager {
fun getDefaultSensor(type: Int): Sensor?
fun registerListener(
systemSensorListener: SensorEventListener,
sensor: Sensor?,
sensorDelay: Int
): Boolean
fun unregisterListener(systemSensorListener: SensorEventListener, sensor: Sensor?)
}
class SystemSensorsManagerImpl(context: Context) : SystemSensorsManager {
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as? SensorManager
private val customSystemSensorEventListener: CustomSensorEventListener =
CustomSensorEventListenerImpl()
override fun getDefaultSensor(type: Int): Sensor? {
return sensorManager?.getDefaultSensor(type)
}
override fun registerListener(systemSensorListener: SensorEventListener, sensor: Sensor?, sensorDelay: Int): Boolean {
customSystemSensorEventListener.originalListener = systemSensorListener
return sensorManager?.registerListener(
customSystemSensorEventListener,
sensor,
sensorDelay
) ?: false
}
override fun unregisterListener(systemSensorListener: SensorEventListener, sensor: Sensor?) {
sensorManager?.unregisterListener(
customSystemSensorEventListener, sensor)
}
}
最后,在您感兴趣的传感器上注册侦听器并提供实际的侦听器。 例如,在上一个答案中的MainActivity
中:
class MainActivity : AppCompatActivity(), SensorEventListener {
private val systemSensorsManager: SystemSensorsManager by lazy {
SystemSensorsManagerImpl(applicationContext)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
val sensor = systemSensorsManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
systemSensorsManager.registerListener(
systemSensorListener = this,
sensor = sensor,
sensorDelay = sensor!!.minDelay
)
}
override fun onDestroy() {
systemSensorsManager.unregisterListener(
systemSensorListener = this,
sensor =
systemSensorsManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
)
super.onDestroy()
}
override fun onSensorChanged(event: SensorEvent?) {
Log.d("TAG", "onSensorChanged: modified value:
${event?.values?.joinToString()}")
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.