【问题标题】:Why is my acceleration sensor still working after closing the activity?为什么我的加速度传感器在关闭活动后仍然工作?
【发布时间】:2018-10-11 06:15:56
【问题描述】:

我正在开发一个使用加速度传感器在屏幕上移动球的应用程序。我使用 Canvas 绘制了球,每次绘图“触摸”屏幕末端时,都会显示一条消息,告诉用户对应的一侧。

如下图所示:

Toast 显示一条消息:“向左移动”,从西班牙语翻译成英语。

您看到消息显示正确。

点击手机返回键出现问题:

您的症状:

  • 图像信息会根据手机的方向再次显示。
  • 消息显然是循环的,也就是说,即使您不移动消息也是随机的。

Toast 消息的行为就好像它们仍在上一个活动中一样,也就是说,我已经离开了。有时它只在我移动手机时显示警告,有时它没有随机移动几次。

主屏幕的手动按钮是将视图引导至第一张带球照片的活动。

虽然在此视图中按下返回按钮,但即使我返回应用程序屏幕,消息也会继续显示。

消除此问题的唯一方法是从应用程序库中删除应用程序,并且过程再次相同。

我强调只有当我进入该视图并返回时才会出现问题,在此之前不会发生。

我附上主要代码:

btnManual.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent intent = new Intent(MainActivity.this, MovimientoActivity.class);
                startActivity(intent);                       
            }

曾经在 MovimientoActivity.class 中

   public class MovimientoActivity extends AppCompatActivity{

        private DrawView view;  //Class where the ball is created with the accelerometer

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            Toast.makeText(this, "Cliclo-onCreate", Toast.LENGTH_SHORT).show();


            DisplayMetrics displaymetrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);

            view = new DrawView(this, displaymetrics); //Se llama a esa vista
            view.setBackgroundColor(Color.parseColor("#F5B041"));
            setContentView(view);

            //Definimos usar toda la pantalla
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);

        }
    }
                });

Class DrawView.java

public class DrawView extends View implements SensorEventListener {

    Cliente cliente = null;

    Sensor accelerometer = null;
    SensorManager manager;

    static String TAG = "DrawView";

    int BLOQUEO_ARRIBA = 0;
    int BLOQUEO_ABAJO = 0;
    int BLOQUEO_DERECHO = 0;
    int BLOQUEO_IZQUIERDO = 0;

    private Bitmap pelota;

    public int ALTURA;

    public int ANCHO;
    DisplayMetrics displaymetrics;

    Punto posicion = new Punto();

    final int X = 0;
    final int Y = 1;
    final int Z = 2;

    public DrawView(Context context, DisplayMetrics displaymetrics) {
        super(context);

        this.displaymetrics = displaymetrics;
        manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);

        if (manager.getSensorList(Sensor.TYPE_ACCELEROMETER).size() != 0) {

            accelerometer = manager.getSensorList(
                    Sensor.TYPE_ACCELEROMETER).get(0);
                    if (!manager.registerListener(this, accelerometer,
                    SensorManager.SENSOR_DELAY_FASTEST)) {
            }
        }

        try {
            AssetManager assetManager = context.getAssets();
            InputStream inputStream;
            inputStream = assetManager.open("bola_2.png");
            pelota = BitmapFactory.decodeStream(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Obtenemos las medidas de la pantalla
        ALTURA = displaymetrics.heightPixels;
        ANCHO = displaymetrics.widthPixels;
    }
    @Override
    public void onSensorChanged(SensorEvent event) {
        // Modificamos la posicion de la bola en el eje X

        posicion.x -= event.values[X];
        //Comprobamos si se sale de la pantalla, y en ese caso, modificamos su valor
        if (posicion.x < 0) {

            if(BLOQUEO_IZQUIERDO == 0){
                Log.i(TAG, "onSensorChanged: izquierdo");
                Toast.makeText(getContext(), "Movimiento a la izquierda", Toast.LENGTH_SHORT).show();

                BLOQUEO_DERECHO = 0;
                BLOQUEO_ARRIBA = 0;
                BLOQUEO_ABAJO = 0;

                BLOQUEO_IZQUIERDO++;
            }

            posicion.x = 0;
        }else if (posicion.x > this.ANCHO -pelota.getWidth()) {

            if(BLOQUEO_DERECHO == 0){
                Log.i(TAG, "onSensorChanged: derecho");
                Toast.makeText(getContext(), "Movimiento a la derecha", Toast.LENGTH_SHORT).show();                        
                BLOQUEO_IZQUIERDO = 0;
                BLOQUEO_ARRIBA = 0;
                BLOQUEO_ABAJO = 0;

                BLOQUEO_DERECHO++;
            }

            posicion.x = this.ANCHO - pelota.getWidth();
        }
        //Modificamos la posicion de la bola en el eje Y
        posicion.y += event.values[Y];
        //Comprobamos si se sale de la pantalla, y en ese caso, modificamos su valor
        if (posicion.y < 0) {

            if(BLOQUEO_ARRIBA == 0){
                Log.i(TAG, "onSensorChanged: arriba");
                Toast.makeText(getContext(), "Movimiento hacia arriba", Toast.LENGTH_SHORT).show();

                BLOQUEO_DERECHO = 0;
                BLOQUEO_IZQUIERDO = 0;
                BLOQUEO_ABAJO = 0;

                BLOQUEO_ARRIBA++;
            }
            posicion.y = 0;

        }else if (posicion.y > this.ALTURA - pelota.getHeight()) {

            if(BLOQUEO_ABAJO == 0){
                Log.i(TAG, "onSensorChanged: abajo");
                Toast.makeText(getContext(), "Movimiento hacia abajo", Toast.LENGTH_SHORT).show();                        
                BLOQUEO_DERECHO = 0;
                BLOQUEO_ARRIBA = 0;
                BLOQUEO_IZQUIERDO = 0;

                BLOQUEO_ABAJO++;
            }

            posicion.y = this.ALTURA - pelota.getHeight();
        }
        //Método invalidate para llamar onDraw
        invalidate();


    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawBitmap(pelota, posicion.x, posicion.y, null);
    }    
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {    
    }        
}

我声明为 BLOQUEO 的变量是因为我只需要传感器通知我一次事件,所以如果它被满足我会做另一个动作,直到另一端被“触摸”。

到目前为止,这就是问题所在。最后,我的目标是防止传感器在球的屏幕被移除后继续工作,或者如果出现问题,它会在后台停止工作。

感谢您给予我的帮助。

【问题讨论】:

    标签: java android sensors


    【解决方案1】:

    您需要在退出应用程序/活动时从 SensorManager 中注销您的侦听器。 为此,您必须在活动中覆盖 onDestroy 方法。 有关所有方法,请参阅此页面 https://developer.android.com/reference/android/hardware/SensorManager

    【讨论】:

    • 如果我的 SensorManager 和 SensorManager 在 DrawView 类中而不是在我可以放置 onDestroy 或 onResume 方法的 Activity 本身中使用它,我将如何应用它?
    【解决方案2】:

    将 manager 设为公共属性,以便您可以从您的活动中访问它。

    public class DrawView extends View implements SensorEventListener {
    
    Cliente cliente = null;
    
    Sensor accelerometer = null;
    public SensorManager manager;
    ...
    }
    

    现在在 MovimientoActivity onPause() 中取消注册监听器:

    protected void onPause() {
         super.onPause();
         if(view!=null)if(view.manager!=null)view.manager.unregisterListener(view);
     }
    

    【讨论】:

      猜你喜欢
      • 2018-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-03
      • 2012-01-11
      • 1970-01-01
      相关资源
      最近更新 更多