diff --git a/README.md b/README.md
index d7be67769..a7b8dd01c 100644
--- a/README.md
+++ b/README.md
@@ -16,8 +16,6 @@ Known Visible Issues:
* No special notifications, EVERYTHING will be send as a Chat/SMS message
* Notifications are not properly queued, if two arrive at about the same time,
one of them will get lost
-* Connection to Pebble will be reopened and closed for every message (dont know
- if this saves or consumes more energy)
* Android 4.4+ only, we can only change this by implementing an
AccessibiltyService. Don't know if it is worth the hassle.
* This will open the dialog to allow capturing notifications every time the
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9816dc3f3..c135f1631 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,10 +12,10 @@
android:label="@string/app_name"
android:theme="@style/AppTheme">
@@ -24,13 +24,15 @@
+
+
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java
new file mode 100644
index 000000000..605557ac1
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java
@@ -0,0 +1,166 @@
+package nodomain.freeyourgadget.gadgetbridge;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.ParcelUuid;
+import android.support.v4.app.NotificationCompat;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Set;
+
+public class BluetoothCommunicationService extends Service {
+ private static final String TAG = "BluetoothCommunicationService";
+
+ // TODO: put in separate static class
+ public static final String ACTION_STARTBLUETOOTHCOMMUNITCATIONSERVICE
+ = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.start";
+ public static final String ACTION_STOPBLUETOOTHCOMMUNITCATIONSERVICE
+ = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.stop";
+ public static final String ACTION_SENDBLUETOOTHMESSAGE
+ = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.sendbluetoothmessage";
+
+ private BluetoothAdapter mBtAdapter = null;
+ private String mBtDeviceAddress = null;
+ private BluetoothSocket mBtSocket = null;
+ private BtSocketIoThread mBtSocketIoThread = null;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent.getAction().equals(ACTION_STARTBLUETOOTHCOMMUNITCATIONSERVICE)) {
+ Intent notificationIntent = new Intent(this, ControlCenter.class);
+ notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+ notificationIntent, 0);
+
+ Notification notification = new NotificationCompat.Builder(this)
+ .setContentTitle("Gadgetbridge")
+ .setTicker("Gadgetbridge Running")
+ .setContentText("Gadgetbrige Running")
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setContentIntent(pendingIntent)
+ .setOngoing(true).build();
+
+
+ //Check the system status
+ mBtAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (mBtAdapter == null) {
+ Toast.makeText(this, "Bluetooth is not supported.", Toast.LENGTH_SHORT).show();
+ } else if (!mBtAdapter.isEnabled()) {
+ Toast.makeText(this, "Bluetooth is disabled.", Toast.LENGTH_SHORT).show();
+ } else {
+ Set pairedDevices = mBtAdapter.getBondedDevices();
+ for (BluetoothDevice device : pairedDevices) {
+ if (device.getName().indexOf("Pebble") == 0) {
+ // Matching device found
+ mBtDeviceAddress = device.getAddress();
+ }
+ }
+
+ try {
+ if (mBtSocket == null || !mBtSocket.isConnected()) {
+ BluetoothDevice btDevice = mBtAdapter.getRemoteDevice(mBtDeviceAddress);
+ ParcelUuid uuids[] = btDevice.getUuids();
+ mBtSocket = btDevice.createRfcommSocketToServiceRecord(uuids[0].getUuid());
+ mBtSocket.connect();
+ mBtSocketIoThread = new BtSocketIoThread(mBtSocket.getInputStream(), mBtSocket.getOutputStream());
+ mBtSocketIoThread.start();
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ startForeground(1, notification); //FIXME: don't hardcode id
+ }
+ } else if (intent.getAction().equals(ACTION_STOPBLUETOOTHCOMMUNITCATIONSERVICE)) {
+ try {
+ mBtSocketIoThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ try {
+ mBtSocket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ mBtSocket = null;
+ mBtSocketIoThread = null;
+
+ stopForeground(true);
+ stopSelf();
+ } else if (intent.getAction().equals(ACTION_SENDBLUETOOTHMESSAGE)) {
+ String title = intent.getStringExtra("notification_title");
+ String content = intent.getStringExtra("notification_content");
+ if (mBtSocketIoThread != null) {
+ byte[] msg;
+ msg = PebbleProtocol.encodeSMS(title, content);
+ mBtSocketIoThread.write(msg);
+ }
+ }
+ return START_STICKY;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private class BtSocketIoThread extends Thread {
+ private final InputStream mmInStream;
+ private final OutputStream mmOutStream;
+
+ public BtSocketIoThread(InputStream instream, OutputStream outstream) {
+ mmInStream = instream;
+ mmOutStream = outstream;
+ }
+
+ public void run() {
+ byte[] buffer = new byte[1000]; // buffer store for the stream
+ int bytes; // bytes returned from read()
+
+ while (true) {
+ try {
+ byte[] ping = {0, 0, 0, 0};
+ // Read from the InputStream
+ //bytes = mmInStream.read(buffer,0,2);
+ //ByteBuffer buf = ByteBuffer.wrap(buffer);
+ //buf.order(ByteOrder.BIG_ENDIAN);
+ //short length = buf.getShort();
+ //Log.e(TAG,Integer.toString(length+4) + " as total length");
+ bytes = mmInStream.read(buffer);
+ Log.e(TAG, Integer.toString(bytes) + ": " + PebbleProtocol.decodeResponse(buffer));
+ write(ping);
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ synchronized public void write(byte[] bytes) {
+ try {
+ mmOutStream.write(bytes);
+ mmOutStream.flush();
+ } catch (IOException e) {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
index b8a0923e3..eb5431606 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
@@ -1,16 +1,9 @@
package nodomain.freeyourgadget.gadgetbridge;
import android.app.NotificationManager;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothSocket;
-import android.content.BroadcastReceiver;
-import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
@@ -18,77 +11,48 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
-import android.widget.Toast;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Set;
import java.util.UUID;
public class ControlCenter extends ActionBarActivity {
// SPP Serial Device UUID
private static final UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
- BluetoothAdapter mBtAdapter;
- String mBtDeviceAddress = null;
- BluetoothSocket mBtSocket;
Button sendButton;
Button testNotificationButton;
+ Button startServiceButton;
EditText editTitle;
EditText editContent;
- private NotificationReceiver nReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controlcenter);
- //Check the system status
- mBtAdapter = BluetoothAdapter.getDefaultAdapter();
- if (mBtAdapter == null) {
- Toast.makeText(this, "Bluetooth is not supported.", Toast.LENGTH_SHORT).show();
- finish();
- return;
- }
- if (!mBtAdapter.isEnabled()) {
- Toast.makeText(this, "Bluetooth is disabled.", Toast.LENGTH_SHORT).show();
- finish();
- return;
- }
-
- Set pairedDevices = mBtAdapter.getBondedDevices();
- for (BluetoothDevice device : pairedDevices) {
- if (device.getName().indexOf("Pebble") == 0) {
- // Matching device found
- mBtDeviceAddress = device.getAddress();
- }
- }
editTitle = (EditText) findViewById(R.id.editTitle);
editContent = (EditText) findViewById(R.id.editContent);
+ startServiceButton = (Button) findViewById(R.id.startServiceButton);
+ startServiceButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent startIntent = new Intent(ControlCenter.this, BluetoothCommunicationService.class);
+ startIntent.setAction(BluetoothCommunicationService.ACTION_STARTBLUETOOTHCOMMUNITCATIONSERVICE);
+ startService(startIntent);
+ }
+ });
sendButton = (Button) findViewById(R.id.sendButton);
sendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
-
- if (!mBtAdapter.isEnabled() || mBtDeviceAddress == null)
- return;
- String title = editTitle.getText().toString();
- String content = editContent.getText().toString();
- try {
- if (mBtSocket == null || !mBtSocket.isConnected()) {
- BluetoothDevice btDevice = mBtAdapter.getRemoteDevice(mBtDeviceAddress);
- mBtSocket = btDevice.createRfcommSocketToServiceRecord(SERIAL_UUID);
- mBtSocket.connect();
- }
- ConnectedTask task = new ConnectedTask();
- task.execute(mBtSocket, title, content);
- } catch (IOException e) {
- e.printStackTrace();
- }
+ Intent startIntent = new Intent(ControlCenter.this, BluetoothCommunicationService.class);
+ startIntent.setAction(BluetoothCommunicationService.ACTION_SENDBLUETOOTHMESSAGE);
+ startIntent.putExtra("notification_title", editTitle.getText().toString());
+ startIntent.putExtra("notification_content", editTitle.getText().toString());
+ startService(startIntent);
}
});
+
testNotificationButton = (Button) findViewById(R.id.testNotificationButton);
testNotificationButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -100,11 +64,9 @@ public class ControlCenter extends ActionBarActivity {
Intent enableIntent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(enableIntent);
- nReceiver = new NotificationReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("nodomain.freeyourgadget.gadgetbridge.NOTIFICATION_LISTENER");
- registerReceiver(nReceiver, filter);
}
private void testNotification() {
@@ -112,7 +74,7 @@ public class ControlCenter extends ActionBarActivity {
NotificationCompat.Builder ncomp = new NotificationCompat.Builder(this);
ncomp.setContentTitle("Test Notification");
ncomp.setContentText("This is a Test Notification from Gadgetbridge");
- ncomp.setTicker("This is a Test Notificytion from Gadgetbridge");
+ ncomp.setTicker("This is a Test Notification from Gadgetbridge");
ncomp.setSmallIcon(R.drawable.ic_launcher);
ncomp.setAutoCancel(true);
nManager.notify((int) System.currentTimeMillis(), ncomp.build());
@@ -141,99 +103,4 @@ public class ControlCenter extends ActionBarActivity {
return super.onOptionsItemSelected(item);
}
-
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- try {
- if (mBtSocket != null) {
- mBtSocket.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (nReceiver != null) {
- unregisterReceiver(nReceiver);
- }
- }
-
-
- //AsyncTask to receive a single line of data and post
- private class ConnectedTask extends
- AsyncTask