Autoconnect. Connection in separate thread. Reconnection on error. UI
improvements
This commit is contained in:
		| @@ -6,9 +6,8 @@ | |||||||
|  |  | ||||||
|     <application |     <application | ||||||
|         android:allowBackup="true" |         android:allowBackup="true" | ||||||
|         android:icon="@mipmap/ic_launcher" |         android:icon="@drawable/icon" | ||||||
|         android:label="@string/app_name" |         android:label="@string/app_name" | ||||||
|         android:roundIcon="@mipmap/ic_launcher_round" |  | ||||||
|         android:supportsRtl="true" |         android:supportsRtl="true" | ||||||
|         android:theme="@style/AppTheme"> |         android:theme="@style/AppTheme"> | ||||||
|         <activity android:name=".MainActivity" android:configChanges="orientation" |         <activity android:name=".MainActivity" android:configChanges="orientation" | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import android.support.v7.app.AppCompatActivity; | |||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.widget.Button; | import android.widget.Button; | ||||||
|  | import android.widget.ImageView; | ||||||
| import android.widget.SeekBar; | import android.widget.SeekBar; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| @@ -20,7 +21,7 @@ import java.util.UUID; | |||||||
| public class MainActivity extends AppCompatActivity { | public class MainActivity extends AppCompatActivity { | ||||||
|  |  | ||||||
|     private final static int REQUEST_ENABLE_BT = 1; |     private final static int REQUEST_ENABLE_BT = 1; | ||||||
|     Button btnConnect; |     TextView txtStatus; | ||||||
|     OutputStream btOutStream; |     OutputStream btOutStream; | ||||||
|     Boolean btConnected = false; |     Boolean btConnected = false; | ||||||
|     BluetoothSocket btSocket = null; |     BluetoothSocket btSocket = null; | ||||||
| @@ -28,25 +29,33 @@ public class MainActivity extends AppCompatActivity { | |||||||
|     SeekBar motorB; |     SeekBar motorB; | ||||||
|     TextView txtA; |     TextView txtA; | ||||||
|     TextView txtB; |     TextView txtB; | ||||||
|     int motorACommand = 2; |     private final static int MOTOR_FULL_FORWARD_COMMAND = 4; | ||||||
|     int motorBCommand = 2; |     private final static int MOTOR_FULL_BACKWARD_COMMAND = 0; | ||||||
|  |     private final static int MOTOR_STOP_COMMAND = 2; | ||||||
|  |     ImageView imEngine; | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void onCreate(Bundle savedInstanceState) { |     protected void onCreate(Bundle savedInstanceState) { | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|         setContentView(R.layout.activity_main); |         setContentView(R.layout.activity_main); | ||||||
|  |  | ||||||
|         btnConnect = (Button)findViewById(R.id.btnConnect); |         txtStatus = (TextView) findViewById(R.id.txtStatus); | ||||||
|  |  | ||||||
|         motorA = (SeekBar)findViewById(R.id.motorA); |         motorA = (SeekBar)findViewById(R.id.motorB); | ||||||
|         motorA.setProgress(2); |         motorA.setProgress(MOTOR_STOP_COMMAND); | ||||||
|         motorA.setMax(4); |         motorA.setMax(MOTOR_FULL_FORWARD_COMMAND); | ||||||
|         motorB = (SeekBar)findViewById(R.id.motorB); |         motorB = (SeekBar)findViewById(R.id.motorA); | ||||||
|         motorB.setProgress(2); |         motorB.setProgress(MOTOR_STOP_COMMAND); | ||||||
|         motorB.setMax(4); |         motorB.setMax(MOTOR_FULL_FORWARD_COMMAND); | ||||||
|  |         motorA.setEnabled(false); | ||||||
|  |         motorB.setEnabled(false); | ||||||
|  |         imEngine = (ImageView)findViewById(R.id.imCE); | ||||||
|  |  | ||||||
|  |         imEngine.setVisibility(View.VISIBLE); | ||||||
|         txtA = (TextView)findViewById(R.id.txtA); |         txtA = (TextView)findViewById(R.id.txtA); | ||||||
|         txtB = (TextView)findViewById(R.id.txtB); |         txtB = (TextView)findViewById(R.id.txtB); | ||||||
|  |         txtA.setText(Integer.toString(MOTOR_STOP_COMMAND)); | ||||||
|  |         txtB.setText(Integer.toString(MOTOR_STOP_COMMAND)); | ||||||
|  |  | ||||||
|         motorA.setOnSeekBarChangeListener( |         motorA.setOnSeekBarChangeListener( | ||||||
|                 new SeekBar.OnSeekBarChangeListener() { |                 new SeekBar.OnSeekBarChangeListener() { | ||||||
| @@ -54,7 +63,6 @@ public class MainActivity extends AppCompatActivity { | |||||||
|                     @Override |                     @Override | ||||||
|                     public void onProgressChanged(SeekBar seekBar, |                     public void onProgressChanged(SeekBar seekBar, | ||||||
|                                                   int progresValue, boolean fromUser) { |                                                   int progresValue, boolean fromUser) { | ||||||
|                         motorBCommand = progresValue; |  | ||||||
|                         sendCommand(); |                         sendCommand(); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -67,7 +75,7 @@ public class MainActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|                     @Override |                     @Override | ||||||
|                     public void onStopTrackingTouch(SeekBar seekBar) { |                     public void onStopTrackingTouch(SeekBar seekBar) { | ||||||
|                         seekBar.setProgress(2); |                         seekBar.setProgress(MOTOR_STOP_COMMAND); | ||||||
|  |  | ||||||
|                     } |                     } | ||||||
|         }); |         }); | ||||||
| @@ -78,7 +86,6 @@ public class MainActivity extends AppCompatActivity { | |||||||
|                     @Override |                     @Override | ||||||
|                     public void onProgressChanged(SeekBar seekBar, |                     public void onProgressChanged(SeekBar seekBar, | ||||||
|                                                   int progresValue, boolean fromUser) { |                                                   int progresValue, boolean fromUser) { | ||||||
|                         motorACommand = progresValue; |  | ||||||
|                         sendCommand(); |                         sendCommand(); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -91,14 +98,51 @@ public class MainActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|                     @Override |                     @Override | ||||||
|                     public void onStopTrackingTouch(SeekBar seekBar) { |                     public void onStopTrackingTouch(SeekBar seekBar) { | ||||||
|                         seekBar.setProgress(2); |                         seekBar.setProgress(MOTOR_STOP_COMMAND); | ||||||
|  |  | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|         btnConnect.setOnClickListener(new View.OnClickListener() { |         connectToCar(); | ||||||
|             public void onClick(View v) { |  | ||||||
|                 if (!btConnected) { |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     protected void onDestroy() { | ||||||
|  |         disconnectFromCar(); | ||||||
|  |         super.onDestroy(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void disconnectFromCar() { | ||||||
|  |         try { | ||||||
|  |             btOutStream.close(); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             //e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |         try { | ||||||
|  |             btSocket.close(); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             //e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |         btConnected = false; | ||||||
|  |         motorA.setEnabled(false); | ||||||
|  |         motorB.setEnabled(false); | ||||||
|  |         imEngine.setVisibility(View.GONE); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void connectToCar() { | ||||||
|  |         new Thread() { | ||||||
|  |             public void run() { | ||||||
|  |                 while (btSocket==null || !btSocket.isConnected()) { | ||||||
|  |                     runOnUiThread(new Runnable() { | ||||||
|  |                         @Override | ||||||
|  |                         public void run() { | ||||||
|  |                             txtStatus.setText("Connecting..."); | ||||||
|  |                             imEngine.setVisibility(View.VISIBLE); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |  | ||||||
|                     BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); |                     BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); | ||||||
|                     if (adapter == null) { |                     if (adapter == null) { | ||||||
|                         // Device does not support Bluetooth |                         // Device does not support Bluetooth | ||||||
| @@ -106,62 +150,83 @@ public class MainActivity extends AppCompatActivity { | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (!adapter.isEnabled()) { |                     if (!adapter.isEnabled()) { | ||||||
|  |                         runOnUiThread(new Runnable() { | ||||||
|  |                             @Override | ||||||
|  |                             public void run() { | ||||||
|  |                                 txtStatus.setText("Bluetooth is not enabled. Will retry in 5 sec."); | ||||||
|  |                                 imEngine.setVisibility(View.VISIBLE); | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|                         //make sure the device's bluetooth is enabled |                         //make sure the device's bluetooth is enabled | ||||||
|                         Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); |                         Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); | ||||||
|                         startActivityForResult(enableBluetooth, REQUEST_ENABLE_BT); |                         startActivityForResult(enableBluetooth, REQUEST_ENABLE_BT); | ||||||
|                     } |                     } else { | ||||||
|  |                         final UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //UUID for serial connection | ||||||
|  |                         String mac = "98:D3:31:F5:2D:2F"; //my laptop's mac adress | ||||||
|  |                         BluetoothDevice device = adapter.getRemoteDevice(mac); //get remote device by mac, we assume these two devices are already paired | ||||||
|  |                         // Get a BluetoothSocket to connect with the given BluetoothDevice | ||||||
|  |                         btSocket = null; | ||||||
|  |                         btOutStream = null; | ||||||
|  |                         try { | ||||||
|  |                             btSocket = device.createRfcommSocketToServiceRecord(SERIAL_UUID); | ||||||
|  |                         } catch (Exception e) { | ||||||
|  |                             runOnUiThread(new Runnable() { | ||||||
|  |                                 @Override | ||||||
|  |                                 public void run() { | ||||||
|  |                                     txtStatus.setText("Error creating socket.  Will retry in 5 sec."); | ||||||
|  |                                     imEngine.setVisibility(View.VISIBLE); | ||||||
|  |                                 } | ||||||
|  |                             }); | ||||||
|  |                         } | ||||||
|  |  | ||||||
|                     final UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //UUID for serial connection |                         try { | ||||||
|                     String mac = "98:D3:31:F5:2D:2F"; //my laptop's mac adress |                             btSocket.connect(); | ||||||
|                     BluetoothDevice device = adapter.getRemoteDevice(mac); //get remote device by mac, we assume these two devices are already paired |                             btOutStream = btSocket.getOutputStream(); | ||||||
|  |  | ||||||
|  |                             btConnected = true; | ||||||
|  |                             runOnUiThread(new Runnable() { | ||||||
|  |                                 @Override | ||||||
|  |                                 public void run() { | ||||||
|  |                                     txtStatus.setText("Connected"); | ||||||
|  |                                     imEngine.setVisibility(View.GONE); | ||||||
|  |                                     motorA.setEnabled(true); | ||||||
|  |                                     motorB.setEnabled(true); | ||||||
|  |                                 } | ||||||
|  |                             }); | ||||||
|  |                         } catch (Exception e) { | ||||||
|  |                             final Exception er = e; | ||||||
|  |                             runOnUiThread(new Runnable() { | ||||||
|  |                                 @Override | ||||||
|  |                                 public void run() { | ||||||
|  |                                     txtStatus.setText("Connection error. Will retry in 5 sec."); | ||||||
|  |                                     imEngine.setVisibility(View.VISIBLE); | ||||||
|  |                                 } | ||||||
|  |  | ||||||
|                     // Get a BluetoothSocket to connect with the given BluetoothDevice |                             }); | ||||||
|                     btSocket = null; |                             e.printStackTrace(); | ||||||
|                     btOutStream = null; |                         } | ||||||
|                     try { |  | ||||||
|                         btSocket = device.createRfcommSocketToServiceRecord(SERIAL_UUID); |  | ||||||
|                     } catch (IOException e) { |  | ||||||
|                         e.printStackTrace(); |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     try { |  | ||||||
|                         btSocket.connect(); |  | ||||||
|                         btOutStream = btSocket.getOutputStream(); |  | ||||||
|                         btConnected = true; |  | ||||||
|                         btnConnect.setText("Disconnect"); |  | ||||||
|                         //now you can use out to send output via out.write |  | ||||||
|                     } catch (IOException e) { |  | ||||||
|                         e.printStackTrace(); |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     try { |  | ||||||
|                         btOutStream.close(); |  | ||||||
|                     } catch (IOException e) { |  | ||||||
|                         e.printStackTrace(); |  | ||||||
|                     } |                     } | ||||||
|                     try { |                     try { | ||||||
|                         btSocket.close(); |                         Thread.sleep(5000); | ||||||
|                     } catch (IOException e) { |                     } catch (InterruptedException e) { | ||||||
|                         e.printStackTrace(); |                         e.printStackTrace(); | ||||||
|                     } |                     } | ||||||
|                     btConnected = false; |  | ||||||
|                     btnConnect.setText("Connect"); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }); |         }.start(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void sendCommand() { |     private void sendCommand() { | ||||||
|         String m1 = Integer.toString(motorACommand); |         String m1 = Integer.toString(motorA.getProgress()); | ||||||
|         String m2 = Integer.toString(motorBCommand); |         String m2 = Integer.toString(motorB.getProgress()); | ||||||
|         txtA.setText(m1); |         txtA.setText(m1); | ||||||
|         txtB.setText(m2); |         txtB.setText(m2); | ||||||
|         try { |         try { | ||||||
|             if (btOutStream != null) |             btOutStream.write((m1+m2).getBytes()); | ||||||
|                 btOutStream.write((m1+m2).getBytes()); |         } catch (Exception e) { | ||||||
|         } catch (IOException e) { |             txtStatus.setText("Disconnected"); | ||||||
|             //e.printStackTrace(); |             disconnectFromCar(); | ||||||
|  |             connectToCar(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable/engine.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable/engine.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 27 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable/icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable/icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 55 KiB | 
| @@ -9,9 +9,10 @@ | |||||||
|     <SeekBar |     <SeekBar | ||||||
|         android:id="@+id/motorA" |         android:id="@+id/motorA" | ||||||
|         style="@style/Widget.AppCompat.SeekBar.Discrete" |         style="@style/Widget.AppCompat.SeekBar.Discrete" | ||||||
|         android:layout_width="182dp" |         android:layout_width="0dp" | ||||||
|         android:layout_height="0dp" |         android:layout_height="0dp" | ||||||
|         android:layout_marginBottom="8dp" |         android:layout_marginBottom="8dp" | ||||||
|  |         android:layout_marginEnd="8dp" | ||||||
|         android:layout_marginStart="8dp" |         android:layout_marginStart="8dp" | ||||||
|         android:layout_marginTop="8dp" |         android:layout_marginTop="8dp" | ||||||
|         android:max="500" |         android:max="500" | ||||||
| @@ -20,16 +21,18 @@ | |||||||
|         android:rotation="270" |         android:rotation="270" | ||||||
|         android:thumb="@android:drawable/ic_notification_overlay" |         android:thumb="@android:drawable/ic_notification_overlay" | ||||||
|         app:layout_constraintBottom_toBottomOf="parent" |         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |         app:layout_constraintEnd_toStartOf="@+id/guideline" | ||||||
|         app:layout_constraintStart_toStartOf="parent" |         app:layout_constraintStart_toStartOf="parent" | ||||||
|         app:layout_constraintTop_toTopOf="parent" /> |         app:layout_constraintTop_toTopOf="parent" /> | ||||||
|  |  | ||||||
|     <SeekBar |     <SeekBar | ||||||
|         android:id="@+id/motorB" |         android:id="@+id/motorB" | ||||||
|         style="@style/Widget.AppCompat.SeekBar.Discrete" |         style="@style/Widget.AppCompat.SeekBar.Discrete" | ||||||
|         android:layout_width="182dp" |         android:layout_width="0dp" | ||||||
|         android:layout_height="0dp" |         android:layout_height="0dp" | ||||||
|         android:layout_marginBottom="8dp" |         android:layout_marginBottom="8dp" | ||||||
|         android:layout_marginEnd="8dp" |         android:layout_marginEnd="8dp" | ||||||
|  |         android:layout_marginStart="8dp" | ||||||
|         android:layout_marginTop="8dp" |         android:layout_marginTop="8dp" | ||||||
|         android:max="500" |         android:max="500" | ||||||
|         android:min="0" |         android:min="0" | ||||||
| @@ -38,18 +41,7 @@ | |||||||
|         android:thumb="@android:drawable/ic_notification_overlay" |         android:thumb="@android:drawable/ic_notification_overlay" | ||||||
|         app:layout_constraintBottom_toBottomOf="parent" |         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|         app:layout_constraintEnd_toEndOf="parent" |         app:layout_constraintEnd_toEndOf="parent" | ||||||
|         app:layout_constraintTop_toTopOf="parent" /> |         app:layout_constraintStart_toStartOf="@+id/guideline" | ||||||
|  |  | ||||||
|     <Button |  | ||||||
|         android:id="@+id/btnConnect" |  | ||||||
|         android:layout_width="wrap_content" |  | ||||||
|         android:layout_height="wrap_content" |  | ||||||
|         android:layout_marginEnd="8dp" |  | ||||||
|         android:layout_marginStart="8dp" |  | ||||||
|         android:layout_marginTop="8dp" |  | ||||||
|         android:text="Connect" |  | ||||||
|         app:layout_constraintEnd_toEndOf="parent" |  | ||||||
|         app:layout_constraintStart_toStartOf="parent" |  | ||||||
|         app:layout_constraintTop_toTopOf="parent" /> |         app:layout_constraintTop_toTopOf="parent" /> | ||||||
|  |  | ||||||
|     <TextView |     <TextView | ||||||
| @@ -60,7 +52,7 @@ | |||||||
|         android:layout_marginStart="8dp" |         android:layout_marginStart="8dp" | ||||||
|         android:text="TextView" |         android:text="TextView" | ||||||
|         app:layout_constraintBottom_toBottomOf="parent" |         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|         app:layout_constraintStart_toEndOf="@+id/motorA" /> |         app:layout_constraintStart_toStartOf="parent" /> | ||||||
|  |  | ||||||
|     <TextView |     <TextView | ||||||
|         android:id="@+id/txtB" |         android:id="@+id/txtB" | ||||||
| @@ -70,6 +62,37 @@ | |||||||
|         android:layout_marginEnd="8dp" |         android:layout_marginEnd="8dp" | ||||||
|         android:text="TextView" |         android:text="TextView" | ||||||
|         app:layout_constraintBottom_toBottomOf="parent" |         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|         app:layout_constraintEnd_toStartOf="@+id/motorB" /> |         app:layout_constraintEnd_toEndOf="parent" /> | ||||||
|  |  | ||||||
|  |     <android.support.constraint.Guideline | ||||||
|  |         android:id="@+id/guideline" | ||||||
|  |         android:layout_width="wrap_content" | ||||||
|  |         android:layout_height="wrap_content" | ||||||
|  |         android:orientation="vertical" | ||||||
|  |         app:layout_constraintGuide_percent="0.5" /> | ||||||
|  |  | ||||||
|  |     <TextView | ||||||
|  |         android:id="@+id/txtStatus" | ||||||
|  |         android:layout_width="wrap_content" | ||||||
|  |         android:layout_height="wrap_content" | ||||||
|  |         android:layout_marginBottom="8dp" | ||||||
|  |         android:layout_marginEnd="8dp" | ||||||
|  |         android:layout_marginStart="8dp" | ||||||
|  |         android:text="Status..." | ||||||
|  |         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |         app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |         app:layout_constraintStart_toStartOf="parent" /> | ||||||
|  |  | ||||||
|  |     <ImageView | ||||||
|  |         android:id="@+id/imCE" | ||||||
|  |         android:layout_width="101dp" | ||||||
|  |         android:layout_height="63dp" | ||||||
|  |         android:layout_marginEnd="8dp" | ||||||
|  |         android:layout_marginStart="8dp" | ||||||
|  |         android:layout_marginTop="16dp" | ||||||
|  |         app:layout_constraintEnd_toStartOf="@+id/guideline" | ||||||
|  |         app:layout_constraintStart_toStartOf="@+id/guideline" | ||||||
|  |         app:layout_constraintTop_toTopOf="parent" | ||||||
|  |         app:srcCompat="@drawable/engine" /> | ||||||
|  |  | ||||||
| </android.support.constraint.ConstraintLayout> | </android.support.constraint.ConstraintLayout> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user