diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a85e9fef4..fa4932240 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,17 +15,20 @@ android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/GadgetbridgeTheme"> - + android:label="@string/title_activity_controlcenter"> + + - @@ -88,7 +90,7 @@ + android:label="@string/title_activity_debug" /> diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AppManagerActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AppManagerActivity.java new file mode 100644 index 000000000..764aed0dc --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AppManagerActivity.java @@ -0,0 +1,69 @@ +package nodomain.freeyourgadget.gadgetbridge; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.widget.ListView; + +import java.util.ArrayList; +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAppAdapter; + + +public class AppManagerActivity extends Activity { + private final String TAG = this.getClass().getSimpleName(); + + public static final String ACTION_REFRESH_APPLIST + = "nodomain.freeyourgadget.gadgetbride.appmanager.action.refresh_applist"; + + ListView appListView; + GBDeviceAppAdapter mGBDeviceAppAdapter; + final List appList = new ArrayList<>(); + + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(ControlCenter.ACTION_QUIT)) { + finish(); + } else if (action.equals(ACTION_REFRESH_APPLIST)) { + int appCount = intent.getIntExtra("app_count", 0); + for (Integer i = 0; i < appCount; i++) { + String appName = intent.getStringExtra("app_name" + i.toString()); + String appCreator = intent.getStringExtra("app_creator" + i.toString()); + appList.add(new GBDeviceApp(appName, appCreator, "")); + } + mGBDeviceAppAdapter.notifyDataSetChanged(); + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_appmanager); + + appListView = (ListView) findViewById(R.id.appListView); + mGBDeviceAppAdapter = new GBDeviceAppAdapter(this, appList); + appListView.setAdapter(this.mGBDeviceAppAdapter); + + IntentFilter filter = new IntentFilter(); + filter.addAction(ControlCenter.ACTION_QUIT); + filter.addAction(ACTION_REFRESH_APPLIST); + registerReceiver(mReceiver, filter); + + Intent startIntent = new Intent(this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_REQUEST_APPINFO); + startService(startIntent); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(mReceiver); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java index ba99aecd6..1095b78ef 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java @@ -48,6 +48,9 @@ public class BluetoothCommunicationService extends Service { = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.setmusicinfo"; public static final String ACTION_REQUEST_VERSIONINFO = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.request_versioninfo"; + public static final String ACTION_REQUEST_APPINFO + = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.request_appinfo"; + private static final String TAG = "BluetoothCommunicationService"; private static final int NOTIFICATION_ID = 1; private BluetoothAdapter mBtAdapter = null; @@ -129,12 +132,24 @@ public class BluetoothCommunicationService extends Service { sendBroadcast(callIntent); break; case VERSION_INFO: - Log.i(TAG, "Got command for VERSION INFO"); + Log.i(TAG, "Got command for VERSION_INFO"); if (gbdevice == null) { return; } - gbdevice.setFirmwareVersion(cmdBundle.info); + gbdevice.setFirmwareVersion(cmdBundle.info[0]); sendDeviceUpdateIntent(); + break; + case APP_INFO: + Log.i(TAG, "Got command for APP_INFO"); + Intent appInfoIntent = new Intent(AppManagerActivity.ACTION_REFRESH_APPLIST); + int appCount = cmdBundle.info.length / 2; + appInfoIntent.putExtra("app_count", appCount); + for (Integer i = 0; i < appCount; i++) { + appInfoIntent.putExtra("app_name" + i.toString(), cmdBundle.info[i * 2]); + appInfoIntent.putExtra("app_creator" + i.toString(), cmdBundle.info[i * 2 + 1]); + } + sendBroadcast(appInfoIntent); + break; default: break; } @@ -248,6 +263,8 @@ public class BluetoothCommunicationService extends Service { } else { sendDeviceUpdateIntent(); } + } else if (action.equals(ACTION_REQUEST_APPINFO)) { + mBtSocketIoThread.write(PebbleProtocol.encodeAppInfoReq()); } else if (action.equals(ACTION_START)) { startForeground(NOTIFICATION_ID, createNotification("Gadgetbridge running")); mStarted = true; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java index 71bb7f48a..1b0ab54c4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java @@ -75,11 +75,16 @@ public class ControlCenter extends Activity { deviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View v, int position, long id) { - Intent startIntent = new Intent(ControlCenter.this, BluetoothCommunicationService.class); - startIntent.setAction(BluetoothCommunicationService.ACTION_CONNECT); - startIntent.putExtra("device_address", deviceList.get(position).getAddress()); + if (deviceList.get(position).getState() == GBDevice.State.CONNECTED) { + Intent startIntent = new Intent(ControlCenter.this, AppManagerActivity.class); + startActivity(startIntent); + } else { + Intent startIntent = new Intent(ControlCenter.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_CONNECT); + startIntent.putExtra("device_address", deviceList.get(position).getAddress()); - startService(startIntent); + startService(startIntent); + } } }); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommand.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommand.java index 9241d75ed..4f30e4b1e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommand.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommand.java @@ -17,5 +17,6 @@ public enum GBCommand { MUSIC_NEXT, MUSIC_PREVIOUS, + APP_INFO_NAME, VERSION_FIRMWARE } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommandBundle.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommandBundle.java index f63f79c78..a0c9eaef2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommandBundle.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommandBundle.java @@ -4,5 +4,5 @@ package nodomain.freeyourgadget.gadgetbridge; public class GBCommandBundle { public GBCommandClass commandClass; public GBCommand command; - public String info; + public String[] info; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommandClass.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommandClass.java index 0fd5aeebf..8faa4657b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommandClass.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBCommandClass.java @@ -3,5 +3,6 @@ package nodomain.freeyourgadget.gadgetbridge; public enum GBCommandClass { MUSIC_CONTROL, CALL_CONTROL, + APP_INFO, VERSION_INFO } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDevice.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDevice.java index dbe3bcc57..d33666612 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDevice.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDevice.java @@ -16,7 +16,6 @@ public class GBDevice { CONNECTED } - public GBDevice(String address, String name) { this.address = address; this.name = name; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDeviceApp.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDeviceApp.java new file mode 100644 index 000000000..17b122325 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDeviceApp.java @@ -0,0 +1,25 @@ +package nodomain.freeyourgadget.gadgetbridge; + +public class GBDeviceApp { + private final String name; + private final String creator; + private final String version; + + public GBDeviceApp(String name, String creator, String version) { + this.name = name; + this.creator = creator; + this.version = version; + } + + public String getName() { + return name; + } + + public String getCreator() { + return creator; + } + + public String getVersion() { + return version; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PebbleProtocol.java index c1eadd93d..15ba3a529 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PebbleProtocol.java @@ -60,12 +60,17 @@ public class PebbleProtocol { static final byte MUSICCONTROL_VOLUMEDOWN = 7; static final byte MUSICCONTROL_GETNOWPLAYING = 7; + static final byte TIME_GETTIME = 0; + static final byte TIME_SETTIME = 2; + + static final byte FIRMWAREVERSION_GETVERSION = 0; + + static final byte APPMANAGER_GETAPPBANKSTATUS = 1; + static final short LENGTH_PREFIX = 4; static final short LENGTH_SETTIME = 9; static final short LENGTH_PHONEVERSION = 21; - static final byte TIME_GETTIME = 0; - static final byte TIME_SETTIME = 2; static final byte PHONEVERSION_APPVERSION_MAGIC = 2; // increase this if pebble complains static final byte PHONEVERSION_APPVERSION_MAJOR = 2; @@ -91,7 +96,7 @@ public class PebbleProtocol { static final byte PHONEVERSION_REMOTE_OS_LINUX = 4; static final byte PHONEVERSION_REMOTE_OS_WINDOWS = 5; - static byte[] encodeMessage(short endpoint, byte type, int cookie, String[] parts) { + private static byte[] encodeMessage(short endpoint, byte type, int cookie, String[] parts) { // Calculate length first int length = LENGTH_PREFIX + 1; if (parts != null) { @@ -207,7 +212,11 @@ public class PebbleProtocol { } public static byte[] encodeFirmwareVersionReq() { - return encodeMessage(ENDPOINT_FIRMWAREVERSION, (byte) 0, 0, null); + return encodeMessage(ENDPOINT_FIRMWAREVERSION, FIRMWAREVERSION_GETVERSION, 0, null); + } + + public static byte[] encodeAppInfoReq() { + return encodeMessage(ENDPOINT_APPMANAGER, APPMANAGER_GETAPPBANKSTATUS, 0, null); } public static byte[] encodePhoneVersion(byte os) { @@ -283,9 +292,37 @@ public class PebbleProtocol { cmd.commandClass = GBCommandClass.VERSION_INFO; cmd.command = GBCommand.VERSION_FIRMWARE; - cmd.info = new String(versionString).trim(); + cmd.info = new String[]{new String(versionString).trim()}; Log.i(TAG, "Got firmware version: " + cmd.info); break; + case ENDPOINT_APPMANAGER: + cmd.commandClass = GBCommandClass.APP_INFO; + switch (pebbleCmd) { + case APPMANAGER_GETAPPBANKSTATUS: + cmd.command = GBCommand.APP_INFO_NAME; + int banks = buf.getInt(); + int banksUsed = buf.getInt(); + byte[] appName = new byte[32]; + byte[] creatorName = new byte[32]; + cmd.info = new String[banksUsed * 2]; + + for (int i = 0; i < banksUsed; i++) { + buf.getInt(); // id + buf.getInt(); // index + buf.get(appName, 0, 32); + buf.get(creatorName, 0, 32); + int flags = buf.getInt(); + short appVersion = buf.getShort(); + cmd.info[i * 2] = new String(appName).trim(); + cmd.info[i * 2 + 1] = new String(creatorName).trim(); + } + break; + default: + Log.i(TAG, "Unknown APPMANAGER command" + pebbleCmd); + cmd.command = GBCommand.UNDEFINEND; + break; + } + break; default: return null; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAppAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAppAdapter.java new file mode 100644 index 000000000..dd7667079 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAppAdapter.java @@ -0,0 +1,44 @@ +package nodomain.freeyourgadget.gadgetbridge.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.GBDeviceApp; +import nodomain.freeyourgadget.gadgetbridge.R; + +public class GBDeviceAppAdapter extends ArrayAdapter { + + private final Context context; + private final List appList; + + public GBDeviceAppAdapter(Context context, List appList) { + super(context, 0, appList); + + this.context = context; + this.appList = appList; + } + + @Override + public View getView(int position, View view, ViewGroup parent) { + GBDeviceApp deviceApp = getItem(position); + + if (view == null) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + view = inflater.inflate(R.layout.device_item, parent, false); + } + TextView deviceStatusLabel = (TextView) view.findViewById(R.id.device_status); + TextView deviceNameLabel = (TextView) view.findViewById(R.id.device_name); + deviceStatusLabel.setText(deviceApp.getVersion() + " by " + deviceApp.getCreator()); + deviceNameLabel.setText(deviceApp.getName()); + + return view; + } +} diff --git a/app/src/main/res/layout/activity_appmanager.xml b/app/src/main/res/layout/activity_appmanager.xml new file mode 100644 index 000000000..2c96678b7 --- /dev/null +++ b/app/src/main/res/layout/activity_appmanager.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 71f0ab94b..ef82dae97 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,10 +1,23 @@ Gadgetbridge - Gadgetbridge Control Center + + Gadgetbridge Settings Debug Quit - Debug Refresh + + App Manager + Debug + + + Settings + General Settings + Connect to device when Bluetooth turned on + Notifications + Notification for SMS + Notification for K9-Mail + Generic notification support + … also when screen is on diff --git a/app/src/main/res/values/strings_activity_settings.xml b/app/src/main/res/values/strings_activity_settings.xml deleted file mode 100644 index 30093888f..000000000 --- a/app/src/main/res/values/strings_activity_settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - General Settings - Connect to device when Bluetooth turned on - - - Notifications - Notification for SMS - Notification for K9-Mail - Generic notification support - … also when screen is on -