我是Android Studio的新手,不理解为什么onSensorChanged()
方法不给出错误和警告,但返回零。我想“将球滚动到设备的屏幕上”。图形组件效果很好。我看到一个球以恒定的速度运动,我想通过将其乘以屏幕的角度来调整速度,因此我的速度变为-零。
请帮我修复它。
我正在真实设备Xiaomi 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);
}
}