I develop an PC remote application that able to move cursor mouse using android accelerometer sensor. I use java.io.PrintWriter to read accelerometer event value from onSensorChanged and sent to server but the app crash. Please help. 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();
}
}
}
}
Ensure that the out
variable is initiated before it is being used. Looking at your code, use
if(isConnected && out!=null) {
// Your code to use out
// out.println(.......);
}
The above if
condition will check that the variable is not null and also that the connection is already made.
In the class ConnectPhoneTask
, onPostExecuted
method is where the out
variable is initiated, ensure that the connection is made with the phone.
//This is where the variable is initiated already in your code
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true);
So the out
variable should only be used once after the connection is made.
See example below,
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));
}