我是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);
    }
}

10-04 19:04