繁体   English   中英

如何以编程方式在android设备中设置模拟传感器(加速度计)

[英]How to set a mock sensor (accelerometer) in android device using programmatically

如何在 Android 设备上设置模拟传感器?

是否可以使用 Android API 设置模拟传感器,或者我们需要使用 NDK 和 JNI 还是使用第三方库?

谁能告诉我如何实现这个?

我需要模拟一个陀螺仪传感器,找不到方法,所以我决定自己做。 如果它对任何人有帮助,我会把它留在这里。 唯一的要求是:您的设备中必须有一个加速度计传感器 如果这样做,您可以使用以下方法模拟加速度计或陀螺仪:

  1. 创建一个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;
    }
}
  1. 创建一个SensorDataListener 这将等同于android.hardware.SensorEventListener
import android.hardware.Sensor;

public interface SensorDataListener {
    void onSensorChanged(SensorData data);

    void onAccuracyChanged(Sensor sensor, int accuracy);
}
  1. 创建一个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);
    }

    // ...
}
  1. 完成。 您可以像这样使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM