当prinln加速度计事件值时应用程序崩溃

Posted

技术标签:

【中文标题】当prinln加速度计事件值时应用程序崩溃【英文标题】:App crash when prinln accelerometer event value 【发布时间】:2017-01-08 10:42:36 【问题描述】:

我开发了一个 PC 远程应用程序,该应用程序能够使用 android 加速度计传感器移动光标鼠标。我使用 java.io.PrintWriter 从 onSensorChanged 读取加速度计事件值并发送到服务器,但应用程序崩溃。请帮忙。 error log Code

Context context;
ToggleButton toggleButton2;
private ToggleButton toggleButton1;
Button nextButton;
Button previousButton;
TextView mousePad;
TextView returnedText;

TextView textViewX;
TextView textViewY;

private SensorManager mSensorManager;
private Sensor mAccelerometer;

private boolean isConnected=false;
private boolean mouseMoved=false;
private Socket socket;
private PrintWriter out;

private float initX =0;
private float initY =0;
private float disX =0;
private float disY =0;

private SpeechRecognizer speech = null;
private Intent recognizerIntent;
private String LOG_TAG = "VoiceRecognitionActivity";


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

    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

    context = this;
    returnedText = (TextView) findViewById(R.id.returnedText);
    toggleButton1 = (ToggleButton) findViewById(R.id.toggleButton1);
    toggleButton2 = (ToggleButton) findViewById(R.id.toggleButton2);
    nextButton = (Button)findViewById(R.id.nextButton);
    previousButton = (Button)findViewById(R.id.previousButton);

    textViewX = (TextView) findViewById(R.id.textViewX);
    textViewY = (TextView) findViewById(R.id.textViewy);


    nextButton.setOnClickListener(this);
    previousButton.setOnClickListener(this);


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


    mousePad.setOnTouchListener(new View.OnTouchListener() 
        @Override
        public boolean onTouch(View v, MotionEvent event) 
            if(isConnected && out!=null)
                switch(event.getAction())
                    case MotionEvent.ACTION_DOWN:
                        //save X and Y positions when user touches the TextView
                        initX =event.getX();
                        initY =event.getY();
                        mouseMoved=false;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        disX = event.getX()- initX; //Mouse movement in x direction
                        disY = event.getY()- initY; //Mouse movement in y direction
                        /*set init to new position so that continuous mouse movement
                        is captured*/
                        initX = event.getX();
                        initY = event.getY();
                        if(disX !=0|| disY !=0)
                            out.println(disX +","+ disY); //send mouse movement to server
                        
                        mouseMoved=true;
                        break;
                    case MotionEvent.ACTION_UP:
                        //consider a tap only if usr did not move mouse after ACTION_DOWN
                        if(!mouseMoved)
                            out.println(Constants.MOUSE_LEFT_CLICK);
                        
                
            
            return true;
        
    );



    speech = SpeechRecognizer.createSpeechRecognizer(this);
    speech.setRecognitionListener(this);
    recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE,
            "en");
    recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
            this.getPackageName());
    recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
            RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
    recognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);

    toggleButton1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
            if (isChecked) 
                speech.startListening(recognizerIntent);
             else 
                speech.stopListening();
            
        
    );
    mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);




@Override
public boolean onCreateOptionsMenu(Menu menu) 
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;


@Override
public boolean onOptionsItemSelected(MenuItem item) 

    int id = item.getItemId();
    if(id == R.id.action_settings) 
        Intent i = new Intent(getApplicationContext(), SetIP.class);
        startActivity(i);
        finish();
    

    //noinspection SimplifiableIfStatement
    if(id == R.id.action_connect) 

        Intent intent =  getIntent();
        String ipadd = intent.getStringExtra("ipaddress");
        ConnectPhoneTask connectPhoneTask = new ConnectPhoneTask();
        connectPhoneTask.execute(ipadd);
        return true;
    

    return super.onOptionsItemSelected(item);



@Override
public void onClick(View v) 
    switch (v.getId()) 
        case R.id.playPauseButton:
            
                out.println(Constants.MOUSE_RIGHT_CLICK);
            
            break;
        case R.id.nextButton:
            if (isConnected && out!=null) 
                out.println(Constants.NEXT);
            
            break;
        case R.id.previousButton:
            if (isConnected && out!=null) 
                out.println(Constants.PREVIOUS);
            
            break;
    



@Override
public void onDestroy()

    super.onDestroy();
    if(isConnected && out!=null) 
        try 
            out.println("exit");
            socket.close();
         catch (IOException e) 
            Log.e("remotedroid", "Error in closing socket", e);
        
    


@Override
public void onResume() 
    super.onResume();
    mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);


@Override
protected void onPause() 
    super.onPause();
    if (speech != null) 
        speech.destroy();
        Log.i(LOG_TAG, "destroy");
    
    mSensorManager.unregisterListener(this);


public void onStop() 
    super.onStop();
    mSensorManager.unregisterListener(this);


public void onAccuracyChanged(Sensor sensor, int accuracy) 
    // can be safely ignored for this demo


public void onSensorChanged(SensorEvent event) 

    float x = event.values[0];
    float y = event.values[1];


    textViewX.setText(Float.toString(x));
    textViewY.setText(Float.toString(y));

    Log.i(LOG_TAG, x+","+y);

    if ((x = null) && (y = null))
     try
    out.println(String.valueOf(x)+","+String.valueOf(y));

catch (IOException e) 
Log.e("remotedroid", "huhuhu", e);

@Override
public void onBeginningOfSpeech() 
    Log.i(LOG_TAG, "onBeginningOfSpeech");


@Override
public void onBufferReceived(byte[] buffer) 
    Log.i(LOG_TAG, "onBufferReceived: " + buffer);


@Override
public void onEndOfSpeech() 
    Log.i(LOG_TAG, "onEndOfSpeech");
    toggleButton1.setChecked(false);


@Override
public void onError(int errorCode) 
    String errorMessage = getErrorText(errorCode);
    Log.d(LOG_TAG, "FAILED " + errorMessage);
    toggleButton1.setChecked(false);


@Override
public void onEvent(int arg0, Bundle arg1) 
    Log.i(LOG_TAG, "onEvent");


@Override
public void onPartialResults(Bundle arg0) 
    Log.i(LOG_TAG, "onPartialResults");


@Override
public void onReadyForSpeech(Bundle arg0) 
    Log.i(LOG_TAG, "onReadyForSpeech");


@Override
public void onResults(Bundle results) 
    Log.i(LOG_TAG, "onResults");
    ArrayList<String> matches = results
            .getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
    String text = "";
    for (String result : matches) 
        text = result;
    

    out.println(text);
    returnedText.setText(text);



@Override
public void onRmsChanged(float rmsdB) 
    Log.i(LOG_TAG, "onRmsChanged: " + rmsdB);



public static String getErrorText(int errorCode) 
    String message;
    switch (errorCode) 
        case SpeechRecognizer.ERROR_AUDIO:
            message = "Audio recording error";
            break;
        case SpeechRecognizer.ERROR_CLIENT:
            message = "Client side error";
            break;
        case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
            message = "Insufficient permissions";
            break;
        case SpeechRecognizer.ERROR_NETWORK:
            message = "Network error";
            break;
        case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
            message = "Network timeout";
            break;
        case SpeechRecognizer.ERROR_NO_MATCH:
            message = "No match";
            break;
        case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
            message = "RecognitionService busy";
            break;
        case SpeechRecognizer.ERROR_SERVER:
            message = "error from server";
            break;
        case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
            message = "No speech input";
            break;
        default:
            message = "Didn't understand, please try again.";
            break;
    
    return message;


public class ConnectPhoneTask extends AsyncTask<String,Void,Boolean> 

    @Override
    protected Boolean doInBackground(String... params) 
        boolean result = true;
        try 
            InetAddress serverAddr = InetAddress.getByName(params[0]);
            socket = new Socket(serverAddr, Constants.SERVER_PORT);//Open socket on server IP and port
         catch (IOException e) 
            Log.e("remotedroid", "Error while connecting", e);
            result = false;
        
        return result;
    

    @Override
    protected void onPostExecute(Boolean result)
    
        isConnected = result;
        Toast.makeText(context,isConnected?"Connected to server!":"Error while connecting",Toast.LENGTH_LONG).show();
        try 
            if(isConnected) 
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                        .getOutputStream())), true);

            
        catch (IOException e)
            Log.e("remotedroid", "Error while creating OutWriter", e);
            Toast.makeText(context,"Error while connecting",Toast.LENGTH_LONG).show();
        
    

【问题讨论】:

你的代码中out在哪里初始化? 请附上问题代码。 我只声明了私有的PrintWriter; (我是新手对不起) 这就是问题所在,您必须在使用之前启动out 变量。查看错误日志,它清楚地指出NullPointerExceptionout 变量上 @codePG 你能举个例子如何启动变量。 【参考方案1】:

确保在使用out 变量之前启动它。查看您的代码,使用

if(isConnected && out!=null) 
    // Your code to use out
    // out.println(.......);

上面的if 条件将检查变量是否为空并且连接是否已经建立。

ConnectPhoneTask类中,onPostExecuted方法是启动out变量的地方,确保与手机建立连接。

//This is where the variable is initiated already in your code
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                        .getOutputStream())), true);

所以out 变量只能在建立连接后使用一次。

请看下面的例子,

public void onSensorChanged(SensorEvent event) 
    float x = event.values[0];
    float y = event.values[1];

    textViewX.setText(Float.toString(x));
    textViewY.setText(Float.toString(y));

    Log.i(LOG_TAG, x+","+y);

    if(isConnected && out!=null)
        out.println(String.valueOf(x) + "," + String.valueOf(y));

【讨论】:

非常感谢@codePG。我的代码现在正在运行。

以上是关于当prinln加速度计事件值时应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

在屏幕上捕捉加速事件

隔离崩溃倾向 (SEGV),但将关键遗留代码加速到单独的二进制文件中

Cocos2d-x加速度计实例:运动的小球

Unity VM 崩溃(看起来像加速问题)

WordPress使用LiteSpeed缓存加速

Android 加速度计传感器值