Cart's tablet Android Java code

Note. Tested on Android version 4.4.2. Subsequent versions may not be entirely compatible.





---- MainActivity.java file -------

// WiFi_Arduino_01P.java
//
// *********************** Kartie control software (client side) ************************
//
// This is WiFi control software for a soap box kartie-type RC vehicle (by IEC, May, 2014).
// This is the remote controlling client component, not the on-board server component.
// Programs an Asus Nexus 7 tablet computer running the Android 4.4.2 operating system.
// This version provides a proportional control effect by sliding a finger on the 
// touch-sensitive screen of the tablet, thereby simulating the action of a joystick.
// A steering self-centering effect is obtained by lifting the finger off the screen which 
// equalises the speeds of the driving wheels on the front end steering bogie.
//
// **** Works with Arduino server software Kartibot_PA07 and Kartibot_PA07_SC (& later) ****
//      (Corresponding VB client is KartwinP1)
//
// WARNING.  This client will give a timeout connection error message if its router is subject
// to WiFi interference e.g. by another router operating on the same channel.

package com.example.WiFi_Arduino_01P;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import android.text.Html;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends Activity {
	private TextView textView1;
	private TextView textView1B; 
	private TextView heading;   
	private TextView note1;;
	private TextView received;
	private Handler mHandler;
	public int i=0, k=-1, threadStop=1, runInd=-1, started=0; 
	public Socket clientSocket = new Socket();
	public String IPAddr = "", ind = "",  reflected="";
	public char gridCommand = 0;
	public char keepAlive = 38; // 38 = '&'. Note, also set as a string in theGuts()
	public int port = 0, timeout = 5000;
	public int button1 = 0; 
	public Button connect, disconnect, exit, buttonIP;
	public String fileContents;
	public EditText editIP;
	public TextView box;
	public Button btnBox;
	public OnClickListener listenBox;
	public RelativeLayout myLayout;
	public ImageView joy;
	public int joyAreaTop;
	public int joyAreaLeft;
	public int joyAreaWidth;
	public int joyAreaHeight;
	public long joyCount = 0;
	public int jy = 0;
	public int bk = 25;  // Speed cut-off value for braking
	public int ms = 30; // Minimum motor speed when not stopped
	public boolean brake = true;  
	public float fspeedLeft;
	public float fspeedRight;
	public float newfspeedLeft;
	public float newfspeedRight;
	public float spinSpeed = 85f;  
	public String commandString = "";
	public String commandStrOld = ""; 
	public String termin = "^";
	public String outmsg;
	public Button drive;
	public boolean buttonStartToggle = false;
	public int testCount = 0;
	public boolean buttonTestToggle = false;
	public Button speed;
	public boolean buttonSpeedToggle = false;
	public Button spinL;
	public boolean btnSpinLeftToggle = false;
	public boolean disableSpinLeft = false;
	public Button spinR;
	public boolean btnSpinRightToggle = false;
	public boolean disableSpinRight = false;
	public Button test;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) { 
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		 
		readFile(null);  // Recover remembered IP address
		// If file gets lost do the following.
		// 1. Comment out readFile above.
		// 2. Go to btnIPset() and un-comment the dummy address.
		// 3. Install and run, touch Confirm IP then touch Disconnect/Exit.
		// 4. Comment the dummy address and install/run again.
		// 5. Dummy should now appear and be edited on the tablet to real address.
		// *** Note.  Cannot get an address to appear by editing the xml file.
 		editIP = (EditText) findViewById(R.id.IPedit);
 		editIP.setText(fileContents);
		
		textView1 = (TextView)findViewById(R.id.textView1);
    	textView1B = (TextView)findViewById(R.id.textView1B);
		heading = (TextView)findViewById(R.id.textTitle);
		joy = (ImageView)findViewById(R.id.imageView1);
		
		speed = (Button) findViewById(R.id.buttonSpeedX2);
		spinL = (Button) findViewById(R.id.buttonSpinLeft);
		spinR = (Button) findViewById(R.id.buttonSpinRight);
		test =  (Button) findViewById(R.id.buttonTest);
		
		RelativeLayout myLayout = 
                (RelativeLayout)findViewById(R.id.joyContainer);; 
        
            myLayout.setOnTouchListener(
            		
        		new RelativeLayout.OnTouchListener() {
        			@Override
					public boolean onTouch(View v, MotionEvent m) {
        				handleTouch(m);     				
        			    return true; 
        			}
        		}
        );
            
            received = (TextView) findViewById(R.id.textConnect);
            note1 = (TextView) findViewById(R.id.notes_01);
            connect = (Button) findViewById(R.id.buttonConnect);
            disconnect = (Button) findViewById(R.id.buttonDisconnect);
            
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy); // Seems necessary ? 
            
            test.setEnabled(true);
            
	}  //  End of 'onCreate'
	
	
	public void showMessages(String message) {
		
		TextView conMsgs = (TextView)  findViewById(R.id.textViewMsgs);
        conMsgs.setVisibility(View.VISIBLE);
        Button endMsgs = (Button)  findViewById(R.id.endMessages);
        endMsgs.setVisibility(View.VISIBLE);
        String fullMsg = "«b»CONNECTION MESSAGE«/b»«br»" + message;
		conMsgs.setText(Html.fromHtml(fullMsg));
	}
	
	public void closeMessages(View view) {
		
		TextView conMsgs = (TextView)  findViewById(R.id.textViewMsgs);
        conMsgs.setVisibility(View.GONE);
        Button endMsgs = (Button)  findViewById(R.id.endMessages);
        endMsgs.setVisibility(View.GONE);
        finish();  //  Exit from the app.
	}

	void handleTouch(MotionEvent m)
	{
	    	
	    	//int pointerCount = m.getPointerCount();
	    	//for (int i = 0; i « pointerCount; i++)
	    	int i = 0; //  Multiple touches are a nuisance in this application	
	    	{
	    		int x = (int) m.getX(i);
	    		int y = (int) m.getY(i);    		
	    		int id = m.getPointerId(i);
	    		int action = m.getActionMasked();
	    		int actionIndex = m.getActionIndex(); 
	    		String actionString;
	    		
	    		switch (action)
	    		{
	    			case MotionEvent.ACTION_DOWN:
	    				actionString = "DOWN";
	    				heading.setTextColor(Color.YELLOW);
	    				Resources res = getResources(); // need this to fetch the drawable
	    				Drawable draw = res.getDrawable( R.drawable.kartmap04 );
	    				joy.setScaleType(ScaleType.FIT_XY);
	    				joy.setImageDrawable(draw); 
	    				break;
	    			case MotionEvent.ACTION_UP:
	    				actionString = "UP";
	    				break;	
	    			case MotionEvent.ACTION_POINTER_DOWN:
	    				actionString = "PNTR DOWN";
	    				break;
	    			case MotionEvent.ACTION_POINTER_UP:
	        			actionString = "PNTR UP";
	        			break;
	    			case MotionEvent.ACTION_MOVE:
	    				actionString = "MOVE";
	    				break;
	    			default:
	    				actionString = "";
	    		}
	    		
	    		// There are many examples on the Web and the above part of 'handleTouch()' is copied from:
	    		// http://www.techotopia.com/index.php/Android_Touch_and_Multi-touch_Event_Handling
	    		// The remaining code below is new here (i.e. original by IEC).
	    		
	    	    joyCount++;
	    	    
	    		if(joyCount == 1) {
	    		// Cannot get width and height to work in main routine so done here instead	
	    		//ImageView joyArea = (ImageView) findViewById(R.id.imageView1); 
	            RelativeLayout joyArea = (RelativeLayout) findViewById(R.id.joyContainer);
	    		joyAreaTop = joyArea.getTop();
	    		joyAreaLeft = joyArea.getLeft();
	    		joyAreaWidth = joyArea.getWidth();
	    		joyAreaHeight = joyArea.getHeight();
	    		}
	    		
	    		// Limit all touches outside joy stick area
	    		if(x « 0) {x = 0;}
	    		if(x » joyAreaWidth) {x = joyAreaWidth;}
	    		if(y « 0) {y = 0;}
	    		if(y » joyAreaHeight) {y = joyAreaHeight;}
	    		
	    		
	    		// Scale the coordinates
	    		float fx = ((float)x / joyAreaWidth) * 255f;
	    		float fy = ((float)y / joyAreaHeight) * 255f;  // y axis will control speeds
	    		
	    		// Convert to  integers
	    		int ix = (int)fx;
	    		int iy = (int)fy;
	    		
	    		// Rescale the y values from -255 to +255 in order to generate
	    		// unmodulated motor speeds (not yet allocated to left and right).
	    		// Note:  negative values mean reverse motor speeds.
	    		jy = 255 - 2 * iy;
	    		
	    		// Rescale the x values from 0 to 512
	    		// To prepare for steering formulation
	    		int xLeft = 2 * ix ;
	    		int xRight = 512 - xLeft;  // i.e. complement of left
	    		
	    		// Truncate any marginal left and right values which are above 255
	    		if(xLeft » 255) {xLeft = 255;}
	    		if(xRight » 255) {xRight = 255;}
	    		
	    		// Create the steering factors which will modulate the motor speeds
	    		float factorLeft = (float)xLeft / 255;
	    		float factorRight = (float)xRight / 255;
	    		
	    		// Set motor speeds provided that both spin buttons are inactive 
	    		if (btnSpinLeftToggle == false && btnSpinRightToggle == false) {
	    			// Calculate the left and right motor speed control values by taking
	    			// the unmodulated motor speed and multiplying by the respective steering factors.
	    			// Note:  negative values mean reverse motor speeds.
	    			// Note:  these values are immediately available to the transceiver thread
	    			fspeedLeft = (float)jy * factorLeft;
	    			fspeedRight = (float)jy * factorRight;
	    			//  Call to casterAct() was here
	    			//  If kartie is in reverse swop motor speeds to maintain intuitive steering direction
	    			if (fspeedLeft « 0 && fspeedRight « 0) {
	    				fspeedLeft = (float)jy * factorRight;
		    			fspeedRight = (float)jy * factorLeft;	    				
	    			}
	    			if (actionString == "UP") {casterAct();}  //  Simulate self-centering caster effect
	    		}
	    		
	    		test.setEnabled(false);
	    		
	    	}
	    	
	}
	
void casterAct() {
	// A simulated sort of caster effect is achieved by lifting the finger and ...
	// making both motorspeeds equal to that which is greatest.
	// This is definitely a control improvement.
	// Note:  abs() method necessary to enable caster action during reverse mode.
	if (Math.abs(fspeedLeft) » Math.abs(fspeedRight)) {
		fspeedRight = fspeedLeft;
		}
	else { 
		fspeedLeft = fspeedRight;		
		}
	}
	
	public void buttonStart(View view) {
		
		drive = (Button) findViewById(R.id.buttonStart);
		
		if (buttonStartToggle == false) {
			drive.setText("STOP\ndriving");
			buttonStartToggle = true;
		}
		else {
			drive.setText("Start\ndriving");
			buttonStartToggle = false;
		}
		
	}
	
	public void buttonSpeed(View view) {
		
		//speed = (Button) findViewById(R.id.buttonSpeedX2);
		
		if (buttonSpeedToggle == false) {
			speed.setText(" " + (char)189 + " Speed ");
			//speed.setText("Normal\nspeed");
			buttonSpeedToggle = true;	
		}
		else {
			speed.setText("Speed x 2");
			buttonSpeedToggle = false;
		}	
		
	}
	
	public void btnTest(View view) {
		
		buttonTestToggle = true;
	}
	
	public void btnSpinLeft(View view) { 
		
		if (disableSpinLeft == true) {return;}
		
		if (btnSpinLeftToggle == false) {
			disableSpinRight = true;
			LayoutParams lp = spinL.getLayoutParams();
			lp.width = dp2px(350);
			lp.height = dp2px(100);
			spinL.setLayoutParams(lp);
			spinL.setText("Stop\nspin");
			btnSpinLeftToggle = true;
			//btnSpinRightToggle = true;  // Disable the opposite spin operation
			fspeedLeft = -spinSpeed; 
			fspeedRight = spinSpeed;
			spinR.setText("Spin\nright");			
		}
		else {
			disableSpinRight = false;
			LayoutParams lp = spinL.getLayoutParams();
			lp.width = dp2px(100);
			lp.height = dp2px(100);
			spinL.setLayoutParams(lp);
			spinL.setText("Spin\nleft");
			btnSpinLeftToggle = false;
			fspeedLeft = 0;
			fspeedRight = 0;
			speed.setText("Speed x 2");
			buttonSpeedToggle = false; 
		}	
		
	}
	
	public void btnSpinRight(View view) {
		
		if (disableSpinRight == true) {return;}
		
		if (btnSpinRightToggle == false) {
			disableSpinLeft = true;
			LayoutParams lp = spinR.getLayoutParams();
			lp.width = dp2px(350);
			lp.height = dp2px(100);
			spinR.setLayoutParams(lp);
			spinR.setText("Stop\nspin");
			spinR.setText("Stop\nspin");
			btnSpinRightToggle = true;
			//btnSpinLeftToggle = false;  // Disable the opposite spin operation
			fspeedLeft = spinSpeed; 
			fspeedRight = -spinSpeed;
			spinL.setText("Spin\nleft");
		}
		else {
			disableSpinLeft = false;
			LayoutParams lp = spinR.getLayoutParams();
			lp.width = dp2px(100);
			lp.height = dp2px(100);
			spinR.setLayoutParams(lp);
			spinR.setText("Spin\nright");
			btnSpinRightToggle = false;
			fspeedLeft = 0;
			fspeedRight = 0;
			speed.setText("Speed x 2");
			buttonSpeedToggle = false;
		}	
	}
	
	public void btnStopMotors(View v) {
		
		Button stoppem = (Button) findViewById(R.id.stopNotice);
		stoppem.setText("Dunnut");
		fspeedLeft = 0;
		fspeedRight = 0;
		finish();
	}
	
	
	public int px2dp(int pixels) {
		
		int dp = (int)(pixels/getResources().getDisplayMetrics().density);
		return dp;
	}
	
public int dp2px(int pixels) {
		
		int px = (int)(pixels*getResources().getDisplayMetrics().density);
		return px;
	}
	
	
	// ******************* Routines imported from WiFi_Android_01 ************** 
	
	public void btnIPset(View view) {
		
		editIP = (EditText) findViewById(R.id.IPedit);
		//editIP.setText("192.168.99.99");  // used to remake a lost file
		IPAddr = editIP.getText().toString();
		//note2 = (TextView) findViewById(R.id.notes_02);
		//note2.setText(IPAddr);
		EditText editPort =(EditText) findViewById(R.id.Portedit);
		String portstr = editPort.getText().toString();
		port = Integer.valueOf(portstr);
		//note2.setText("Target connection address: " + IPAddr + " port " + portstr);
		buttonIP = (Button) findViewById(R.id.buttonIPset);
		buttonIP.setTextColor(Color.LTGRAY);
		buttonIP.setEnabled(false);
		//connect = (Button) findViewById(R.id.buttonConnect);
		connect.setEnabled(true);
		connect.setTextColor(Color.BLACK);
		//disconnect = (Button) findViewById(R.id.buttonDisconnect);
		disconnect.setTextColor(Color.BLACK);
		writeFile(null); // Remember the IP setting
	
	}
	

	public void btnConnect(View view) {	
		
		note1.setText("Trying to connect");

		connect.setEnabled(false);
		disconnect.setEnabled(true);
		buttonIP.setEnabled(false);
		buttonIP.setBackgroundColor(256);
		received.setEnabled(true);
		//receiveLab.setEnabled(true);
		
		threadStop = 0;
		
		boolean connectionSuccess = true;
		
		 try {
			 
			 clientSocket.connect(new InetSocketAddress(IPAddr, port), timeout);
		    } catch (UnknownHostException e) {
		        String msg = e.toString();
		        showMessages(msg);
		        connectionSuccess = false;
		    } catch (IOException e) {
		    	String msg = "«br»" + e.toString() + "«br»«b»Try resetting the server before running this client.«/b»";
		    	msg += "    «b»Also ensure that the router channel is not blocked by another router.«/b»«br»";
		    	showMessages(msg);
		    	connectionSuccess = false;
		        disconnect.setEnabled(false);
		    }
		
		if (connectionSuccess) {
			connect.setTextColor(Color.BLACK);
			connect.setText("Connected");
			
			note1.setText("Connected");
			
			mHandler = new Handler(); 
			mHandler.post(mUpdate); 
		}
		
		} 
	
	//*****************************************************
		// The 2nd thread.
		// This thread contains the routines for the transmission and reception of control data.
		public Runnable mUpdate = new Runnable() {		
			   @Override
			public void run() {
				   
				   char arg0 = 0;
				   char arg1 = 42;  // asterisk
				   
			     i++;  // Not currently used 
			     
			     if(started == 0) {
			    	 started++;
			    	 theGuts(arg1);
			    	 mydelay(250); 
			    	 received.setText(reflected);
			     }
			     
			     // If there is a current grid command, send it
			     // and get a reply
			     if(gridCommand != 0) {
			    	 theGuts(gridCommand);
			    	 gridCommand = 0; 
			    	 //mydelay(250);
			    	 received.setText(reflected);
			     }
			     
			     // Test if window still has focus or visible
			     	else if (winfoc() == true) {
			    	   theGuts(keepAlive);
			    	 // Sending the keepAlive char is actually redundant
			    	 // because the server will detect a lost connection anyway.
			    	 // It is kept here as a starting point for diagnosis
			     }
			     
			     // End the connection.  A fail-safe strategy because 
			     // the server will respond by stopping motors 
			     // if they happen to be running
			        else {wasbuttonExit(null);} 
			     
			    // Loop after a short delay 
			    if(threadStop == 0) { 
			    	mHandler.postDelayed(this, 250); 
			    }
			     
			    }
			  
			};
			
	// End of 2nd thread	
	//***********************************************************	
				
	//TCP send and receive (called from within 2nd thread)
	public void theGuts(char gridCmd) { 
			
		 k++;
		 
		    if (clientSocket.isConnected()) {
		    	
		        try {  //  Send data ...
		        	boolean keeper = false;
		        	OutputStream outstr = clientSocket.getOutputStream();
		        	fetchCommandString();  //  Method to organize command string
		        	//if(commandString.compareTo(commandStrOld) == 0) {keeper = true;} // Do not transmit consecutive duplicates.
		        	if(commandString.equals(commandStrOld)) {keeper = true;} // Do not transmit consecutive duplicates.
		        	outmsg = commandString + "\r\n";
		        	if(keeper == true) outmsg = "&" + "\r\n";
		        	if(k == 0) {outmsg = " ";}
		        	byte[] outbytes = outmsg.getBytes();
		        	outstr.write(outbytes);  
		        	// Above is string version, 3 lines below is single char version
		        	// char outmsg = gridCmd;
		        	// if(k == 0) {outmsg = 12;}
		        	// outstr.write(outmsg);
		        	commandStrOld = commandString;
		        } catch (IOException e) {
		        	String msg = "«br»Device was connected but there was an«br»";
		            msg += "exception while WRITING to the socket.«br»«br»" + e.toString();
		            showMessages(msg);
		        }
		        
		        try {  //  Receive data ...
		            InputStream instr = clientSocket.getInputStream();
		            clientSocket.setSoTimeout(5000);  // Prevents blocking when expected data does not arrive.
		            int buffSize = clientSocket.getReceiveBufferSize();
			        //  In the lines below it is not clear why the maximum buffer size needs to be some times tested and sometimes not.	
		            //  NB The maximum buffSize test prevents uncaught fatal overflow when IP link is broken (EPIPE).
		            //  However, the test prevents reception of the 'Hello' message from server so omit it for 1st iteration.  
		            boolean readit = false;
		            if(k » 0) {if(buffSize » 0 && buffSize « 100) readit = true;}  // All iterations except the first.
		            else      {if(buffSize » 0) readit = true;}  // First iteration case.
		            if(readit == true) {
		            	byte[] buff = new byte[buffSize];
		            	int byteCount = instr.read(buff);
		            	reflected = new String(buff, 0, byteCount); 	// Read the input data
		            }
		        } catch (IOException e) {
					String msg = "«br»Device was connected but there was an«br»"; 
		            msg += "exception while READING the socket.«br»«br»" + e.toString();
		            showMessages(msg);
		        }
		        
		    } // End of If
		    
		} // End of method

public void fetchCommandString() {
	
	if(buttonTestToggle == true && brake == true) {
		testCount++;  // To defeat the command string repeat test (during development)
		commandString = "T" + "`" + "Test" + "`" + String.valueOf(testCount) + termin;
		note1.setText("Sent:  " + commandString);
		buttonTestToggle = false;
		return;		
	}
	
	if(buttonSpeedToggle == false) {
		newfspeedLeft = fspeedLeft / 2;
		newfspeedRight = fspeedRight / 2; 
	}
	else {
		newfspeedLeft = fspeedLeft;
		newfspeedRight = fspeedRight; 
	}
	
	int speedLeft = (int) newfspeedLeft; 
	int speedRight = (int) newfspeedRight;
	
	textView1.setText(String.valueOf(speedLeft));
	textView1B.setText(String.valueOf(speedRight));
	
	brake =false;
	if(speedLeft « bk && speedLeft » -bk && speedRight « bk && speedRight » -bk) {brake = true;}
	
	if(brake == false ) { 
		
	    //Adjust speed settings which are too low to start motors moving
		//NB  The 3rd test on each line negates minimum to enable very slow sharp turns
		if(speedLeft » 0 && speedLeft « ms && speedRight « ms) {speedLeft = ms;}
		if(speedLeft « 0 && speedLeft » -ms && speedRight » ms) {speedLeft = -ms;}
		if(speedRight » 0 && speedRight « ms && speedLeft « ms) {speedRight = ms;}
		if(speedRight « 0 && speedRight » -ms && speedLeft » ms) {speedRight = -ms;}		
		
		commandString = "P" + "`" + speedLeft + "`" + speedRight + termin;
		}
	else {
		commandString = "S" + "`" + "brake" + "`" + "brake" + termin;
		fspeedLeft = 0; fspeedRight = 0; // Seems to need this for 100% stopping reliability
		}
	
	note1.setText("Sent:  " + commandString);
	
}

			
boolean winfoc() {
//  Doing this inside the actual Runnable is not allowed
	boolean x = hasWindowFocus();
	return x;
	}
	
public void mydelay(Integer millisecs) {
	//TextView note1 = (TextView) findViewById(R.id.notes_01);
	try {
		Thread.sleep(millisecs);
	} catch (InterruptedException e) {
		String msg = "Thread sleep error.«br»" + e.toString();
		showMessages(msg);
	}
	}

public void btnDisconnect(View view) { 
	
	//System.exit(0); // Bad practice but kills signal more reliably than  finsh()
	finish();  //  Temporary fix because cannot test for closed socket
	
	disconnect.setEnabled(false);
	
	try {
		clientSocket.close();
	} catch (IOException e) {
		String msg = "Failed to close connection.«br»" + e.toString();
		showMessages(msg);
	}
	threadStop = 1;
	disconnect.setTextColor(Color.BLACK);
	
}


// Was a button method but button no longer exists therefore now a plain method
public void wasbuttonExit(View view) {
	
	System.exit(0); // Bad practice but kills signal more reliably than finish()
	
}

	
public void writeFile(View view) {
		
		EditText editIP = (EditText) findViewById(R.id.IPedit);
		IPAddr = editIP.getText().toString();
		                            
		try {
		    FileOutputStream fos = openFileOutput("ArduinoIPAddr", Context.MODE_PRIVATE);
		    //fos.write(IPAddr.getText().toString().getBytes());
		    fos.write(IPAddr.getBytes());
		    fos.close();
		} catch (Exception e) {;
		    String msg = "Cannot write local file.«br»" + e.toString();
		    showMessages(msg);
		}
		
	}
		
	public void readFile(View view) {
		
		try {
		    BufferedReader inputReader = new BufferedReader(new InputStreamReader(
		            openFileInput("ArduinoIPAddr")));
		    String inputString;
		    StringBuffer stringBuffer = new StringBuffer();                
		    while ((inputString = inputReader.readLine()) != null) {
		        stringBuffer.append(inputString + "\n");
		    }
		    fileContents = stringBuffer.toString();
		} catch (IOException e) {
		    String msg = "Cannot read local file.«br»" + e.toString();
		    showMessages(msg);
		}			
	}
	
	// ****************** End of routines imported from WiFi_Android_01 **********************

}
----Layoutfile ----

?xml version="1.0" encoding="UTF-8"?

-RelativeLayout
android:orientation="verticalandroid:backgandroid:layout_height="fill_parent"
android:layout_width="fill_parent" android:id="@+id/RelativeLayout1"
xmlns:android="http://schemas.android.com/apk/res/android"

TextView android:background="@color/title" android:layout_height="50dp"
android:layout_width="wrap_content" android:id="@+id/textTitle"
android:text="Remote Kartie Controller" android:textSize="25sp"
android:textColor="@color/white" android:textStyle="bold"
android:layout_marginBottom="0dp" android:layout_marginLeft="160dp"/

TextView android:background="@color/joyfield" android:layout_height="50dp"
android:layout_width="fill_parent" android:id="@+id/textPortLabel"
android:text="Port" android:textSize="20sp" android:textColor="@color/yellow"
android:textStyle="bold" android:layout_marginBottom="0dp"
android:layout_marginLeft="40dp" android:gravity="center"
android:paddingTop="25dp" android:paddingBottom="0dp"
android:layout_toRightOf="@+id/textTitle"/

Button android:background="@color/defbutton" android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="@+id/buttonIPset" android:text=" Confirm IP address  "
android:textSize="25sp" android:layout_marginBottom="0dp"
android:layout_marginLeft="10dp" android:onClick="btnIPset"
android:layout_below="@+id/textTitle" android:layout_marginRight="10dp"/

EditText android:background="@color/joyfield" android:layout_height="44dp"
android:layout_width="200dp" android:id="@+id/IPedit"
android:text="192.168.1.3" android:textSize="25sp"
android:textColor="@color/yellow" android:layout_marginBottom="10dp"
android:paddingTop="7dp" android:layout_toRightOf="@id/buttonIPset"
android:layout_below="@+id/textTitle" android:layout_marginRight="32dp"
android:scrollHorizontally="false" android:singleLine="true"
android:paddingRight="5dp" android:paddingLeft="0dp"/

EditText android:background="@color/joyfield" android:layout_height="44dp"
android:layout_width="wrap_content" android:id="@+id/Portedit"
android:text="23" android:textSize="25sp" android:textColor="@color/yellow"
android:layout_marginBottom="10dp" android:paddingTop="7dp"
android:layout_toRightOf="@id/IPedit" android:layout_below="@+id/textTitle"
android:paddingRight="0dp" android:paddingLeft="0dp"/

Button android:background="@color/defbutton"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="@+id/buttonConnect" android:text=" Connect "
android:textSize="25sp" android:layout_marginBottom="0dp"
android:layout_marginLeft="10dp" android:onClick="btnConnect"
android:layout_below="@+id/buttonIPset" android:layout_marginRight="10dp"/

TextView android:background="@color/joyfield" android:layout_height="44dp"
android:layout_width="wrap_content" android:id="@+id/textConnect"
android:text="Disconnected" android:textSize="25sp"
android:textColor="@color/yellow" android:layout_marginBottom="10dp"
android:paddingTop="7dp" android:layout_toRightOf="@id/buttonConnect"
android:layout_below="@+id/buttonIPset" android:layout_marginRight="5dp"
android:paddingRight="10dp" android:paddingLeft="10dp"/

Button android:background="@color/defbutton"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="@+id/buttonDisconnect" android:text=" Disconnect/Exit"
android:textSize="25sp" android:layout_marginBottom="0dp"
android:layout_marginLeft="5dp" android:layout_toRightOf="@+id/textConnect"
android:onClick="btnDisconnect" android:layout_below="@+id/buttonIPset"
android:layout_marginRight="10dp"/

TextView android:background="@color/joyfield" android:layout_height="wrap_content" android:layout_width="fill_parent"
android:id="@+id/stopNotice" android:text="- - - - - - - - - - - - - - -"
android:textSize="15sp" android:textColor="@color/yellow"
android:textStyle="bold" android:layout_marginBottom="0dp"
android:gravity="center" android:layout_below="@+id/buttonConnect"/


-RelativeLayout android:layout_height="wrap_content"
android:layout_width="wrap_content" android:id="@+id/joyContainer"
android:layout_below="@+id/stopNotice"

ImageView android:background="@drawable/kartmstart" android:layout_height="550dp" android:layout_width="fill_parent"
android:id="@+id/imageView1" android:layout_centerHorizontal="true"
android:contentDescription="J stick area"/

Button android:background="@color/defbutton" android:layout_height="100dp"
android:layout_width="100dp" android:id="@+id/buttonSpinLeft"
android:text="Spin\nleft" android:textSize="25sp" android:layout_marginLeft="4dp" android:onClick="btnSpinLeft"
android:padding="15dp" android:layout_centerVertical="true"
android:layout_alignParentLeft="true"/

Button android:background="@color/defbutton" android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="@+id/buttonStart" android:text="Start\ndriving"
android:textSize="25sp" android:onClick="buttonStart" android:padding="15dp"
android:visibility="invisible" android:layout_centerInParent="true"/

Button android:background="@color/defbutton" android:layout_height="100dp"
android:layout_width="100dp" android:id="@+id/buttonSpinRight"
android:text="Spin\nright" android:textSize="25sp" android:onClick="btnSpinRight" android:layout_marginRight="6dp"
android:padding="15dp" android:layout_centerVertical="true"
android:layout_alignParentRight="true"/

!-- Invisible except for messages display --


TextView android:background="@color/brown" android:layout_height="300dp"
android:layout_width="500dp" android:id="@+id/textViewMsgs"
android:text="Connection mesages" android:textSize="25sp"
android:textColor="@color/white" android:layout_marginBottom="0dp"
android:layout_below="@+id/buttonSpinLeft" android:padding="15dp"
android:visibility="invisible" android:layout_centerInParent="true"/

Button android:background="@color/defbutton" android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="@+id/endMessages" android:text="E X I T" android:textSize="30sp"
android:textColor="@color/brown" android:textStyle="bold"
android:paddingTop="5dp" android:paddingBottom="15dp" android:onClick="closeMessages" android:layout_below="@+id/textViewMsgs"
android:paddingRight="15dp" android:paddingLeft="15dp" android:layout_centerHorizontal="true" android:visibility="invisible"
android:layout_marginTop="10dp"/

!-- End of invisible --


/RelativeLayout

Button android:background="@color/defbutton"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="@+id/buttonTest" android:text="Blink Test"
android:textSize="25sp" android:layout_marginBottom="0dp"
android:layout_marginLeft="10dp" android:onClick="btnTest"
android:layout_below="@+id/joyContainer" android:layout_marginRight="10dp"/

TextView android:background="@color/joyfield" android:layout_height="44dp"
android:layout_width="70dp" android:id="@+id/textView1" android:text=" 1234"
android:textSize="25sp" android:textColor="@color/yellow"
android:layout_marginBottom="10dp" android:layout_marginLeft="75dp"
android:paddingTop="7dp" android:layout_toRightOf="@+id/buttonTest"
android:layout_below="@+id/joyContainer" android:layout_marginRight="12dp"/

TextView android:background="@color/joyfield" android:layout_height="44dp"
android:layout_width="70dp" android:id="@+id/textView1B" android:text=" 1234
" android:textSize="25sp" android:textColor="@color/yellow"
android:layout_marginBottom="0dp" android:layout_marginLeft="25dp"
android:paddingTop="7dp" android:layout_toRightOf="@+id/textView1"
android:layout_below="@+id/joyContainer" android:layout_marginRight="10dp"/

Button android:background="@color/defbutton"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="@+id/buttonSpeedX2" android:text="Speed x 2"
android:textSize="25sp" android:layout_marginBottom="0dp"
android:layout_marginLeft="45dp" android:layout_toRightOf="@+id/textView1B"android:onClick="buttonSpeed"
android:layout_below="@+id/joyContainer" android:layout_marginRight="10dp"/


-HorizontalScrollView android:layout_height="fill_parent"
android:layout_width="fill_parent" android:layout_below="@+id/buttonTest"

TextView android:background="@color/joyfield"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:id="@+id/notes_01" android:text="Transmitted
commands"android:textSize="25sp" android:textColor="@color/yellow"
android:layout_marginBottom="10dp" android:scrollbars="vertical"
android:layout_gravity="center_horizontal"/

/HorizontalScrollView

/RelativeLayout

----- Strings file ------

«?xml version="1.0" encoding="UTF-8"?»

-«resources»

«string name="app_name"»WiFi_Arduino_01P«/string»

«string name="app_name_mv"»MotionEvent«/string»

«string name="action_settings"»Settings«/string»

«string name="hello_world"»Hello world!«/string»

«color name="defbutton"»@android:drawable/btn_default«/color»

«color name="joyfield"»#666666«/color»

«color name="title"»#666666«/color»

«color name="white"»#FFFFFF«/color»

«color name="silver"»#C0C0C0«/color»

«color name="grey"»#808080«/color»

«color name="black"»#000000«/color»

«color name="red"»#FF0000«/color»

«color name="blue"»#0000FF«/color»

«color name="green"»#00FF00«/color»

«color name="magenta"»#FF80FF«/color»

«color name="cyan"»#80FFFF«/color»

«color name="yellow"»#FFFF80«/color»

«color name="brown"»#803000«/color»

«color name="bg"»#ECECEC«/color»

«/resources»