java - 为什么 TYPE_ROTATION_VECTOR 传感器返回空值?
问题描述
我是 Android Studio 的新手,不明白为什么该onSensorChanged()
方法没有给出错误和警告,而是返回零。我想“在设备的屏幕上滚动球”。图形组件运行良好。我看到一个运动速度恒定的球,我想通过将它乘以屏幕角度来调整速度,因此我的速度变为 - 零。请帮我修复它。
我正在真实设备小米 MI9 SE 上测试该应用程序。
//MAIN ACTIVITY
package com.example.app_2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class Gravity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_gravity);
setContentView(new MovementView(this));
}
}
//PHYSICS
package com.example.app_2;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MovementView extends SurfaceView implements SurfaceHolder.Callback {
public float xPos;
public float yPos;
public float xVel;
public float yVel;
public float width;
public float height;
private float circleRadius;
private Paint circlePaint;
UpdateThread updateThread;
public MovementView(Context context) {
super(context);
getHolder().addCallback(this);
circleRadius = 30;
circlePaint = new Paint();
circlePaint.setColor(Color.RED);
xVel = 2 ; // скорость движения
yVel = 2 ; // шарика
}
@Override
public void onDraw(Canvas c) {
c.drawColor(Color.WHITE);
c.drawCircle(xPos, yPos, circleRadius, circlePaint);
}
public void updatePhysics() {
float xz, zy;
xz = Acceleration.Accel(1);
zy = Acceleration.Accel(-1);
xPos += xVel - xz;
yPos += yVel - zy;
if (yPos - circleRadius < 0 || yPos + circleRadius > height) {
//В случае ударов о верх или низ холста
if (yPos - circleRadius < 0) {
//Удар о верхнюю грань
yPos = circleRadius;
}else{
//Удар о нижнюю грань
yPos = height - circleRadius;
}
//Меняем направление шарика
yVel *= -1;
}
if (xPos - circleRadius < 0 || xPos + circleRadius > width) {
//В случае столкновений с правой или левой стенками
if (xPos - circleRadius < 0) {
//В случае столкновений с левой стенкой
xPos = circleRadius;
} else {
//В случае столкновений с правой стенкой
xPos = width - circleRadius;
}
//Меняем x направление на обратное
xVel *= -1;
}
}
public void surfaceCreated(SurfaceHolder holder) {
Rect surfaceFrame = holder.getSurfaceFrame();
width = surfaceFrame.width();
height = surfaceFrame.height();
xPos = width / 2;
yPos = height / 2;
updateThread = new UpdateThread(this);
updateThread.setRunning(true);
updateThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
updateThread.setRunning(false);
while (retry) {
try {
updateThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}
//THREAD
package com.example.app_2;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class UpdateThread extends Thread{
private long time;
private final int fps = 5;
private boolean toRun = false;
private MovementView movementView;
private SurfaceHolder surfaceHolder;
UpdateThread(MovementView rMovementView) {
movementView = rMovementView;
surfaceHolder = movementView.getHolder();
}
void setRunning(boolean run) {
toRun = run;
}
@Override
public void run() {
Canvas c;
while (toRun) {
long cTime = System.currentTimeMillis();
//if ((cTime - time) <= (100000 / fps)) {
c = null;
try {
c = surfaceHolder.lockCanvas(null);
movementView.updatePhysics();
movementView.onDraw(c);
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
//}
time = cTime;
}
}
}
//ACCELERATION
package com.example.app_2;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import androidx.core.content.ContextCompat;
import static android.content.Context.SENSOR_SERVICE;
import static android.hardware.Sensor.TYPE_ROTATION_VECTOR;
import static androidx.core.content.ContextCompat.getSystemService;
public class Acceleration extends Service implements SensorEventListener {
public SensorManager sensorManager;
public static float xy_angle, xz_angle, zy_angle;
public Acceleration(Context pContext) {
sensorManager = (SensorManager) pContext.getSystemService(SENSOR_SERVICE);
assert sensorManager != null;
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
assert sensorManager != null;
xy_angle = sensorEvent.values[0];
xz_angle = sensorEvent.values[1];
zy_angle = sensorEvent.values[2];
}
public static float Accel(int a){
float angle;
if (a > 0){
angle = xz_angle;
} else {
angle = zy_angle;
}
return angle;
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
我希望在数据请求时Acceleration.Accel(1)
返回TYPE_ROTATION_VECTOR
传感器的值,但我总是得到零。
解决方案
您需要做的是将您的应用程序传递Context
给您的Acceleration
类,以便您SensorManager
可以初始化。在方法SensorManager
内部进行初始化的onSensorChanged()
方式意味着它SensorManager
甚至从未被设置,因为onSensorChanged()
甚至从未被调用过。
所以在下面的修改后的Acceleration
类中,我添加了一个构造函数,然后你需要调用它,并将你的应用程序Context
作为参数传入:
public class Acceleration extends Service implements SensorEventListener {
public SensorManager sensorManager;
public static float xy_angle, xz_angle, zy_angle;
public Acceleration(Context pContext) {
sensorManager = (SensorManager) pContext.getSystemService(SENSOR_SERVICE);
assert sensorManager != null;
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
xy_angle = sensorEvent.values[0];
xz_angle = sensorEvent.values[1];
zy_angle = sensorEvent.values[2];
}
public static float accel(int a) {
float angle;
if (a > 0) {
angle = xz_angle;
} else {
angle = zy_angle;
}
return angle;
}
}
在您的Gravity
班级中,只需初始化一个Acceleration
对象:
public class Gravity extends AppCompatActivity {
Acceleration acceleration;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MovementView(this));
acceleration = new Acceleration(this);
}
}
推荐阅读
- firebase - Firestore 实时更新或 Sockets.io 用于实时聊天
- unity3d - Animator SetFloat(int 0) as Transition,现在是为了防止循环?
- java - 装饰器设计和工厂设计模式
- selenium-webdriver - 试图点击登录按钮,但它说元素不可交互
- java - Firebase Android Java - 无法获得孩子的价值
- python - 基于另一列的有序值汇总一列数据的python代码
- angular - 如何通过找到 ng-repeat 来选择下拉按钮?
- c# - 导入 TextMesh Pro 后编译器错误
- cocoapods - pod repo push 错误:多个命令产生
- c# - 如何创建一个矩形数组c#