如何在新线程中读取陀螺仪数据?

时间:2013-06-20 09:17:20

标签: android gyroscope jxl

我正在开发一个读取GYRO数据的APP,然后将X,Y,Z值保存在存储在SD卡中的excel文件中。 我正在使用JXL来实现excel写入,因为excel写入是资源占用我为它开始新的线程。 我的代码编译好了,但在手机上运行时出现错误,如下所示:

 06-20 17:15:45.328: W/dalvikvm(19897): threadid=13: thread exiting with uncaught             exception (group=0x41c30450)
 06-20 17:15:45.328: E/AndroidRuntime(19897): FATAL EXCEPTION: Thread-58127
 06-20 17:15:45.328: E/AndroidRuntime(19897): java.lang.NullPointerException
 06-20 17:15:45.328: E/AndroidRuntime(19897):   at hunk.hong.sonymobile.gyrotest.MainActivity$2.run(MainActivity.java:169)
 06-20 17:15:45.328: E/AndroidRuntime(19897):   at java.lang.Thread.run(Thread.java:856)

以下是我的源代码:

 public class MainActivity extends Activity implements SensorEventListener {

        private TextView TV;
        private TextView TV1;
        private Button button1;
        private SensorManager mSensorManager;
        private Sensor mSensor;
        private EditText mEditText;
        private SensorEvent mSensorEvent;
        private Thread mThread;
        private SensorEvent event;

        DatabaseHandler db = new DatabaseHandler(this);


        Timer timer = new Timer();
        Handler handler = new Handler(){
            public void handleMessage(Message msg){
                switch (msg.what){
                case 1:

                    //do someting
                    //setTitle("hear me?");
                    break;
                }
                super.handleMessage(msg);
            }
        };


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);


            button1 = (Button)findViewById(R.id.button1);
            mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
            TV = (TextView)findViewById(R.id.action_settings);
            TV1 = (TextView)findViewById(R.id.textView1);
            mEditText = (EditText)findViewById(R.id.editText1);

            if (mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) == null){
                //sorry, there is no GYRO in your device
                TV.setText("sorry, there is no GYRO in your device!!!");
            }
            else{
                mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
                TV.setText("vendor:"+mSensor.getName()+"\n"+"version:"+mSensor.getVersion()+"\n"+"MAX Range:"+mSensor.getMaximumRange()
                        +"\n"+"Resulation:"+mSensor.getResolution());
            }

            button1.setOnClickListener(new OnClickListener(){
                @Override
                public void onClick(View v){
                    if(mThread == null){
                        mThread = new Thread(runnable);
                        mThread.start();//thread start
                    }
                    else{
                        //Toast.makeText(this, "thread is already running", Toast.LENGTH_LONG).show();
                    }
                }
            });


        }

        Runnable runnable = new Runnable(){
            @Override
            public void run(){

            String Fnamexls = "GyroTest"+".xls";
            File sdCard = Environment.getExternalStorageDirectory();
            File directory = new File (sdCard.getAbsolutePath()+"/GyroTest");
            directory.mkdir();
            File file = new File(directory,Fnamexls);
            WritableWorkbook workbook;
            try{
                int i=1;
                workbook = Workbook.createWorkbook(file);
                WritableSheet sheet = workbook.createSheet("First Sheet", 0);
                Label labelTitle1 = new Label(0,0,"X-rotation(R/S)");
                Label labelTitle2 = new Label(1,0,"Y-rotation(R/S)");
                Label labelTitle3 = new Label(2,0,"Z-rotation(R/S)");
                try{//write title
                    sheet.addCell(labelTitle1);
                    sheet.addCell(labelTitle2);
                    sheet.addCell(labelTitle3);
                }catch(RowsExceededException e){
                    e.printStackTrace();
                }catch (WriteException e){
                    e.printStackTrace();
                }
                for (i=1;i<=100;i++){//write 100 data in excel
                    Label labeli0 = new Label(0,i,Float.toString(event.values[0]));
                    Label labeli1 = new Label(1,i,Float.toString(event.values[1]));
                    Label labeli2 = new Label(2,i,Float.toString(event.values[2]));
                    try{
                        sheet.addCell(labeli0);
                        sheet.addCell(labeli1);
                        sheet.addCell(labeli2);
                    }catch (RowsExceededException e){
                        e.printStackTrace();
                        }catch (WriteException e){
                            e.printStackTrace();
                        }
                }

                workbook.write();
                try{
                    workbook.close();
                }catch(WriteException e){
                    e.printStackTrace();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
            }
        };

        protected void onResume()  
        {  
            super.onResume();  
            /*register the sensor listener to listen to the gyroscope sensor, use the 
            call backs defined in this class, and gather the sensor information as quick 
            as possible*/  
            mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),SensorManager.SENSOR_DELAY_UI);  //get sensor readout suitable for user interface
        }  
        //When this Activity isn't visible anymore  
        @Override  
        protected void onStop()  
        {  
            //unregister the sensor listener when application is not visible
            mSensorManager.unregisterListener(this);  
            super.onStop();  
        } 

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

        @Override  
        public void onSensorChanged(SensorEvent event)  
        {  
            //if sensor is unreliable, return void  
            if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)  
            {  
                return;  
            }  

            //else it will output the rotation values  
            TV1.setText("Rotation X  :"+ Float.toString(event.values[0]) +"\n"+  
                       "Rotation Y  :"+ Float.toString(event.values[1]) +"\n"+  
                       "Rotation Z  :"+ Float.toString(event.values[2])); 

        }  
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }

    }

对于错误消息,问题应该在下面一行:

Label labeli0 = new Label(0,i,Float.toString(event.values[0])); 
Label labeli1 = new Label(1,i,Float.toString(event.values[1])); 
Label labeli2 = new Label(2,i,Float.toString(event.values[2]));

任何人都可以帮我找到这个bug吗? 以及如何解决这个问题? 如何在新线程中读取陀螺仪数据?

提前谢谢你!

1 个答案:

答案 0 :(得分:2)

发生 NullPointerException ,因为您没有保存从传感器检索的值。在OnSensorChanged()方法中,您只需设置文本,而不是将值复制到全局事件。因此,当您在run()方法中访问SensorEvent实例时,会发生异常。

private volatile float[] mValues;

@Override  
public void onSensorChanged(SensorEvent event)  
{  
    //if sensor is unreliable, return void  
    if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)  
    {  
        return;  
    }  

    mValues = event.values.clone();

    //else it will output the rotation values  
    TV1.setText("Rotation X  :"+ Float.toString(event.values[0]) +"\n"+  
               "Rotation Y  :"+ Float.toString(event.values[1]) +"\n"+  
               "Rotation Z  :"+ Float.toString(event.values[2])); 

}

然后更改以下部分

Label labeli0 = new Label(0,i,Float.toString(mValues[0]));
Label labeli1 = new Label(1,i,Float.toString(mValues[1]));
Label labeli2 = new Label(2,i,Float.toString(mValues[2]));

因为您同时执行此操作,所以最好实现缓冲区并将缓冲区写入excel文件。 的注意 代码将工作,因为您没有在共享对象上提供任何并发度测量,在本例中为mValues。即使声明它volatile,onSensorChanged方法也会收到非常快的值,如果你不将它们保存在某个临时的地方并按顺序将它们写入excel文件,线程将丢弃大部分值。