diff --git a/app/build.gradle b/app/build.gradle
index 5bfba5ce9..188bf4060 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -17,6 +17,8 @@ android {
outputFileName = new File("remote-" + android.defaultConfig.versionCode + ".apk")
}
}
+ multiDexEnabled true
+
}
buildTypes {
release {
@@ -40,31 +42,34 @@ dependencies {
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
exclude group: 'com.android.support', module: 'support-annotations'
})
- implementation 'androidx.appcompat:appcompat:1.0.2'
- implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
+ implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'com.afollestad.material-dialogs:commons:0.9.6.0'
implementation 'com.mikepenz:materialdrawer:6.1.1'
- implementation 'androidx.recyclerview:recyclerview:1.0.0'
- implementation 'androidx.annotation:annotation:1.0.1'
- implementation 'com.google.android.material:material:1.0.0'
+ implementation 'androidx.recyclerview:recyclerview:1.1.0'
+ implementation 'androidx.annotation:annotation:1.1.0'
+ implementation 'com.google.android.material:material:1.1.0'
implementation 'com.mikepenz:google-material-typeface:3.0.1.3.original@aar'
implementation 'com.mikepenz:fontawesome-typeface:5.3.1.1@aar'
implementation 'com.mikepenz:octicons-typeface:3.2.0.5@aar'
implementation 'de.hdodenhof:circleimageview:2.2.0'
- implementation 'com.mikepenz:itemanimators:1.1.0'
implementation 'com.mikepenz:crossfader:1.5.1@aar'
implementation 'com.mikepenz:crossfadedrawerlayout:1.0.1@aar'
implementation 'com.google.android:flexbox:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
- implementation "androidx.preference:preference:1.1.0"
+ implementation "androidx.preference:preference:1.1.1"
testImplementation 'junit:junit:4.12'
implementation 'com.github.parse-community:ParseLiveQuery-Android:1.1.0'
implementation 'com.google.code.gson:gson:2.8.6'
- androidTestImplementation 'androidx.test:runner:1.1.1'
- implementation 'me.aflak.libraries:bluetooth:1.3.4'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ implementation 'com.github.ivbaranov:rxbluetooth2:2.1.1'
+ implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.caverock:androidsvg-aar:1.4'
+ implementation 'com.android.support:multidex:1.0.3'
+
+
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d7dfcd13c..68a9b7a19 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -28,7 +28,8 @@
-
@@ -37,15 +38,18 @@
-
+ android:theme="@style/AppTheme"
+ android:usesCleartextTraffic="true">
+
@@ -56,9 +60,9 @@
android:name=".InitialActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
- android:theme="@style/MyMaterialTheme.Base"
- android:windowSoftInputMode="stateHidden|adjustResize">
-
+ android:theme="@style/AppTheme.NoActionBar"
+ android:windowSoftInputMode="stateHidden|adjustResize"
+ tools:ignore="LockedOrientationActivity" />
diff --git a/app/src/main/java/io/treehouses/remote/Constants.java b/app/src/main/java/io/treehouses/remote/Constants.java
index 8da51f6a3..443824d02 100644
--- a/app/src/main/java/io/treehouses/remote/Constants.java
+++ b/app/src/main/java/io/treehouses/remote/Constants.java
@@ -53,6 +53,7 @@ public class Constants {
public static final int STATE_LISTEN = 1; // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
+ public static final int STATE_FAILED = -1;
// Message types sent from the BluetoothChatService Handler
public static final int MESSAGE_STATE_CHANGE = 1;
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/DialogFragments/RPIDialogFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/DialogFragments/RPIDialogFragment.java
index 97c9202e7..9731785ff 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/DialogFragments/RPIDialogFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/DialogFragments/RPIDialogFragment.java
@@ -40,14 +40,13 @@
import io.treehouses.remote.R;
import io.treehouses.remote.adapter.RPIListAdapter;
import io.treehouses.remote.bases.BaseDialogFragment;
+import io.treehouses.remote.callback.BluetoothDeviceCallback;
import io.treehouses.remote.callback.SetDisconnect;
import io.treehouses.remote.pojo.DeviceInfo;
import static android.widget.Toast.LENGTH_LONG;
-public class RPIDialogFragment extends BaseDialogFragment {
-
- private static BluetoothChatService mChatService = null;
+public class RPIDialogFragment extends BaseDialogFragment implements BluetoothDeviceCallback {
private static RPIDialogFragment instance = null;
private List raspberry_devices = new ArrayList(), all_devices = new ArrayList();
@@ -55,7 +54,6 @@ public class RPIDialogFragment extends BaseDialogFragment {
private static BluetoothDevice mainDevice = null;
private ListView listView;
private ArrayAdapter mArrayAdapter;
- private BluetoothAdapter mBluetoothAdapter;
private SetDisconnect checkConnectionState;
private Context context;
private Switch mDiscoverRaspberry;
@@ -77,25 +75,19 @@ public static androidx.fragment.app.DialogFragment newInstance(int num) {
public Dialog onCreateDialog(Bundle savedInstanceState) {
instance = this;
context = getContext();
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothCheck();
- if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); }
- mBluetoothAdapter.startDiscovery();
- LayoutInflater inflater = Objects.requireNonNull(getActivity()).getLayoutInflater();
+ LayoutInflater inflater = getActivity().getLayoutInflater();
final View mView = inflater.inflate(R.layout.activity_rpi_dialog_fragment, null);
initDialog(mView);
-
- if (mChatService == null) { mChatService = new BluetoothChatService(mHandler, getActivity().getApplicationContext()); }
-
- pairedDevices = mBluetoothAdapter.getBondedDevices();
+ mChatService.updateHandler(mHandler);
+ mChatService.startDiscovery(this);
+ pairedDevices = mChatService.getPairedDevices();
setAdapterNotNull(raspberryDevicesText);
for (BluetoothDevice d : pairedDevices) {
if (checkPiAddress(d.getAddress())) {
addToDialog(d, raspberryDevicesText, raspberry_devices, false);
progressBar.setVisibility(View.INVISIBLE); }
}
- intentFilter();
-
return mDialog;
}
@@ -106,9 +98,13 @@ private void initDialog(View mView) {
mDialog.setTitle(R.string.select_device);
listViewOnClickListener(mView);
Button mCloseButton = mView.findViewById(R.id.rpi_close_button);
- mCloseButton.setOnClickListener(v -> {
- bluetoothCheck("unregister");
- dismiss();
+ mCloseButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ checkConnectionState.checkConnectionState();
+ mChatService.disconnect();
+ dismiss();
+ }
});
mDiscoverRaspberry = mView.findViewById(R.id.rpi_switch);
mDiscoverRaspberry.setChecked(true);
@@ -116,23 +112,15 @@ private void initDialog(View mView) {
progressBar = mView.findViewById(R.id.progressBar);
}
- private void intentFilter() {
- IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
- filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
- filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
- getActivity().registerReceiver(mReceiver, filter);
- }
-
private void listViewOnClickListener(View mView) {
listView.setOnItemClickListener((parent, view, position, id) -> {
- mChatService = new BluetoothChatService(mHandler, getActivity().getApplicationContext());
+ mChatService.updateHandler(mHandler);
List deviceList;
if (mDiscoverRaspberry.isChecked()) deviceList = raspberry_devices;
else deviceList = all_devices;
if (checkPiAddress(deviceList.get(position).getAddress())) {
mainDevice = deviceList.get(position);
- mChatService.connect(deviceList.get(position),true);
+ mChatService.connectToDevice(deviceList.get(position));
int status = mChatService.getState();
mDialog.cancel();
finish(status, mView);
@@ -179,27 +167,22 @@ private void finish(int status, View mView) {
@Override
public void onDestroy() {
super.onDestroy();
- try { if (mBluetoothAdapter == null) context.unregisterReceiver(mReceiver); } catch (Exception e) { e.printStackTrace(); }
}
private AlertDialog getAlertDialog(View mView, Context context, Boolean wifi) {
return new AlertDialog.Builder(context).setView(mView).setIcon(R.drawable.dialog_icon).create();
}
- public void bluetoothCheck(String... args) {
- if (mBluetoothAdapter == null) {
+ public void bluetoothCheck() {
+ if (!mChatService.isBluetoothSupported()) {
Toast.makeText(getActivity(), "Your Bluetooth Is Not Enabled or Not Supported", LENGTH_LONG).show();
- getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, getActivity().getIntent());
- context.unregisterReceiver(mReceiver);
+// getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, getActivity().getIntent());
+ dismiss();
}
- if (args.length >= 1) {
- if (args[0].equals("unregister")) {
- context.unregisterReceiver(mReceiver);
- Intent intent = new Intent();
- intent.putExtra("mChatService", mChatService);
- getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);
- }
+ else if (!mChatService.isBluetoothEnabled()) {
+ Toast.makeText(context, "Please enable bluetooth", Toast.LENGTH_SHORT).show();
}
+
}
private void setAdapterNotNull(List listVal) {
@@ -207,20 +190,6 @@ private void setAdapterNotNull(List listVal) {
listView.setAdapter(mArrayAdapter);
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (checkPiAddress(device.getAddress())) {
- addToDialog(device, raspberryDevicesText, raspberry_devices, true);
- progressBar.setVisibility(View.INVISIBLE);
- }
- addToDialog(device, allDevicesText, all_devices, true);
- Log.e("Broadcast BT", device.getName() + "\n" + device.getAddress());
- }
- }
- };
-
private void addToDialog(BluetoothDevice device, List textList, List mDevices, Boolean inRange) {
if (!mDevices.contains(device)){
mDevices.add(device);
@@ -248,17 +217,17 @@ public void handleMessage(Message msg) {
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
+ checkConnectionState.checkConnectionState();
switch (msg.arg1) {
case Constants.STATE_CONNECTED:
- Log.e("RPIDialogFragment", "Bluetooth Connection Status Change: State Listen");
+ Log.e("RPIDialogFragment", "Bluetooth Connection Status Change: State Connected");
pDialog.dismiss();
- listener.setChatService(mChatService);
- checkConnectionState.checkConnectionState();
- mBluetoothAdapter.cancelDiscovery();
+ dismiss();
Toast.makeText(context, "Bluetooth Connected", LENGTH_LONG).show();
break;
- case Constants.STATE_NONE:
+ case Constants.STATE_FAILED:
pDialog.dismiss();
+ dismiss();
Toast.makeText(context, "Connection Failed: Please Try Again", LENGTH_LONG).show();
Log.e("RPIDialogFragment", "Bluetooth Connection Status Change: State None");
break;
@@ -272,4 +241,14 @@ public void handleMessage(Message msg) {
};
public Handler getmHandler() { return mHandler; }
+
+ @Override
+ public void onDeviceFound(BluetoothDevice device) {
+ Log.e("RPIDIALOG", "onDeviceFound: "+ device.getName());
+ if (checkPiAddress(device.getAddress())) {
+ addToDialog(device, raspberryDevicesText, raspberry_devices, true);
+ progressBar.setVisibility(View.INVISIBLE);
+ }
+ addToDialog(device, allDevicesText, all_devices, true);
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/HomeFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/HomeFragment.java
index 4ee232bee..f904dfadd 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/HomeFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/HomeFragment.java
@@ -1,5 +1,6 @@
package io.treehouses.remote.Fragments;
+import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
@@ -42,6 +43,7 @@
import io.treehouses.remote.pojo.NetworkProfile;
import io.treehouses.remote.utils.SaveUtils;
+import static android.widget.Toast.LENGTH_LONG;
import static io.treehouses.remote.Constants.REQUEST_ENABLE_BT;
@@ -55,7 +57,6 @@ public class HomeFragment extends BaseHomeFragment implements SetDisconnect {
private ExpandableListView network_profiles;
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- private BluetoothChatService mChatService = null;
private Button connectRpi, getStarted, testConnection;
private Boolean connectionState = false;
private Boolean result = false;
@@ -73,8 +74,8 @@ public class HomeFragment extends BaseHomeFragment implements SetDisconnect {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
View view = inflater.inflate(R.layout.activity_home_fragment, container, false);
- mChatService = listener.getChatService();
connectRpi = view.findViewById(R.id.btn_connect);
getStarted = view.findViewById(R.id.btn_getStarted);
preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
@@ -155,11 +156,10 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
}
- private void connectRpiListener() {
+ public void connectRpiListener() {
connectRpi.setOnClickListener(v -> {
if (connectionState) {
- RPIDialogFragment.getInstance().bluetoothCheck("unregister");
- mChatService.stop();
+ mChatService.disconnect();
connectionState = false;
checkConnectionState();
return;
@@ -181,7 +181,7 @@ public void testConnectionListener() {
List options = Arrays.asList(getResources().getStringArray(R.array.led_options));
String[] options_code = getResources().getStringArray(R.array.led_options_commands);
selected_LED = options.indexOf(preference);
- writeToRPI(options_code[selected_LED]);
+ mChatService.write(options_code[selected_LED]);
testConnectionDialog = showTestConnectionDialog(false, "Testing Connection...", R.string.test_connection_message, selected_LED);
testConnectionDialog.show();
result = false;
@@ -189,19 +189,18 @@ public void testConnectionListener() {
}
public void checkConnectionState() {
- mChatService = listener.getChatService();
if (mChatService.getState() == Constants.STATE_CONNECTED) {
+ mChatService.updateHandler(mHandler);
showLogDialog(preferences);
transitionOnConnected();
connectionState = true;
checkVersionSent = true;
- writeToRPI("treehouses remote version " + BuildConfig.VERSION_CODE + "\n");
+ mChatService.write("treehouses remote version " + BuildConfig.VERSION_CODE + "\n");
} else {
transitionDisconnected();
connectionState = false;
}
- mChatService.updateHandler(mHandler);
}
private void transitionOnConnected() {
@@ -236,10 +235,6 @@ private void dismissTestConnection() {
}
}
- private void writeToRPI(String ping) {
- mChatService.write(ping.getBytes());
- }
-
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
@@ -256,7 +251,7 @@ private void checkVersion(String output) {
showUpgradeCLI();
}
else if(BuildConfig.VERSION_CODE == 2 || output.contains("true")) {
- writeToRPI("treehouses remote check\n");
+ mChatService.write("treehouses remote check\n");
}
else if (output.contains("false")){
AlertDialog alertDialog = new AlertDialog.Builder(getContext())
@@ -291,7 +286,7 @@ private void readMessage(String output) {
internetSent = false;
if (output.trim().contains("true")) internetstatus.setImageDrawable(getResources().getDrawable(R.drawable.circle_green));
else internetstatus.setImageDrawable(getResources().getDrawable(R.drawable.circle));
- writeToRPI("treehouses upgrade --check\n");
+ mChatService.write("treehouses upgrade --check\n");
}
else {
moreActions(output);
@@ -319,10 +314,11 @@ private void moreActions(String output) {
}
}
+
/**
* The Handler that gets information back from the BluetoothChatService
*/
-
+ @SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -334,16 +330,19 @@ public void handleMessage(Message msg) {
readMessage(output);
}
break;
+ case Constants.MESSAGE_STATE_CHANGE:
+ checkConnectionState();
+ switch (msg.arg1) {
+ case Constants.STATE_CONNECTED:
+ Log.e("Home Fragment", "Bluetooth Connection Status Change: State Connected");
+ Toast.makeText(getContext(), "Bluetooth Connected", LENGTH_LONG).show();
+ break;
+ case Constants.STATE_NONE:
+ Log.e("RPIDialogFragment", "Bluetooth Connection Status Change: State None");
+ break;
+ }
+ break;
}
}
};
-
- @Override
- public void onResume() {
- super.onResume();
- if (mChatService.getState() == Constants.STATE_CONNECTED) {
- checkVersionSent = true;
- writeToRPI("treehouses remote version " + BuildConfig.VERSION_CODE + "\n");
- }
- }
}
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/NewNetworkFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/NewNetworkFragment.java
index 031166536..fc2af7463 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/NewNetworkFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/NewNetworkFragment.java
@@ -116,7 +116,7 @@ private void updateNetworkText(String mode) {
private void updateNetworkMode() {
String s = "treehouses networkmode";
- mChatService.write(s.getBytes());
+ mChatService.write(s);
Toast.makeText(getContext(), "Network Mode updated", Toast.LENGTH_LONG).show();
}
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/ServicesDetailsFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/ServicesDetailsFragment.java
index 79ba8dc07..afb748b47 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/ServicesDetailsFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/ServicesDetailsFragment.java
@@ -1,5 +1,6 @@
package io.treehouses.remote.Fragments;
+import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Handler;
@@ -72,7 +73,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
return view;
}
- final Handler handlerDetails = new Handler() {
+ @SuppressLint("HandlerLeak")
+ public final Handler handlerDetails = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -83,7 +85,8 @@ public void handleMessage(Message msg) {
break;
case Constants.MESSAGE_WRITE:
- String write_msg = new String((byte[]) msg.obj);
+ String write_msg = (String) msg.obj;
+ Log.d("WRITE", write_msg);
break;
}
}
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/ServicesFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/ServicesFragment.java
index 2adb93dad..d4e77689d 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/ServicesFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/ServicesFragment.java
@@ -62,7 +62,6 @@ public void onTabReselected(TabLayout.Tab tab) { }
mChatService = listener.getChatService();
mChatService.updateHandler(handler);
writeToRPI("treehouses remote allservices\n");
-
return view;
}
@@ -91,7 +90,7 @@ else if(a==0) {
}
break;
case Constants.MESSAGE_WRITE:
- String write_msg = new String((byte[]) msg.obj);
+ String write_msg = (String) msg.obj;
Log.d("WRITE", write_msg);
break;
}
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/ServicesTabFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/ServicesTabFragment.java
index 4eb073b2a..87744184f 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/ServicesTabFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/ServicesTabFragment.java
@@ -64,7 +64,7 @@ public void handleMessage(Message msg) {
moreAction(output);
break;
case Constants.MESSAGE_WRITE:
- String write_msg = new String((byte[]) msg.obj);
+ String write_msg = (String) msg.obj;
Log.d("WRITE", write_msg);
break;
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/StatusFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/StatusFragment.java
index 629f69eba..858ea70be 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/StatusFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/StatusFragment.java
@@ -1,5 +1,6 @@
package io.treehouses.remote.Fragments;
+import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
@@ -56,11 +57,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
if (mChatService.getState() == Constants.STATE_CONNECTED) {
btStatus.setImageDrawable(getResources().getDrawable(R.drawable.tick));
}
- checkStatusNow();
String ping = "hostname";
- byte[] pSend1 = ping.getBytes();
- mChatService.write(pSend1);
+ mChatService.write(ping);
return view;
}
@@ -114,7 +113,7 @@ private void updateStatus(String readMessage) {
rpiVersion = res[3];
writeToRPI("treehouses memory free");
} else if (lastCommand.equals("treehouses memory free")) {
- setCard(tvMemory, memoryStatus, "Memory: " + readMessage + "bytes available");
+ setCard(tvMemory, memoryStatus, "Memory: " + readMessage + " bytes available");
writeToRPI("treehouses internet");
} else if (lastCommand.equals("treehouses internet")) {
checkWifiStatus(readMessage);
@@ -137,8 +136,7 @@ private void checkWifiStatus(String readMessage) {
private void writeToRPI(String ping) {
lastCommand = ping;
- byte[] pSend = ping.getBytes();
- mChatService.write(pSend);
+ mChatService.write(ping);
}
private void setCard(TextView textView, ImageView tick, String text) {
@@ -157,11 +155,11 @@ private void checkUpgradeNow() {
}
private void checkUpgradeStatus(String readMessage) {
checkUpgradeNow();
- if (readMessage.startsWith("false ") && readMessage.length() < 14) {
+ if (readMessage.contains("false")) {
ivUpgrade.setImageDrawable(getResources().getDrawable(R.drawable.tick));
tvUpgrade.setText(String.format("Upgrade Status: Latest Version: %s", rpiVersion));
upgrade.setVisibility(View.GONE);
- } else if (readMessage.startsWith("true ") && readMessage.length() < 14){
+ } else if (readMessage.contains("true")){
ivUpgrade.setImageDrawable(getResources().getDrawable(R.drawable.tick_png));
tvUpgrade.setText(String.format("Upgrade available from %s to %s", rpiVersion, readMessage.substring(4)));
upgrade.setVisibility(View.VISIBLE);
@@ -205,16 +203,16 @@ public void onAttach(@NonNull Context context) {
/**
* The Handler that gets information back from the BluetoothChatService
*/
+ @SuppressLint("HandlerLeak")
public final Handler mHandler = new Handler() {
+ @SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
- checkStatusNow();
break;
case Constants.MESSAGE_WRITE:
- byte[] writeBuf = (byte[]) msg.obj;
- String writeMessage = new String(writeBuf);
+ String writeMessage = (String) msg.obj;
Log.d(TAG, "writeMessage = " + writeMessage);
break;
case Constants.MESSAGE_READ:
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/TerminalFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/TerminalFragment.java
index e4215acbd..c255fdfe1 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/TerminalFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/TerminalFragment.java
@@ -136,7 +136,7 @@ public void onDestroy() {
// not enabled during onStart(), so we were paused to enable it...
// onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
if (mChatService != null && mChatService.getState() == Constants.STATE_NONE) {
- mChatService.start();
+// mChatService.start();
idle(mPingStatus, pingStatusButton);
}
}
@@ -248,26 +248,18 @@ private void onResultCaseDialogChpass(int resultCode, Intent data) {
}
}
- private void buildJSON() {
+ private void buildJSON(String s) {
try {
- JSONObject jsonObject = new JSONObject(jsonString);
+ JSONObject jsonObject = new JSONObject(s);
commands = new Gson().fromJson(jsonObject.toString(), CommandsList.class);
if (commands != null) updateArrayAdapters(commands);
} catch (JSONException e) { e.printStackTrace(); }
}
private void handleJson(String readMessage) {
- if (jsonReceiving) {
- jsonString += readMessage.trim();
- if (jsonString.endsWith("]}")) {
- jsonString += readMessage.trim();
- buildJSON();
- jsonReceiving = false;
- jsonSent = false;
- }
- } else if (readMessage.startsWith("{")) {
- jsonReceiving = true;
- jsonString = readMessage.trim();
+ if (readMessage.startsWith("{")) {
+ buildJSON(readMessage);
+ jsonSent = false;
}
}
@@ -294,9 +286,6 @@ public void handleMessage(Message msg) {
else { handlerCaseRead(readMessage, mPingStatus, pingStatusButton);
filterMessages(readMessage, mConversationArrayAdapter, MainApplication.getTerminalList()); }
break;
- case Constants.MESSAGE_DEVICE_NAME:
- handlerCaseName(msg, getActivity());
- break;
case Constants.MESSAGE_TOAST:
handlerCaseToast(msg);
break;
diff --git a/app/src/main/java/io/treehouses/remote/Fragments/TunnelFragment.java b/app/src/main/java/io/treehouses/remote/Fragments/TunnelFragment.java
index 70f8bac4d..3f1f8139c 100644
--- a/app/src/main/java/io/treehouses/remote/Fragments/TunnelFragment.java
+++ b/app/src/main/java/io/treehouses/remote/Fragments/TunnelFragment.java
@@ -94,10 +94,6 @@ public void setupChat() {
mConversationView.setAdapter(mConversationArrayAdapter);
- // Initialize the BluetoothChatService to perform bluetooth connections
- if (mChatService.getState() == Constants.STATE_NONE) {
- mChatService = new BluetoothChatService(mHandler, getActivity().getApplicationContext());
- }
// Initialize the buffer for outgoing messages
new StringBuilder();
}
@@ -125,17 +121,10 @@ private void onSwitchChecked() {
private void configConditions(String readMessage) {
if (readMessage.trim().contains("Error")) {
- try {
- listener.sendMessage("treehouses tor start");
- Thread.sleep(300);
- listener.sendMessage("treehouses tor add 80");
- Thread.sleep(300);
- listener.sendMessage("treehouses tor add 22");
- Thread.sleep(300);
- listener.sendMessage("treehouses tor add 2200");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ listener.sendMessage("treehouses tor start\n");
+ listener.sendMessage("treehouses tor add 80\n");
+ listener.sendMessage("treehouses tor add 22\n");
+ listener.sendMessage("treehouses tor add 2200\n");
}
}
@@ -158,10 +147,6 @@ public void handleMessage(Message msg) {
handlerCaseRead(readMessage, mPingStatus, pingStatusButton);
filterMessages(readMessage, mConversationArrayAdapter, MainApplication.getTunnelList());
break;
- case Constants.MESSAGE_DEVICE_NAME:
- Activity activity = getActivity();
- handlerCaseName(msg, activity);
- break;
case Constants.MESSAGE_TOAST:
handlerCaseToast(msg);
break;
diff --git a/app/src/main/java/io/treehouses/remote/InitialActivity.java b/app/src/main/java/io/treehouses/remote/InitialActivity.java
index 196644094..3f46ead04 100644
--- a/app/src/main/java/io/treehouses/remote/InitialActivity.java
+++ b/app/src/main/java/io/treehouses/remote/InitialActivity.java
@@ -1,6 +1,7 @@
package io.treehouses.remote;
import android.Manifest;
+import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
@@ -48,9 +49,9 @@ public class InitialActivity extends PermissionActivity
private static InitialActivity instance = null;
private Boolean validBluetoothConnection = false;
int REQUEST_COARSE_LOCATION = 99;
- private static BluetoothChatService mChatService = null;
private String mConnectedDeviceName = null;
private NavigationView navigationView;
+ private BluetoothChatService mChatService;
DrawerLayout drawer;
private String TAG = "InitialActivity";
@@ -65,16 +66,10 @@ protected void onCreate(Bundle savedInstanceState) {
setSupportActionBar(toolbar);
drawer = findViewById(R.id.drawer_layout);
-
+ mChatService = getChatService();
checkLocationPermission();
-
- if (mChatService == (null)) {
- Log.e(TAG, "mChatService Status: NULL");
- mChatService = new BluetoothChatService(mHandler, getApplicationContext());
- } else {
- Log.e(TAG, "mChatService Status: " + mChatService.getState());
- mChatService.updateHandler(mHandler);
- }
+ Log.e(TAG, "mChatService Status: " + mChatService.getState());
+ mChatService.updateHandler(mHandler);
checkStatusNow();
@@ -90,6 +85,7 @@ protected void onCreate(Bundle savedInstanceState) {
new GPSService(this);
}
+
public static InitialActivity getInstance() {
return instance;
}
@@ -204,17 +200,9 @@ protected void onActivityResult(int requestCode, int resultCode, @Nullable Inten
mChatService.updateHandler(mHandler);
}
-
- @Override
- public void setChatService(BluetoothChatService chatService) {
- mChatService = chatService;
- mChatService.updateHandler(mHandler);
- checkStatusNow();
- }
-
@Override
public BluetoothChatService getChatService() {
- return mChatService;
+ return ((MainApplication)this.getApplicationContext()).mChatService;
}
private void checkStatusNow() {
@@ -271,17 +259,14 @@ public void sendMessage(String message) {
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
- byte[] send = message.getBytes();
- mChatService.write(send);
-
- // Reset out string buffer to zero and clear the edit text field
-// mOutStringBuffer.setLength(0);
+ mChatService.write(message);
}
}
/**
* The Handler that gets information back from the BluetoothChatService
*/
+ @SuppressLint("HandlerLeak")
public final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -291,14 +276,18 @@ public void handleMessage(Message msg) {
case Constants.MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
- if (!mConnectedDeviceName.equals("") || mConnectedDeviceName != null) {
- Log.e("DEVICE", "" + mConnectedDeviceName);
- checkStatusNow();
- }
+ Log.e("DEVICE", "" + mConnectedDeviceName);
+ checkStatusNow();
+
break;
}
}
};
-
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ Log.e(TAG, "onDestroy: "+"DESTROYED");
+ mChatService.disconnect();
+ }
}
diff --git a/app/src/main/java/io/treehouses/remote/MainApplication.java b/app/src/main/java/io/treehouses/remote/MainApplication.java
index c57537e0c..b69ffdf1f 100644
--- a/app/src/main/java/io/treehouses/remote/MainApplication.java
+++ b/app/src/main/java/io/treehouses/remote/MainApplication.java
@@ -6,6 +6,7 @@
import java.util.ArrayList;
+import io.treehouses.remote.Network.BluetoothChatService;
import io.treehouses.remote.utils.SaveUtils;
public class MainApplication extends Application {
@@ -13,9 +14,12 @@ public class MainApplication extends Application {
private static ArrayList terminalList, tunnelList, commandList;
public static boolean showLogDialog = true;
public static boolean ratingDialog = true;
+
+ public BluetoothChatService mChatService;
@Override
public void onCreate() {
super.onCreate();
+ mChatService = new BluetoothChatService(null, getApplicationContext());
terminalList = new ArrayList();
tunnelList = new ArrayList();
commandList = new ArrayList();
diff --git a/app/src/main/java/io/treehouses/remote/Network/BluetoothChatService.java b/app/src/main/java/io/treehouses/remote/Network/BluetoothChatService.java
index 04fd5e269..545ad26fa 100644
--- a/app/src/main/java/io/treehouses/remote/Network/BluetoothChatService.java
+++ b/app/src/main/java/io/treehouses/remote/Network/BluetoothChatService.java
@@ -26,21 +26,31 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Bundle;
import android.os.Handler;
-import android.os.Message;
import android.util.Log;
-import androidx.preference.PreferenceManager;
+import com.github.ivbaranov.rxbluetooth.BluetoothConnection;
+import com.github.ivbaranov.rxbluetooth.RxBluetooth;
+
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
import java.util.UUID;
+import io.reactivex.FlowableOperator;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
+
import io.treehouses.remote.Constants;
+import io.treehouses.remote.callback.BluetoothDeviceCallback;
/**
* This class does all the work for setting up and managing Bluetooth
@@ -50,35 +60,31 @@
*/
public class BluetoothChatService implements Serializable{
-
// Debugging
private static final String TAG = "BluetoothChatService";
-
// Name for the SDP record when creating server socket
private static final String NAME_SECURE = "BluetoothChatSecure";
- //private static final String NAME_INSECURE = "BluetoothChatInsecure";
// well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB
- private static final UUID MY_UUID_SECURE =
- UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
+ private static final UUID MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
+ private CompositeDisposable compositeDisposable;
+ private BluetoothConnection bluetoothConnection;
+
- //private static final UUID MY_UUID_INSECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static String connectedDeviceName = "NULL";
// Member fields
- private final BluetoothAdapter mAdapter;
private BluetoothDevice mDevice;
private static Handler mHandler;
-// private AcceptThread mSecureAcceptThread;
- //private AcceptThread mInsecureAcceptThread;
- private ConnectThread mConnectThread;
- private ConnectedThread mConnectedThread;
+
private int mCurrentState;
- private int mNewState;
- private boolean bNoReconnect;
+ private RxBluetooth bluetooth;
private Context context;
-// private BluetoothSocket socket = null;
+ private Queue sentCommands;
+ private boolean switchedHandler = false;
+ private Handler tempHandler;
+ private Queue tempToSendCommands;
/**
* Constructor. Prepares a new BluetoothChat session.
*
@@ -86,499 +92,175 @@ public class BluetoothChatService implements Serializable{
* @param handler A Handler to send messages back to the UI Activity
*/
public BluetoothChatService(Handler handler, Context applicationContext) {
- mAdapter = BluetoothAdapter.getDefaultAdapter();
- mCurrentState = Constants.STATE_NONE;
- mNewState = mCurrentState;
- mHandler = handler;
this.context = applicationContext;
+ init();
+ }
+ private void init() {
+ compositeDisposable = new CompositeDisposable();
+ mCurrentState = Constants.STATE_NONE;
+ mHandler = null;
+ sentCommands = new LinkedList<>();
+ tempToSendCommands = new LinkedList<>();
+ bluetooth = new RxBluetooth(context);
}
- public void updateHandler(Handler handler){
- mHandler = handler;
+ public void updateHandler(Handler handler, boolean... args){
+ Log.e(TAG, "updateHandler:");
+ if (!sentCommands.isEmpty() && mCurrentState == Constants.STATE_CONNECTED) {
+ Log.e(TAG, "updateHandler: with overflow");
+ switchedHandler = true;
+ tempHandler = handler;
+ tempToSendCommands.clear();
+ } else {
+ Log.e(TAG, "updateHandler: without overflow");
+ mHandler = handler;
+ }
}
- /**
- * Update UI title according to the current state of the chat connection
- */
- private synchronized void updateUserInterfaceTitle() {
- mCurrentState = getState();
- Log.d(TAG, "updateUserInterfaceTitle() " + mNewState + " -> " + mCurrentState);
- mNewState = mCurrentState;
+ private synchronized void updateUserInterfaceTitle() {
+ Log.d(TAG, "updateUserInterfaceTitle() " + " -> " + mCurrentState);
// Give the new state to the Handler so the UI Activity can update
- mHandler.sendMessage(mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, mNewState, -1));
+ mHandler.sendMessage(mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, mCurrentState, -1));
}
- /**
- * Return the current connection state.
- */
public synchronized int getState() {
return mCurrentState;
}
- public String getConnectedDeviceName(){return connectedDeviceName;}
- /**
- * Start the chat service. Specifically start AcceptThread to begin a
- * session in listening (server) mode. Called by the Activity onResume()
- */
- public synchronized void start() {
- Log.d(TAG, "start");
- bNoReconnect = false;
- // Cancel any thread attempting to make a connection
- if (mConnectThread != null) {
- mConnectThread.cancel();
- mConnectThread = null;
- }
-
- // Cancel any thread currently running a connection
- if (mConnectedThread != null) {
- mConnectedThread.cancel();
- mConnectedThread = null;
- }
-
- // Start the thread to listen on a BluetoothServerSocket
-// if (mSecureAcceptThread == null) {
-// mSecureAcceptThread = new AcceptThread(true);
-// mSecureAcceptThread.start();
-// }
-// if (mInsecureAcceptThread == null) {
-// mInsecureAcceptThread = new AcceptThread(false);
-// mInsecureAcceptThread.start();
-// }
- // Update UI title
- updateUserInterfaceTitle();
+ public String getConnectedDeviceName(){
+ if (mDevice != null) return mDevice.getName();
+ return "NO DEVICE CONNECTED";
}
- /**
- * Start the ConnectThread to initiate a connection to a remote device.
- *
- * @param device The BluetoothDevice to connect
- * @param secure Socket Security type - Secure (true) , Insecure (false)
- */
- public synchronized void connect(BluetoothDevice device, boolean secure) {
- Log.d(TAG, "connect to: " + device);
-
- // Cancel any thread attempting to make a connection
- if (mCurrentState == Constants.STATE_CONNECTING) {
- if (mConnectThread != null) {
- mConnectThread.cancel();
- mConnectThread = null;
- }
- }
-
- // Cancel any thread currently running a connection
- if (mConnectedThread != null) {
- mConnectedThread.cancel();
- mConnectedThread = null;
- }
-
- // Start the thread to connect with the given device
- mConnectThread = new ConnectThread(device, secure);
- mConnectThread.start();
- // Update UI title
- updateUserInterfaceTitle();
+ public void connectToDevice(BluetoothDevice device) {
+ stopDiscovery();
+ mCurrentState = Constants.STATE_CONNECTING;
+ compositeDisposable.add(bluetooth.connectAsClient(device, MY_UUID_SECURE).subscribeOn(Schedulers.computation()).subscribe(
+ bluetoothSocket -> {
+ Log.e(TAG, "connectToDevice: CONNECTED to " + device.getName());
+ mDevice = device;
+ mCurrentState = Constants.STATE_CONNECTED;
+ bluetooth.cancelDiscovery();
+ updateUserInterfaceTitle();
+ compositeDisposable.clear();
+ startChat(bluetoothSocket);
+ }, throwable -> {
+ Log.e(TAG, "connectToDevice: FAILED TO CONNECT");
+ mCurrentState = Constants.STATE_FAILED;
+ updateUserInterfaceTitle();
+ init();
+ }));
}
- /**
- * Start the ConnectedThread to begin managing a Bluetooth connection
- *
- * @param socket The BluetoothSocket on which the connection was made
- * @param device The BluetoothDevice that has been connected
- */
- public synchronized void connected(BluetoothSocket socket, BluetoothDevice
- device, final String socketType) {
- Log.d(TAG, "connected, Socket Type:" + socketType);
- connectedDeviceName = device.getName();
- mDevice = device;
- // Cancel the thread that completed the connection
- if (mConnectThread != null) {
- mConnectThread.cancel();
- mConnectThread = null;
- }
-
- // Cancel any thread currently running a connection
- if (mConnectedThread != null) {
- mConnectedThread.cancel();
- mConnectedThread = null;
- }
-
- // Cancel the accept thread because we only want to connect to one device
-// if (mSecureAcceptThread != null) {
-// mSecureAcceptThread.cancel();
-// mSecureAcceptThread = null;
-// }
-// if (mInsecureAcceptThread != null) {
-// mInsecureAcceptThread.cancel();
-// mInsecureAcceptThread = null;
-// }
-
- // Start the thread to manage the connection and perform transmissions
- mConnectedThread = new ConnectedThread(socket, socketType);
- mConnectedThread.start();
-
- // Send the name of the connected device back to the UI Activity
-
- updateUserInterfaceTitle();
-
- Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
- Bundle bundle = new Bundle();
- bundle.putString(Constants.DEVICE_NAME, device.getName());
- msg.setData(bundle);
- mHandler.sendMessage(msg);
- // Update UI title
- Log.e(TAG,"Connected");
+ private void startChat(BluetoothSocket socket) throws Exception {
+ Log.e(TAG, "startChat: "+"START READING" );
+ bluetoothConnection = new BluetoothConnection(socket);
+
+ compositeDisposable.add(bluetoothConnection.observeByteStream().lift((FlowableOperator) this::getWriter).onBackpressureBuffer().observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io())
+ .subscribe(s -> {
+ // READ COMMAND RESPONSE
+ Log.d(TAG, "READ: " + s);
+ //Remove the last command because response has been received
+ if (!sentCommands.isEmpty()) sentCommands.remove();
+ //Send the response to the target
+ if (!switchedHandler) mHandler.obtainMessage(Constants.MESSAGE_READ, s).sendToTarget();
+
+ //Sent all the waiting commands
+ if (switchedHandler && sentCommands.isEmpty()) {
+ Log.e(TAG, "SENT ALL PREVIOUS");
+ switchedHandler = false;
+ mHandler = tempHandler;
+ writeOverflow();
+ }
+
+ }, throwable -> {
+ Log.e(TAG, "startChat: "+ "ERROR OCCURRED WHILE READING");
+ mCurrentState = Constants.STATE_FAILED;
+ updateUserInterfaceTitle();
+ disconnect();
+ }));
}
- /**
- * Stop all threads
- */
- public synchronized void stop() {
- Log.d(TAG, "stop");
- bNoReconnect = true;
- if (mConnectThread != null) {
- mConnectThread.cancel();
- mConnectThread = null;
+ private void writeOverflow() {
+ while (!tempToSendCommands.isEmpty()) {
+ write(tempToSendCommands.remove());
}
+ }
- if (mConnectedThread != null) {
- mConnectedThread.cancel();
- mConnectedThread = null;
+ public void disconnect() {
+ Log.e(TAG, "DISCONNECTING");
+ if (bluetoothConnection != null) {
+ bluetoothConnection.closeConnection();
+ bluetoothConnection = null;
+ mDevice = null;
}
-
-// if (mSecureAcceptThread != null) {
-// mSecureAcceptThread.cancel();
-// mSecureAcceptThread = null;
-// }
-
-// if (mInsecureAcceptThread != null) {
-// mInsecureAcceptThread.cancel();
-// mInsecureAcceptThread = null;
-// }
mCurrentState = Constants.STATE_NONE;
- // Update UI title
updateUserInterfaceTitle();
+ destroy();
+ init();
}
- /**
- * Write to the ConnectedThread in an unsynchronized manner
- *
- * @param out The bytes to write
- * @see ConnectedThread#write(byte[])
- */
- public void write(byte[] out) {
- // Create temporary object
- Log.d(TAG, "write: " + new String(out));
- ConnectedThread r;
- // Synchronize a copy of the ConnectedThread
- synchronized (this) {
- if (mCurrentState != Constants.STATE_CONNECTED) return;
- r = mConnectedThread;
- }
- // Perform the write unsynchronized
- r.write(out);
- }
-
- /**
- * Indicate that the connection attempt failed and notify the UI Activity.
- */
- private void connectionFailed() {
- // Send a failure message back to the Activity
- callHandler("Unable to connect to device");
-
- mCurrentState = Constants.STATE_NONE;
- // Update UI title
+ public void startDiscovery(BluetoothDeviceCallback callback) {
+ Log.e(TAG, "STARTING DISCOVERY");
+ if (bluetooth.isDiscovering()) bluetooth.cancelDiscovery();
+ bluetooth.startDiscovery();
+ mCurrentState = Constants.STATE_LISTEN;
updateUserInterfaceTitle();
-
- // Start the service over to restart listening mode
- BluetoothChatService.this.start();
+ compositeDisposable.add(bluetooth.observeDevices()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribeOn(Schedulers.io())
+ .subscribe(bluetoothDevice -> {
+ callback.onDeviceFound(bluetoothDevice);
+ Log.e(TAG, "DEVICE FOUND: "+ bluetoothDevice.getName()+ " ADDRESS: " + bluetoothDevice.getAddress());
+ }));
}
- /**
- * Indicate that the connection was lost and notify the UI Activity.
- */
- private void connectionLost() {
- // Send a failure message back to the Activity
- callHandler("Device connection was lost");
- SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
- Log.d(TAG, "connectionLost: ");
- if (mDevice != null && !bNoReconnect && preferences.getBoolean("reconnectBluetooth", true)) {
- BluetoothChatService.this.connect(mDevice, true);
- } else {
- mCurrentState = Constants.STATE_NONE;
- // Update UI title
- updateUserInterfaceTitle();
- // Start the service over to restart listening mode
- BluetoothChatService.this.start();
- }
+ public void stopDiscovery() {
+ bluetooth.cancelDiscovery();
}
- public void callHandler(String message) {
- Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
- Bundle bundle = new Bundle();
- bundle.putString(Constants.TOAST, message);
- msg.setData(bundle);
- mHandler.sendMessage(msg);
+ public Set getPairedDevices() {
+ return bluetooth.getBondedDevices();
}
- /**
- * This thread runs while listening for incoming connections. It behaves
- * like a server-side client. It runs until a connection is accepted
- * (or until cancelled).
- */
- // Uncomment this if phone needs to be able to accept connections from other devices
-// private class AcceptThread extends Thread {
-// // The local server socket
-// private final BluetoothServerSocket mmServerSocket;
-// private String mSocketType;
-//
-// public AcceptThread(boolean secure) {
-// BluetoothServerSocket tmp = null;
-// mSocketType = secure ? "Secure" : "Insecure";
-//
-// // Create a new listening server socket
-// try {
-//// if (secure) {
-// tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE);
-//// } else {
-//// tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, MY_UUID_INSECURE);
-//// }
-// } catch (Exception e) {
-// Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
-// }
-// mmServerSocket = tmp;
-// mCurrentState = Constants.STATE_LISTEN;
-// }
-//
-// @Override
-// public void run() {
-// Log.d(TAG, "Socket Type: " + mSocketType + "BEGIN mAcceptThread" + this);
-// setName("AcceptThread" + mSocketType);
-//
-// // Listen to the server socket if we're not connected
-// while (mCurrentState != Constants.STATE_CONNECTED) {
-// try {
-// // This is a blocking call and will only return on a successful connection or an exception
-// Log.e("TAG", "currentState: " + mCurrentState);
-//
-// socket = mmServerSocket.accept();
-// } catch (Exception e) {
-// Log.e(TAG, "Socket Type: " + mSocketType + " accept() failed" + e);
-// mCurrentState = Constants.STATE_NONE;
-// updateUserInterfaceTitle();
-// checkConnection("connectionCheck");
-// break;
-// }
-//
-// // If a connection was accepted
-// if (socket != null) {
-// synchronized (BluetoothChatService.this) {
-// switch (mCurrentState) {
-// case Constants.STATE_LISTEN:
-// case Constants.STATE_CONNECTING:
-// // Situation normal. Start the connected thread.
-// connected(socket, socket.getRemoteDevice(), mSocketType);
-// break;
-// case Constants.STATE_NONE:
-// case Constants.STATE_CONNECTED:
-// // Either not ready or already connected. Terminate new socket.
-// try {
-// mmServerSocket.close();
-// HomeFragment homeFragment = new HomeFragment();
-// homeFragment.checkConnectionState();
-// } catch (IOException e) {
-// Log.e(TAG, "Could not close unwanted socket", e);
-// }
-// break;
-// }
-// }
-// }
-// }
-// Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);
-//
-// }
-//
-// public void cancel() {
-// Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
-// try {
-// mmServerSocket.close();
-// } catch (IOException e) {
-// Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
-// }
-// }
-// }
-//
-// private void checkConnection(String message) {
-// mCurrentState = getState();
-// if (mCurrentState == Constants.STATE_CONNECTED) {
-// Message msg = mHandler.obtainMessage(Constants.MESSAGE_READ);
-// Bundle bundle = new Bundle();
-// bundle.putString(Constants.TOAST, message);
-// msg.setData(bundle);
-// RPIDialogFragment rpiDialogFragment = new RPIDialogFragment();
-// rpiDialogFragment.getmHandler().handleMessage(msg);
-// }
-// }
-
- /**
- * This thread runs while attempting to make an outgoing connection
- * with a device. It runs straight through; the connection either
- * succeeds or fails.
- */
- private class ConnectThread extends Thread {
- private final BluetoothSocket mmSocket;
- private final BluetoothDevice mmDevice;
- private String mSocketType;
-
- public ConnectThread(BluetoothDevice device, boolean secure) {
- mmDevice = device;
- BluetoothSocket tmp = null;
- mSocketType = secure ? "Secure" : "Insecure";
-
- // Get a BluetoothSocket for a connection with the
- // given BluetoothDevice
- try {
-// if (secure) {
- tmp = device.createRfcommSocketToServiceRecord(
- MY_UUID_SECURE);
-// } else {
-// tmp = device.createInsecureRfcommSocketToServiceRecord(
-// MY_UUID_INSECURE);
-// }
- mCurrentState = Constants.STATE_CONNECTING;
- } catch (IOException e) {
- Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
- mCurrentState = Constants.STATE_NONE;
- }
- mmSocket = tmp;
-
- }
-
- public void run() {
- Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
- setName("ConnectThread" + mSocketType);
-
- // Always cancel discovery because it will slow down a connection
- mAdapter.cancelDiscovery();
-
- // Make a connection to the BluetoothSocket
- try {
- // This is a blocking call and will only return on a
- // successful connection or an exception
- mmSocket.connect();
- } catch (IOException e) {
- // Close the socket
- try {
- mmSocket.close();
- } catch (IOException e2) {
- Log.e(TAG, "unable to close() " + mSocketType +
- " socket during connection failure", e2);
- }
- connectionFailed();
- return;
- }
-
- // Reset the ConnectThread because we're done
- synchronized (BluetoothChatService.this) {
- mConnectThread = null;
- }
-
- // Start the connected thread
- connected(mmSocket, mmDevice, mSocketType);
- }
-
- public void cancel() {
- try {
- mmSocket.close();
- } catch (IOException e) {
- Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
- }
- }
+ public boolean isBluetoothSupported() {
+ return bluetooth.isBluetoothAvailable();
}
- /**
- * This thread runs during a connection with a remote device.
- * It handles all incoming and outgoing transmissions.
- */
- private class ConnectedThread extends Thread {
- private final BluetoothSocket mmSocket;
- private final InputStream mmInStream;
- private final OutputStream mmOutStream;
-
- public ConnectedThread(BluetoothSocket socket, String socketType) {
- Log.d(TAG, "create ConnectedThread: " + socketType);
- mmSocket = socket;
- InputStream tmpIn = null;
- OutputStream tmpOut = null;
-
- // Get the BluetoothSocket input and output streams
- try {
- tmpIn = socket.getInputStream();
- Log.d(TAG, " tmpIn = " + tmpIn);
- tmpOut = socket.getOutputStream();
- Log.d(TAG, " tmpOut = " + tmpOut);
- } catch (IOException e) {
- Log.e(TAG, "temp sockets not created", e);
- }
-
- mmInStream = tmpIn;
- mmOutStream = tmpOut;
- mCurrentState = Constants.STATE_CONNECTED;
- }
-
- public void run() {
- Log.i(TAG, "BEGIN mConnectedThread");
- byte[] buffer = new byte[10000];
- int bytes;
- String out;
-
- // Keep listening to the InputStream while connected
- while (true) {
- try {
- // Read from the InputStream
- bytes = mmInStream.read(buffer);
- out = new String(buffer, 0, bytes);
- Log.d(TAG, "out = " + out + "size of out = " + out.length() + ", bytes = " + bytes);
- mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, out)
- .sendToTarget();
-// mEmulatorView.write(buffer, bytes);
- // Send the obtained bytes to the UI Activity
- //mHandler.obtainMessage(BlueTerm.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
- } catch (IOException e) {
- Log.e(TAG, "disconnected", e);
- connectionLost();
- break;
- }
- }
+ public boolean isBluetoothEnabled() {
+ return bluetooth.isBluetoothEnabled();
+ }
+ private void destroy() {
+ Log.e(TAG, "DESTROYING");
+ if (bluetooth != null) {
+ bluetooth.cancelDiscovery();
}
+ compositeDisposable.clear();
+ mCurrentState = Constants.STATE_NONE;
+ }
- /**
- * Write to the connected OutStream.
- *
- * @param buffer The bytes to write
- */
- public void write(byte[] buffer) {
- try {
- Log.d(TAG, "write: I am in inside write method");
- mmOutStream.write(buffer);
-
- // Share the sent message back to the UI Activity
- mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
- .sendToTarget();
- } catch (IOException e) {
- Log.e(TAG, "Exception during write", e);
- Log.d(TAG, "write: i am in inside write method exception");
+ public void write(String message) {
+ if (bluetoothConnection != null) {
+
+ Log.d(TAG, "write: " + message);
+ if (switchedHandler) {
+ Log.e(TAG, "WRITING TO TEMP: "+message);
+ tempToSendCommands.add(message);
+ } else {
+ Log.e(TAG, "SENDING TO BLUETOOTH: "+message);
+ sentCommands.add(message);
+ bluetoothConnection.send(message);
}
+ mHandler.obtainMessage(Constants.MESSAGE_WRITE, message).sendToTarget();
+ } else {
+ Log.e(TAG, "Error while writing to bluetooth");
}
+ }
- public void cancel() {
- try {
- mmSocket.close();
- } catch (IOException e) {
- Log.e(TAG, "close() of connect socket failed", e);
- }
- }
+ private Subscriber getWriter(Subscriber subscriber) {
+ return new MyWriter(subscriber);
}
-
}
diff --git a/app/src/main/java/io/treehouses/remote/Network/MyWriter.java b/app/src/main/java/io/treehouses/remote/Network/MyWriter.java
new file mode 100644
index 000000000..994e8258c
--- /dev/null
+++ b/app/src/main/java/io/treehouses/remote/Network/MyWriter.java
@@ -0,0 +1,52 @@
+package io.treehouses.remote.Network;
+
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+
+import java.util.ArrayList;
+
+public class MyWriter implements Subscriber {
+ ArrayList buffer = new ArrayList<>();
+ Subscriber subscriber;
+ private static int DELIMITER = '~';
+
+ public MyWriter(Subscriber subscriber) {
+ this.subscriber = subscriber;
+ }
+
+ @Override
+ public void onSubscribe(Subscription s) {
+ subscriber.onSubscribe(s);
+ }
+
+ @Override
+ public void onNext(Byte b) {
+ if (b == DELIMITER) emit();
+ else buffer.add(b);
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ if (!buffer.isEmpty()) emit();
+ subscriber.onError(t);
+ }
+
+ @Override
+ public void onComplete() {
+ if (!buffer.isEmpty()) emit();
+ subscriber.onComplete();
+ }
+
+ private void emit() {
+ if (buffer.isEmpty()) {
+ subscriber.onNext("");
+ return;
+ }
+
+ byte[] bArray = new byte[buffer.size()];
+
+ for (int i = 0; i < buffer.size(); i++) bArray[i] = buffer.get(i);
+ subscriber.onNext(new String(bArray));
+ buffer.clear();
+ }
+}
diff --git a/app/src/main/java/io/treehouses/remote/bases/BaseDialogFragment.java b/app/src/main/java/io/treehouses/remote/bases/BaseDialogFragment.java
index fd7bd1e5c..e49a6cc52 100644
--- a/app/src/main/java/io/treehouses/remote/bases/BaseDialogFragment.java
+++ b/app/src/main/java/io/treehouses/remote/bases/BaseDialogFragment.java
@@ -5,15 +5,21 @@
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
+import io.treehouses.remote.Network.BluetoothChatService;
import io.treehouses.remote.callback.HomeInteractListener;
public class BaseDialogFragment extends DialogFragment {
public HomeInteractListener listener;
+ public BluetoothChatService mChatService;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if (context instanceof HomeInteractListener)
listener = (HomeInteractListener) context;
+ else
+ throw new RuntimeException("Implement interface first");
+
+ mChatService = listener.getChatService();
}
}
diff --git a/app/src/main/java/io/treehouses/remote/bases/BaseFragment.java b/app/src/main/java/io/treehouses/remote/bases/BaseFragment.java
index 2e5d2c004..5da0a0465 100644
--- a/app/src/main/java/io/treehouses/remote/bases/BaseFragment.java
+++ b/app/src/main/java/io/treehouses/remote/bases/BaseFragment.java
@@ -14,8 +14,7 @@
import io.treehouses.remote.callback.HomeInteractListener;
public class BaseFragment extends Fragment {
- public BluetoothChatService mChatService = null;
- public BluetoothAdapter mBluetoothAdapter = null;
+ public BluetoothChatService mChatService;
public HomeInteractListener listener;
@@ -26,31 +25,28 @@ public void onAttach(@NonNull Context context) {
listener = (HomeInteractListener) context;
else
throw new RuntimeException("Implement interface first");
+
+ mChatService = listener.getChatService();
+
+ }
+
+ public void setupChat() {
+
}
protected void onLoad(Handler mHandler) {
mChatService = listener.getChatService();
mChatService.updateHandler(mHandler);
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
- if (mBluetoothAdapter == null) {
+ if (!mChatService.isBluetoothSupported()) {
Toast.makeText(getActivity(), "Bluetooth is not available", Toast.LENGTH_LONG).show();
getActivity().finish();
}
- checkStatusNow();
- if (!mBluetoothAdapter.isEnabled()) {
+ if (!mChatService.isBluetoothEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, Constants.REQUEST_ENABLE_BT);
- } else {
- setupChat();
}
}
- public void checkStatusNow() {
- }
-
- public void setupChat() {
- }
-
}
diff --git a/app/src/main/java/io/treehouses/remote/bases/BaseHomeFragment.java b/app/src/main/java/io/treehouses/remote/bases/BaseHomeFragment.java
index 2d0cbce2e..f95817248 100644
--- a/app/src/main/java/io/treehouses/remote/bases/BaseHomeFragment.java
+++ b/app/src/main/java/io/treehouses/remote/bases/BaseHomeFragment.java
@@ -164,7 +164,7 @@ protected void showRPIDialog(SetDisconnect s) {
androidx.fragment.app.DialogFragment dialogFrag = RPIDialogFragment.newInstance(123);
((RPIDialogFragment) dialogFrag).setCheckConnectionState(s);
dialogFrag.setTargetFragment(this, Constants.REQUEST_DIALOG_FRAGMENT_HOTSPOT);
- dialogFrag.show(getFragmentManager().beginTransaction(), "rpiDialog");
+ dialogFrag.show(getParentFragmentManager().beginTransaction(), "rpiDialog");
}
protected boolean matchResult(String output, String option1, String option2) { return output.contains(option1) || output.contains(option2); }
diff --git a/app/src/main/java/io/treehouses/remote/bases/BaseServicesFragment.java b/app/src/main/java/io/treehouses/remote/bases/BaseServicesFragment.java
index 3dd90aeea..d7838fe0f 100644
--- a/app/src/main/java/io/treehouses/remote/bases/BaseServicesFragment.java
+++ b/app/src/main/java/io/treehouses/remote/bases/BaseServicesFragment.java
@@ -23,8 +23,6 @@
public class BaseServicesFragment extends BaseFragment {
private static final int[] MINIMUM_VERSION = {1, 14, 1};
- private String startJson = "";
- private boolean gettingJSON = false;
protected ServicesData servicesData;
protected void openLocalURL(String url) {
@@ -61,7 +59,7 @@ protected boolean checkVersion(int[] versionIntNumber) {
return (versionIntNumber[0] == MINIMUM_VERSION[0]) && (versionIntNumber[1] == MINIMUM_VERSION[1]) && (versionIntNumber[2] >= MINIMUM_VERSION[2]);
}
protected void writeToRPI(String ping) {
- mChatService.write(ping.getBytes());
+ mChatService.write(ping);
}
protected void performService(String action, String command, String name) {
@@ -130,26 +128,14 @@ protected int performAction(String output, ArrayList services) {
if (isError(output)) {
i = 0;
}
- else if (gettingJSON) {
- startJson += output.trim();
- if (startJson.endsWith("}}")) {
- startJson += output.trim();
- try {
- JSONObject jsonObject = new JSONObject(startJson);
- servicesData = new Gson().fromJson(jsonObject.toString(), ServicesData.class);
- constructServiceList(servicesData, services);
-
- } catch (JSONException e) { e.printStackTrace(); }
- gettingJSON = false;
- }
- i = 1;
- }
- else if (output.trim().startsWith("{")) {
- Log.d("STARTED", "performAction: ");
- startJson = output.trim();
- gettingJSON = true;
+ else if (output.startsWith("{")) {
+ try{
+ JSONObject jsonObject = new JSONObject(output);
+ servicesData = new Gson().fromJson(jsonObject.toString(), ServicesData.class);
+ constructServiceList(servicesData, services);
+ i = 1;
+ } catch (JSONException e) { e.printStackTrace();i= 0;}
}
-
return i;
}
diff --git a/app/src/main/java/io/treehouses/remote/bases/BaseTerminalFragment.java b/app/src/main/java/io/treehouses/remote/bases/BaseTerminalFragment.java
index e9ec55edc..20064d83d 100644
--- a/app/src/main/java/io/treehouses/remote/bases/BaseTerminalFragment.java
+++ b/app/src/main/java/io/treehouses/remote/bases/BaseTerminalFragment.java
@@ -40,7 +40,7 @@ public class BaseTerminalFragment extends BaseFragment{
public String handlerCaseWrite(String TAG, ArrayAdapter mConversationArrayAdapter, Message msg) {
- byte[] writeBuf = (byte[]) msg.obj;
+ String writeBuf = (String) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
if (!writeMessage.contains("google.com") && !writeMessage.contains("remote")) {
@@ -50,14 +50,6 @@ public String handlerCaseWrite(String TAG, ArrayAdapter mConversationArr
return writeMessage;
}
- public void handlerCaseName(Message msg, Activity activity ) {
- // save the connected device's name
- String mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
- if (null != activity) {
- Toast.makeText(activity, "Connected to " + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
- }
- }
-
public void handlerCaseToast(Message msg) {
if (null != getActivity()) {
Toast.makeText(getActivity(), msg.getData().getString(Constants.TOAST), Toast.LENGTH_SHORT).show();
@@ -121,7 +113,7 @@ private boolean filterMessage(String readMessage) {
protected void filterMessages(String readMessage, ArrayAdapter mConversationArrayAdapter, ArrayList list) {
//make it so text doesn't show on chat (need a better way to check multiple strings since mConversationArrayAdapter only takes messages line by line)
- if (filterMessage(readMessage)) {
+ if (filterMessage(readMessage) && mConversationArrayAdapter != null) {
list.add(readMessage);
mConversationArrayAdapter.notifyDataSetChanged();
}
diff --git a/app/src/main/java/io/treehouses/remote/bases/PermissionActivity.java b/app/src/main/java/io/treehouses/remote/bases/PermissionActivity.java
index 3bf10e6db..258813acd 100644
--- a/app/src/main/java/io/treehouses/remote/bases/PermissionActivity.java
+++ b/app/src/main/java/io/treehouses/remote/bases/PermissionActivity.java
@@ -12,6 +12,9 @@
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
+import io.treehouses.remote.MainApplication;
+import io.treehouses.remote.Network.BluetoothChatService;
+
public abstract class PermissionActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_WIFI = 111;
private static final int PERMISSION_REQUEST_CODE_CAMERA = 112;
diff --git a/app/src/main/java/io/treehouses/remote/callback/BluetoothDeviceCallback.java b/app/src/main/java/io/treehouses/remote/callback/BluetoothDeviceCallback.java
new file mode 100644
index 000000000..4c3bd3b1d
--- /dev/null
+++ b/app/src/main/java/io/treehouses/remote/callback/BluetoothDeviceCallback.java
@@ -0,0 +1,7 @@
+package io.treehouses.remote.callback;
+
+import android.bluetooth.BluetoothDevice;
+
+public interface BluetoothDeviceCallback {
+ void onDeviceFound(BluetoothDevice bluetoothDevice);
+}
diff --git a/app/src/main/java/io/treehouses/remote/callback/HomeInteractListener.java b/app/src/main/java/io/treehouses/remote/callback/HomeInteractListener.java
index f28bac2f3..624e62584 100644
--- a/app/src/main/java/io/treehouses/remote/callback/HomeInteractListener.java
+++ b/app/src/main/java/io/treehouses/remote/callback/HomeInteractListener.java
@@ -9,5 +9,4 @@ public interface HomeInteractListener {
void openCallFragment(Fragment f);
// void updateHandler(Handler handler);
BluetoothChatService getChatService();
- void setChatService(BluetoothChatService service);
}
diff --git a/app/src/main/res/layout/activity_splash_screen.xml b/app/src/main/res/layout/activity_splash_screen.xml
index d18a98cbe..9cbae0f2c 100644
--- a/app/src/main/res/layout/activity_splash_screen.xml
+++ b/app/src/main/res/layout/activity_splash_screen.xml
@@ -1,7 +1,7 @@
-
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 70bd3176d..15a80e342 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -41,6 +41,10 @@
- @color/colorAccent
+