-1

I have some code that aims to count how many times the user turns too quickly. I implemented a gyroscope and have some code working within on Resume to collect the data, along with some voice outputs. However, I am having problems making the gyroscope work properly within onResume. For one, the voice outputs do not work properly, and goes out of order. Next, I still am not getting values for the gyroscope.

package com.example.shivamgandhi.gyrosafe;

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.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class Balance_Test_Activity extends VoiceControl implements View.OnClickListener, SensorEventListener, View.OnTouchListener {

    int n = 2;
    Button btnarray[] = new Button[n];
    private SensorManager mSensorManager;
    private Sensor default_gyro;
    private TextView textView79;
    RelativeLayout RelativeLayout;
    int count1 = 0;
    float axisX, axisY, axisZ;
    double omegaMagnitude;
    EditText ed29;
    private static final float NS2S = 1.0f / 1000000000.0f;
    private final float[] deltaRotationVector = new float[4];
    int touch = 0;

    int count2 = 0;
    int time1 = 0;
    int time2 = 0;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.balance_test);

        RelativeLayout = (RelativeLayout)findViewById(R.id.RelativeLayout4);

        btnarray[0] = (Button)findViewById(R.id.button10);
        btnarray[1] = (Button)findViewById(R.id.button20);

        mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        default_gyro = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

        textView79 = (TextView)findViewById(R.id.textView79);

        ed29 = (EditText)findViewById(R.id.editText29);

        for(int i = 0; i <n; i++){
            btnarray[i].setOnClickListener(this);
        }

        RelativeLayout.setOnTouchListener(this);

    }

    //when this Activity starts
    @Override
    protected void onResume()
    {
        super.onResume();

        if (touch == 1){
            try{
                speakWords("Please place your hands on your hips and keep your feet under your shoulders. Hold your balance for the next 20 seconds");
                Thread.sleep(2000);
                while(time1 < 334){
                    mSensorManager.registerListener(this, default_gyro, SensorManager.SENSOR_DELAY_UI);
                    if(omegaMagnitude > 2){
                        count1 ++;
                        time1 ++;
                    }
                    else{
                        time1 ++;
                    }
                }
                Thread.sleep(2000);
                speakWords("Place your hands by your side. Tap to continue.");
                Thread.sleep(1000);
                touch = 10;
            }
            catch(InterruptedException e){
                e.printStackTrace();
            }
        }

        if (touch == 2){
            speakWords("Please place your hands on your hips and stand on your nondominant foot for the next 20 seconds");
            while(time2 < 334){
                mSensorManager.registerListener(this, default_gyro, SensorManager.SENSOR_DELAY_UI);
                if(omegaMagnitude > 2){
                    count2 ++;
                    time1 ++;
                }
                else{
                    time1 ++;
                }
            }
            speakWords("You may resume normal stance now");
            touch = 20;
        }


    }

    @Override
    protected void onStop()
    {
        //unregister the sensor listener
        mSensorManager.unregisterListener(this);
        super.onStop();
    }

    @Override
    public void onClick(View v){
        if(v == findViewById(R.id.button10)){
            Intent myIntent = new Intent(this, Results_Page_Activity.class);
            startActivity(myIntent);
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event){
        if(v == RelativeLayout){
           if(touch == 0){
               touch = 1;
               onResume();
               return true;
           }
            else if (touch == 10){
               touch = 2;
               onResume();
               return true;
           }
            return true;
        }
        else{
            return false;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1)
    {
        //Do nothing.
    }


    public void onSensorChanged(SensorEvent event) {
        // This timestep's delta rotation to be multiplied by the current rotation
        // after computing it from the gyro sample data.

        // Axis of the rotation sample, not normalized yet.
        float axisX = event.values[0];
        float axisY = event.values[1];
        float axisZ = event.values[2];

        // Calculate the angular speed of the sample
        double omegaMagnitude = Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);

        float[] deltaRotationMatrix = new float[9];
        SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);

        textView79.setText("Gyro X (Roll) :" + Float.toString(event.values[2]) + "\n" +
                "Gyro Y (Pitch) :" + Float.toString(event.values[1]) + "\n" +
                "Gyro Z (Yaw) :" + Float.toString(event.values[0]));
    }
}

How do I go about fixing this code so that I can actually retrieve values from the gyroscope? Thanks in advance :)

sjgandhi2312
  • 155
  • 1
  • 2
  • 10
  • This is the **3rd time you have asked this** and you are not going to get a useful answer until you stop deleting your questions and face the basic facts they expose. You **cannot** get sensor data in a lifecycle method, and you **cannot** have a long running loop in a lifecycle method either. As you were told the last time you asked this, you have to get the data in the sensor callback, and then you can mailbox it to where it is needed. If you want a long running loop, you will have to use one of the background thread mechanisms. – Chris Stratton Mar 14 '16 at 03:30
  • First, I changed my code and changed the question entirely, so I have not been asking the same question. You will not see any comment that answers my question in any of the other questions I have asked. All I asked was that a few things be clarified as to why my code is bad. You haven't posted a solution to my question or pointed out a way in which I can get to a solution either. I deleted one question that became redundant after I had significantly changed my code and learned that I was making a serious error. Please provide some form of guidance for how I can go forward instead of attacking. – sjgandhi2312 Mar 14 '16 at 15:34
  • Your changes did not change the **fundamental problem** with your approach but merely moved it around in irrelevant ways. You were told how to solve it, but you ignored that and deleted the question in which you were told. Now you've been told the same things yet again - in an answer you've accepted, though you still don't seem willing to accept what it is actually telling you about how you will have to entirely change the organization of your program to an event-driven model. – Chris Stratton Mar 14 '16 at 16:42
  • I have no idea how to do that. I've accepted the answer and asked how to implement the advice, which shows that you don't know whether or not I'm trying to implement the advice. If you even looked at the code, you'll notice that I changed from putting the gyro in a separate method into onResume. I honestly see no reason for such anger. If it's relevant, I'm a beginner programmer, and this is my first project. I hope you don't expect everybody to be an expert, especially if they're asking questions that you deem fairly obvious. – sjgandhi2312 Mar 14 '16 at 20:25
  • Trying to put it in onResume, or anything called from onResume, or anything called from *any* of the lifecyle methods is not going to work - and is precisely what you were already told is not going to work. You are merely moving things around in irrelevant ways. To solve the problem, you are going to have to take time to understand event driven programming models, and if there are parts of your task for which events and state will not work, then you will also need to learn about threads. Those are the answers to the followup question you posted in your comment below. – Chris Stratton Mar 14 '16 at 20:56
  • I'm sorry for being so aggressive. I read up about event driven programming, and I feel like it involves just making another method that activates when the user touches the screen. However, I am not sure how I would implement the gyro in that method. Last time, I learned that the gyro cannot be implemented in such a method, so I am not sure how to move forward from there. – sjgandhi2312 Mar 15 '16 at 00:47
  • Screen touching, a well as lifecycle methods are all UI events. You cannot directly get the gyro data there, you can only get it in the sensor callback method (also an event, but triggered by the sensor stack). If you need the data in a place where you cannot directly get it, you will have to do something like "mailbox" the data by storing it from where you get it and then re-reading it where you need it - but you can only read it after it is available. As you dig more into Android mechanisms you will find other ways of posting data from one setting to another, some of which can be events. – Chris Stratton Mar 15 '16 at 00:48
  • Can you suggest any resources for learning how to do this? I won't ask you to explain more of this for me, but almost none of this is familiar to me. – sjgandhi2312 Mar 15 '16 at 01:05
  • You'll need to find two sorts of resources - one on properly using android sensors (there used to be something in ApiDemos in the SDK samples, there are also now lots of contextual links in the sidebar of this page). More challenging will be learning about state machine style programming - not really sure where you start with that online, though you can try a web search. It's going to take quite a bit of learning to accomplish your goal. – Chris Stratton Mar 15 '16 at 01:12

1 Answers1

0

Ok, several issues here.

1)Never sleep in onResume, or anywhere else on the UI thread. You can't hold it up like that. At best doing so will cause you to look like you've crashed, at worst it will actually crash due to a watchdog. It will almost never do what you want.

2)You're never actually setting imegaMagnitude, because you have it redefined in onSensorChanged

3)You won't see the right value anyway, because it won't be set until onSensorChanged is called. Since that's only called on the UI thread, it won't be called until after onResume finishes (see 1). So your code can never work anyway.

4)You can't call onResume yourself. Only the framework is allowed to call lifecycle functions. Doing so yourself will seriously screw things up.

Your approach is completely unsuable. Rewrite your logic to use event based processing and a state machine pattern. This code isn't salvagable.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • How would you propose I make the new code? I initially tried to make the code by creating a new function gyrotest with the sleep, but I learned that I can't access the gyro from there. – sjgandhi2312 Mar 13 '16 at 22:26