문제

im writing a simple IMU using Android phone (sending data via TCP to computer and visualising it on a PC). The thing is that code compiles and works perfectly on API 18 and 19 (checked on different phones), problem is that it doesn't want to work on API 16 (phone and emulator). I've managed to notice that problem is in method that initializes the sensors. I'm posting a code and an logcat error below. I've cut writing to SD and sending via TCP, because it does work on API 16 flawlessly (when initSensors(); is commented out). Hope you can help me. Robert

Main class:

public class Sensor412 extends Activity {

    public SensorManager mSensorManager;
    public mySensors mSensors;

    // Initializing Sensors
    void initSensors() {
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

        List<Sensor> accel_sensor_list = mSensorManager
                    .getSensorList(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener((SensorEventListener) mSensors,
            accel_sensor_list.get(0), SensorManager.SENSOR_DELAY_UI);

        List<Sensor> magn_sensor_list = mSensorManager
                .getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
        mSensorManager.registerListener((SensorEventListener) mSensors,
                magn_sensor_list.get(0), SensorManager.SENSOR_DELAY_UI);

        List<Sensor> gyro_sensor_list = mSensorManager
                .getSensorList(Sensor.TYPE_GYROSCOPE);
        mSensorManager.registerListener((SensorEventListener) mSensors,
                gyro_sensor_list.get(0), SensorManager.SENSOR_DELAY_UI);
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            //Creating sensor class
            mSensors = new mySensors();

        }//onCreate

        @Override
        protected void onPause() {
            super.onPause();
            // Wyłącz odczyt gdy aplikacja wchodzi w stan Pause
            mSensorManager.unregisterListener(mSensors);
        }//onPause  

        @Override
        protected void onResume() {
            super.onResume();
            // Włącz odczyt gdy aplikacja zostanie wznowiona (stan Resume)
            initSensors();
        }//onResume    
    }

mySensors class:

package com.example.sensor412;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

public class mySensors implements SensorEventListener {

    private static int VECTOR_SIZE = 3;
    private static int MATRIX_SIZE = 16;

    private int type;
    public static float z_deg, y_deg, x_deg, accels_x, accels_y, accels_z,
            magn_x, magn_y, magn_z, gyro_x, gyro_y, gyro_z;
    private boolean isReady;

    float[] vals = new float[VECTOR_SIZE];
    float[] accels = new float[VECTOR_SIZE];
    float[] magn = new float[VECTOR_SIZE];
    float[] gyro = new float[VECTOR_SIZE];
    float[] orientation_rad = new float[VECTOR_SIZE];

    float[] R_orig = new float[MATRIX_SIZE];
    float[] I_orig = new float[VECTOR_SIZE];
    float[] R_remapped = new float[MATRIX_SIZE];

    public void onSensorChanged(SensorEvent event) {
        type = event.sensor.getType();
        vals = event.values.clone();

        switch (type) {
        case Sensor.TYPE_ACCELEROMETER:
            accels = vals.clone();
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            magn = vals.clone();
            break;
        case Sensor.TYPE_GYROSCOPE:
            gyro = vals.clone();
            isReady = true;
        }

        if (isReady && magn != null && accels != null && gyro != null) {
            isReady = false;

            SensorManager.getRotationMatrix(R_orig, I_orig, accels, magn);
            SensorManager.getOrientation(R_orig, orientation_rad);
            //rad->deg
            z_deg = orientation_rad[0] * 57.2957795f;
            y_deg = orientation_rad[1] * 57.2957795f;
            x_deg = orientation_rad[2] * 57.2957795f;

            accels_x = accels[0];
            accels_y = accels[1];
            accels_z = accels[2];

            magn_x = magn[0];
            magn_y = magn[1];
            magn_z = magn[2];

            gyro_x = gyro[0];
            gyro_y = gyro[1];
            gyro_z = gyro[2];

        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }
}

Logcat error:

01-06 00:10:16.296: E/AndroidRuntime(660): java.lang.RuntimeException: Unable to resume activity {com.example.sensor412/com.example.sensor412.Sensor412}: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2575)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.ActivityThread.access$600(ActivityThread.java:130)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.os.Handler.dispatchMessage(Handler.java:99)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.os.Looper.loop(Looper.java:137)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.ActivityThread.main(ActivityThread.java:4745)
01-06 00:10:16.296: E/AndroidRuntime(660):  at java.lang.reflect.Method.invokeNative(Native Method)
01-06 00:10:16.296: E/AndroidRuntime(660):  at java.lang.reflect.Method.invoke(Method.java:511)
01-06 00:10:16.296: E/AndroidRuntime(660):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-06 00:10:16.296: E/AndroidRuntime(660):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-06 00:10:16.296: E/AndroidRuntime(660):  at dalvik.system.NativeStart.main(Native Method)
01-06 00:10:16.296: E/AndroidRuntime(660): Caused by: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
01-06 00:10:16.296: E/AndroidRuntime(660):  at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
01-06 00:10:16.296: E/AndroidRuntime(660):  at java.util.ArrayList.get(ArrayList.java:304)
01-06 00:10:16.296: E/AndroidRuntime(660):  at java.util.Collections$UnmodifiableList.get(Collections.java:1050)
01-06 00:10:16.296: E/AndroidRuntime(660):  at com.example.sensor412.Sensor412.initSensors(Sensor412.java:125)
01-06 00:10:16.296: E/AndroidRuntime(660):  at com.example.sensor412.Sensor412.onResume(Sensor412.java:266)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1184)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.Activity.performResume(Activity.java:5082)
01-06 00:10:16.296: E/AndroidRuntime(660):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2565)
01-06 00:10:16.296: E/AndroidRuntime(660):  ... 12 more

Again I'd like to add that on Android 4.3 and 4.4 it does work perfectly - as a proof I'm adding a screenshot from my Nexus 4 running android 4.4. ( https://dl.dropboxusercontent.com/u/60262901/sensorapp.png )

EDIT: Thanks for the answers, as the phone I was testing app with and emu don't have a gyroscope it caused problems, the real phones with API 18 and 19 had these sensors and with that it worked flawlessly. Thanks for the answers!

도움이 되었습니까?

해결책

It appears as though the list of Gyro sensors is empty, hence the IndexOutOfBoundsException. Can you confirm that the emulator and device on API 16 both have gyros? As a safeguard, you should check that the array isn't empty before trying to get any elements from it.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top