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

时间:2014-03-24 12:58:32

标签: android accelerometer android-sensors

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

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

有人可以告诉我如何实现这个吗?

1 个答案:

答案 0 :(得分:0)

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

  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) {}
}