Почему датчик TYPE_ROTATION_VECTOR возвращает нулевое значение? - PullRequest
2 голосов
/ 18 октября 2019

Я новичок в 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во время запроса данных, но я всегда получаю ноль.

1 Ответ

0 голосов
/ 18 октября 2019

Что вам нужно сделать, это передать 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...