Pebble: Allow stopping apps though PebbleKit messages (also in the API)

This commit is contained in:
Andreas Shimokawa 2015-09-13 21:44:26 +02:00
parent 6fff4fb7ba
commit 95e22a4e32
11 changed files with 35 additions and 26 deletions

View File

@ -114,7 +114,7 @@ public class AppManagerActivity extends Activity {
@Override @Override
public void onItemClick(AdapterView parent, View v, int position, long id) { public void onItemClick(AdapterView parent, View v, int position, long id) {
UUID uuid = appList.get(position).getUUID(); UUID uuid = appList.get(position).getUUID();
GBApplication.deviceService().onAppStart(uuid); GBApplication.deviceService().onAppStart(uuid, true);
} }
}); });

View File

@ -34,7 +34,7 @@ public interface EventHandler {
void onAppInfoReq(); void onAppInfoReq();
void onAppStart(UUID uuid); void onAppStart(UUID uuid, boolean start);
void onAppDelete(UUID uuid); void onAppDelete(UUID uuid);

View File

@ -11,8 +11,8 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm; import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind; import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService; import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
public class GBDeviceService implements DeviceService { public class GBDeviceService implements DeviceService {
@ -150,9 +150,10 @@ public class GBDeviceService implements DeviceService {
} }
@Override @Override
public void onAppStart(UUID uuid) { public void onAppStart(UUID uuid, boolean start) {
Intent intent = createIntent().setAction(ACTION_STARTAPP) Intent intent = createIntent().setAction(ACTION_STARTAPP)
.putExtra(EXTRA_APP_UUID, uuid); .putExtra(EXTRA_APP_UUID, uuid)
.putExtra(EXTRA_APP_START, start);
invokeService(intent); invokeService(intent);
} }

View File

@ -45,6 +45,7 @@ public interface DeviceService extends EventHandler {
static final String EXTRA_MUSIC_ALBUM = "music_album"; static final String EXTRA_MUSIC_ALBUM = "music_album";
static final String EXTRA_MUSIC_TRACK = "music_track"; static final String EXTRA_MUSIC_TRACK = "music_track";
static final String EXTRA_APP_UUID = "app_uuid"; static final String EXTRA_APP_UUID = "app_uuid";
static final String EXTRA_APP_START = "app_start";
static final String EXTRA_URI = "uri"; static final String EXTRA_URI = "uri";
static final String EXTRA_ALARMS = "alarms"; static final String EXTRA_ALARMS = "alarms";
static final String EXTRA_PERFORM_PAIR = "perform_pair"; static final String EXTRA_PERFORM_PAIR = "perform_pair";

View File

@ -26,7 +26,6 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm; import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind; import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand; import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -51,6 +50,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SE
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_START; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_START;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_STARTAPP; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_STARTAPP;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_ALARMS; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_ALARMS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_START;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_UUID; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_UUID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_COMMAND; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_COMMAND;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_PHONENUMBER; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_PHONENUMBER;
@ -183,7 +183,7 @@ public class DeviceCommunicationService extends Service {
case ACTION_NOTIFICATION_GENERIC: { case ACTION_NOTIFICATION_GENERIC: {
String title = intent.getStringExtra(EXTRA_NOTIFICATION_TITLE); String title = intent.getStringExtra(EXTRA_NOTIFICATION_TITLE);
String body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY); String body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY);
int handle = intent.getIntExtra(EXTRA_NOTIFICATION_HANDLE,-1); int handle = intent.getIntExtra(EXTRA_NOTIFICATION_HANDLE, -1);
NotificationKind notificationKind = (NotificationKind) intent.getSerializableExtra(EXTRA_NOTIFICATION_KIND); NotificationKind notificationKind = (NotificationKind) intent.getSerializableExtra(EXTRA_NOTIFICATION_KIND);
mDeviceSupport.onGenericNotification(title, body, handle, notificationKind); mDeviceSupport.onGenericNotification(title, body, handle, notificationKind);
break; break;
@ -247,7 +247,8 @@ public class DeviceCommunicationService extends Service {
break; break;
case ACTION_STARTAPP: { case ACTION_STARTAPP: {
UUID uuid = (UUID) intent.getSerializableExtra(EXTRA_APP_UUID); UUID uuid = (UUID) intent.getSerializableExtra(EXTRA_APP_UUID);
mDeviceSupport.onAppStart(uuid); boolean start = intent.getBooleanExtra(EXTRA_APP_START, true);
mDeviceSupport.onAppStart(uuid, start);
break; break;
} }
case ACTION_DELETEAPP: { case ACTION_DELETEAPP: {
@ -273,6 +274,7 @@ public class DeviceCommunicationService extends Service {
/** /**
* For testing! * For testing!
*
* @param factory * @param factory
*/ */
public void setDeviceSupportFactory(DeviceSupportFactory factory) { public void setDeviceSupportFactory(DeviceSupportFactory factory) {
@ -282,6 +284,7 @@ public class DeviceCommunicationService extends Service {
/** /**
* Disposes the current DeviceSupport instance (if any) and sets a new device support instance * Disposes the current DeviceSupport instance (if any) and sets a new device support instance
* (if not null). * (if not null).
*
* @param deviceSupport * @param deviceSupport
*/ */
private void setDeviceSupport(@Nullable DeviceSupport deviceSupport) { private void setDeviceSupport(@Nullable DeviceSupport deviceSupport) {

View File

@ -178,11 +178,11 @@ public class ServiceDeviceSupport implements DeviceSupport {
} }
@Override @Override
public void onAppStart(UUID uuid) { public void onAppStart(UUID uuid, boolean start) {
if (checkBusy("app start")) { if (checkBusy("app start")) {
return; return;
} }
delegate.onAppStart(uuid); delegate.onAppStart(uuid, start);
} }
@Override @Override

View File

@ -574,7 +574,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
} }
@Override @Override
public void onAppStart(UUID uuid) { public void onAppStart(UUID uuid, boolean start) {
// not supported // not supported
} }

View File

@ -88,9 +88,10 @@ public class PebbleIoThread extends GBDeviceIoThread {
UUID uuid; UUID uuid;
switch (action) { switch (action) {
case PEBBLEKIT_ACTION_APP_START: case PEBBLEKIT_ACTION_APP_START:
case PEBBLEKIT_ACTION_APP_STOP:
uuid = (UUID) intent.getSerializableExtra("uuid"); uuid = (UUID) intent.getSerializableExtra("uuid");
if (uuid != null) { if (uuid != null) {
write(mPebbleProtocol.encodeAppStart(uuid)); write(mPebbleProtocol.encodeAppStart(uuid, action == PEBBLEKIT_ACTION_APP_START));
} }
break; break;
case PEBBLEKIT_ACTION_APP_SEND: case PEBBLEKIT_ACTION_APP_SEND:

View File

@ -67,6 +67,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
static final short ENDPOINT_PUTBYTES = (short) 48879; static final short ENDPOINT_PUTBYTES = (short) 48879;
static final byte APPRUNSTATE_START = 1; static final byte APPRUNSTATE_START = 1;
static final byte APPRUNSTATE_STOP = 2;
static final byte BLOBDB_INSERT = 1; static final byte BLOBDB_INSERT = 1;
static final byte BLOBDB_DELETE = 4; static final byte BLOBDB_DELETE = 4;
@ -877,19 +878,20 @@ public class PebbleProtocol extends GBDeviceProtocol {
} }
@Override @Override
public byte[] encodeAppStart(UUID uuid) { public byte[] encodeAppStart(UUID uuid, boolean start) {
if (isFw3x) { if (isFw3x) {
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + LENGTH_APPRUNSTATE); ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + LENGTH_APPRUNSTATE);
buf.order(ByteOrder.BIG_ENDIAN); buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort(LENGTH_APPRUNSTATE); buf.putShort(LENGTH_APPRUNSTATE);
buf.putShort(ENDPOINT_APPRUNSTATE); buf.putShort(ENDPOINT_APPRUNSTATE);
buf.put(APPRUNSTATE_START); buf.put(start ? APPRUNSTATE_START : APPRUNSTATE_STOP);
buf.putLong(uuid.getMostSignificantBits()); buf.putLong(uuid.getMostSignificantBits());
buf.putLong(uuid.getLeastSignificantBits()); buf.putLong(uuid.getLeastSignificantBits());
return buf.array(); return buf.array();
} else { } else {
ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>(); ArrayList<Pair<Integer, Object>> pairs = new ArrayList<>();
pairs.add(new Pair<>(1, (Object) 1)); // launch int param = start ? 1 : 0;
pairs.add(new Pair<>(1, (Object) param));
return encodeApplicationMessagePush(ENDPOINT_LAUNCHER, uuid, pairs); return encodeApplicationMessagePush(ENDPOINT_LAUNCHER, uuid, pairs);
} }
} }

View File

@ -5,23 +5,23 @@ import org.slf4j.LoggerFactory;
import java.util.UUID; import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
/** /**
* An abstract base class for devices speaking a serial protocol, like via * An abstract base class for devices speaking a serial protocol, like via
* an rfcomm bluetooth socket or a TCP socket. * an rfcomm bluetooth socket or a TCP socket.
* * <p/>
* This class uses two helper classes to deal with that: * This class uses two helper classes to deal with that:
* - GBDeviceIoThread, which creates and maintains the actual socket connection and implements the transport layer * - GBDeviceIoThread, which creates and maintains the actual socket connection and implements the transport layer
* - GBDeviceProtocol, which implements the encoding and decoding of messages, i.e. the actual device specific protocol * - GBDeviceProtocol, which implements the encoding and decoding of messages, i.e. the actual device specific protocol
* * <p/>
* Note that these two classes need to be implemented in a device specific way. * Note that these two classes need to be implemented in a device specific way.
* * <p/>
* This implementation implements all methods of {@link EventHandler}, calls the {@link GBDeviceProtocol device protocol} * This implementation implements all methods of {@link EventHandler}, calls the {@link GBDeviceProtocol device protocol}
* to create the device specific message for the respective events and sends them to the device via {@link #sendToDevice(byte[])}. * to create the device specific message for the respective events and sends them to the device via {@link #sendToDevice(byte[])}.
*/ */
@ -85,6 +85,7 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
/** /**
* Sends the given message to the device. This implementation delegates the * Sends the given message to the device. This implementation delegates the
* writing to the {@link #getDeviceIOThread device io thread} * writing to the {@link #getDeviceIOThread device io thread}
*
* @param bytes the message to send to the device * @param bytes the message to send to the device
*/ */
protected void sendToDevice(byte[] bytes) { protected void sendToDevice(byte[] bytes) {
@ -149,8 +150,8 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
} }
@Override @Override
public void onAppStart(UUID uuid) { public void onAppStart(UUID uuid, boolean start) {
byte[] bytes = gbDeviceProtocol.encodeAppStart(uuid); byte[] bytes = gbDeviceProtocol.encodeAppStart(uuid, start);
sendToDevice(bytes); sendToDevice(bytes);
} }

View File

@ -2,9 +2,9 @@ package nodomain.freeyourgadget.gadgetbridge.service.serial;
import java.util.UUID; import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
public abstract class GBDeviceProtocol { public abstract class GBDeviceProtocol {
@ -48,7 +48,7 @@ public abstract class GBDeviceProtocol {
return null; return null;
} }
public byte[] encodeAppStart(UUID uuid) { public byte[] encodeAppStart(UUID uuid, boolean start) {
return null; return null;
} }