1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-26 10:35:50 +01:00

Merge pull request #445 from Freeyourgadget/liveview

Liveview: Initial support for Liveview devices
This commit is contained in:
Daniele Gobbetti 2016-12-07 13:21:40 +01:00 committed by GitHub
commit 259eb51784
10 changed files with 688 additions and 2 deletions

View File

@ -19,6 +19,7 @@ need to create an account and transmit any of your data to the vendor's servers.
* Mi Band, Mi Band 1A, Mi Band 1S * Mi Band, Mi Band 1A, Mi Band 1S
* Mi Band 2 * Mi Band 2
* Vibratissimo (experimental) * Vibratissimo (experimental)
* Liveview
## Features (Pebble) ## Features (Pebble)
@ -113,6 +114,12 @@ Known Issues:
* If you use other apps like Mi Fit, and "bonding" with Gadgetbridge does not work, please * If you use other apps like Mi Fit, and "bonding" with Gadgetbridge does not work, please
try to unpair the band in the other app and try again with Gadgetbridge. try to unpair the band in the other app and try again with Gadgetbridge.
## Features (Liveview)
* set time (automatically upon connection)
* display notifications and vibrate
## Authors (in order of first code contribution) ## Authors (in order of first code contribution)
* Andreas Shimokawa * Andreas Shimokawa

View File

@ -0,0 +1,110 @@
package nodomain.freeyourgadget.gadgetbridge.devices.liveview;
//Changed by Renze: Fixed brightness constants
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* Message constants reverse-engineered by Andrew de Quincey (<a
* href="http://adq.livejournal.com">http://adq.livejournal.com</a>).
*
* @author Robert &lt;xperimental@solidproject.de&gt;
*/
public final class LiveviewConstants {
public static Charset ENCODING = StandardCharsets.ISO_8859_1;
public static ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
public static final byte CLOCK_24H = 0;
public static final byte CLOCK_12H = 1;
public static final byte MSG_GETCAPS = 1;
public static final byte MSG_GETCAPS_RESP = 2;
public static final byte MSG_DISPLAYTEXT = 3;
public static final byte MSG_DISPLAYTEXT_ACK = 4;
public static final byte MSG_DISPLAYPANEL = 5;
public static final byte MSG_DISPLAYPANEL_ACK = 6;
public static final byte MSG_DEVICESTATUS = 7;
public static final byte MSG_DEVICESTATUS_ACK = 8;
public static final byte MSG_DISPLAYBITMAP = 19;
public static final byte MSG_DISPLAYBITMAP_ACK = 20;
public static final byte MSG_CLEARDISPLAY = 21;
public static final byte MSG_CLEARDISPLAY_ACK = 22;
public static final byte MSG_SETMENUSIZE = 23;
public static final byte MSG_SETMENUSIZE_ACK = 24;
public static final byte MSG_GETMENUITEM = 25;
public static final byte MSG_GETMENUITEM_RESP = 26;
public static final byte MSG_GETALERT = 27;
public static final byte MSG_GETALERT_RESP = 28;
public static final byte MSG_NAVIGATION = 29;
public static final byte MSG_NAVIGATION_RESP = 30;
public static final byte MSG_SETSTATUSBAR = 33;
public static final byte MSG_SETSTATUSBAR_ACK = 34;
public static final byte MSG_GETMENUITEMS = 35;
public static final byte MSG_SETMENUSETTINGS = 36;
public static final byte MSG_SETMENUSETTINGS_ACK = 37;
public static final byte MSG_GETTIME = 38;
public static final byte MSG_GETTIME_RESP = 39;
public static final byte MSG_SETLED = 40;
public static final byte MSG_SETLED_ACK = 41;
public static final byte MSG_SETVIBRATE = 42;
public static final byte MSG_SETVIBRATE_ACK = 43;
public static final byte MSG_ACK = 44;
public static final byte MSG_SETSCREENMODE = 64;
public static final byte MSG_SETSCREENMODE_ACK = 65;
public static final byte MSG_GETSCREENMODE = 66;
public static final byte MSG_GETSCREENMODE_RESP = 67;
public static final int DEVICESTATUS_OFF = 0;
public static final int DEVICESTATUS_ON = 1;
public static final int DEVICESTATUS_MENU = 2;
public static final byte RESULT_OK = 0;
public static final byte RESULT_ERROR = 1;
public static final byte RESULT_OOM = 2;
public static final byte RESULT_EXIT = 3;
public static final byte RESULT_CANCEL = 4;
public static final int NAVACTION_PRESS = 0;
public static final int NAVACTION_LONGPRESS = 1;
public static final int NAVACTION_DOUBLEPRESS = 2;
public static final int NAVTYPE_UP = 0;
public static final int NAVTYPE_DOWN = 1;
public static final int NAVTYPE_LEFT = 2;
public static final int NAVTYPE_RIGHT = 3;
public static final int NAVTYPE_SELECT = 4;
public static final int NAVTYPE_MENUSELECT = 5;
public static final int ALERTACTION_CURRENT = 0;
public static final int ALERTACTION_FIRST = 1;
public static final int ALERTACTION_LAST = 2;
public static final int ALERTACTION_NEXT = 3;
public static final int ALERTACTION_PREV = 4;
public static final int BRIGHTNESS_OFF = 49;
public static final int BRIGHTNESS_DIM = 50;
public static final int BRIGHTNESS_MAX = 51;
public static final String CLIENT_SOFTWARE_VERSION = "0.0.3";
}

View File

@ -0,0 +1,105 @@
package nodomain.freeyourgadget.gadgetbridge.devices.liveview;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class LiveviewCoordinator extends AbstractDeviceCoordinator {
@Override
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
String name = candidate.getDevice().getName();
if (name != null && name.startsWith("LiveView")) {
return DeviceType.LIVEVIEW;
}
return DeviceType.UNKNOWN;
}
@Override
public DeviceType getDeviceType() {
return DeviceType.LIVEVIEW;
}
@Override
public Class<? extends Activity> getPairingActivity() {
return null;
}
@Override
public Class<? extends Activity> getPrimaryActivity() {
return null;
}
@Override
public InstallHandler findInstallHandler(Uri uri, Context context) {
return null;
}
@Override
public boolean supportsActivityDataFetching() {
return false;
}
@Override
public boolean supportsActivityTracking() {
return false;
}
@Override
public SampleProvider<? extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return null;
}
@Override
public boolean supportsScreenshots() {
return false;
}
@Override
public boolean supportsAlarmConfiguration() {
return false;
}
@Override
public boolean supportsHeartRateMeasurement(GBDevice device) {
return false;
}
@Override
public int getTapString() {
//TODO: changeme
return R.string.tap_connected_device_for_activity;
}
@Override
public String getManufacturer() {
return "Sony Ericsson";
}
@Override
public boolean supportsAppsManagement() {
return false;
}
@Override
public Class<? extends Activity> getAppsManagementActivity() {
return null;
}
@Override
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
// nothing to delete, yet
}
}

View File

@ -12,6 +12,7 @@ public enum DeviceType {
MIBAND(10), MIBAND(10),
MIBAND2(11), MIBAND2(11),
VIBRATISSIMO(20), VIBRATISSIMO(20),
LIVEVIEW(30),
TEST(1000); TEST(1000);
private final int key; private final int key;

View File

@ -174,7 +174,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
try (DBHandler dbHandler = GBApplication.acquireDB()) { try (DBHandler dbHandler = GBApplication.acquireDB()) {
DaoSession session = dbHandler.getDaoSession(); DaoSession session = dbHandler.getDaoSession();
boolean askForDBMigration = false; boolean askForDBMigration = false;
if (DBHelper.findDevice(device, session) == null && device.getType() != DeviceType.VIBRATISSIMO) { if (DBHelper.findDevice(device, session) == null && device.getType() != DeviceType.VIBRATISSIMO && (device.getType() != DeviceType.LIVEVIEW)) {
askForDBMigration = true; askForDBMigration = true;
} }
DBHelper.getDevice(device, session); // implicitly creates the device in database if not present, and updates device attributes DBHelper.getDevice(device, session); // implicitly creates the device in database if not present, and updates device attributes

View File

@ -9,8 +9,8 @@ import java.util.EnumSet;
import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.vibratissimo.VibratissimoCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.liveview.LiveviewSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBand2Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBand2Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.PebbleSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.PebbleSupport;
@ -93,6 +93,9 @@ public class DeviceSupportFactory {
case VIBRATISSIMO: case VIBRATISSIMO:
deviceSupport = new ServiceDeviceSupport(new VibratissimoSupport(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING)); deviceSupport = new ServiceDeviceSupport(new VibratissimoSupport(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
break; break;
case LIVEVIEW:
deviceSupport = new ServiceDeviceSupport(new LiveviewSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
} }
if (deviceSupport != null) { if (deviceSupport != null) {
deviceSupport.setContext(gbDevice, mBtAdapter, mContext); deviceSupport.setContext(gbDevice, mBtAdapter, mContext);

View File

@ -0,0 +1,220 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.liveview;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.ParcelUuid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewConstants;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class LiveviewIoThread extends GBDeviceIoThread {
private static final Logger LOG = LoggerFactory.getLogger(LiveviewIoThread.class);
private static final UUID SERIAL = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private final LiveviewProtocol mLiveviewProtocol;
private final LiveviewSupport mLiveviewSupport;
private BluetoothAdapter mBtAdapter = null;
private BluetoothSocket mBtSocket = null;
private InputStream mInStream = null;
private OutputStream mOutStream = null;
private boolean mQuit = false;
@Override
public void quit() {
mQuit = true;
if (mBtSocket != null) {
try {
mBtSocket.close();
} catch (IOException e) {
LOG.error(e.getMessage());
}
}
}
private boolean mIsConnected = false;
public LiveviewIoThread(GBDevice gbDevice, Context context, GBDeviceProtocol lvProtocol, LiveviewSupport lvSupport, BluetoothAdapter lvBtAdapter) {
super(gbDevice, context);
mLiveviewProtocol = (LiveviewProtocol) lvProtocol;
mBtAdapter = lvBtAdapter;
mLiveviewSupport = lvSupport;
}
@Override
public synchronized void write(byte[] bytes) {
if (null == bytes)
return;
LOG.debug("writing:" + GB.hexdump(bytes, 0, bytes.length));
try {
mOutStream.write(bytes);
mOutStream.flush();
} catch (IOException e) {
LOG.error("Error writing.", e);
}
}
@Override
public void run() {
mIsConnected = connect();
if (!mIsConnected) {
setUpdateState(GBDevice.State.NOT_CONNECTED);
return;
}
mQuit = false;
while (!mQuit) {
LOG.info("Ready for a new message exchange.");
try {
GBDeviceEvent deviceEvents[] = mLiveviewProtocol.decodeResponse(parseIncoming());
if (deviceEvents == null) {
LOG.info("unhandled message");
} else {
for (GBDeviceEvent deviceEvent : deviceEvents) {
if (deviceEvent == null) {
continue;
}
mLiveviewSupport.evaluateGBDeviceEvent(deviceEvent);
}
}
} catch (SocketTimeoutException ignore) {
LOG.debug("socket timeout, we can't help but ignore this");
} catch (IOException e) {
LOG.info(e.getMessage());
mIsConnected = false;
mBtSocket = null;
mInStream = null;
mOutStream = null;
LOG.info("Bluetooth socket closed, will quit IO Thread");
break;
}
}
mIsConnected = false;
if (mBtSocket != null) {
try {
mBtSocket.close();
} catch (IOException e) {
LOG.error(e.getMessage());
}
mBtSocket = null;
}
setUpdateState(GBDevice.State.NOT_CONNECTED);
}
@Override
protected boolean connect() {
GBDevice.State originalState = gbDevice.getState();
setUpdateState(GBDevice.State.CONNECTING);
try {
BluetoothDevice btDevice = mBtAdapter.getRemoteDevice(gbDevice.getAddress());
ParcelUuid uuids[] = btDevice.getUuids();
if (uuids == null) {
return false;
}
for (ParcelUuid uuid : uuids) {
LOG.info("found service UUID " + uuid);
}
mBtSocket = btDevice.createRfcommSocketToServiceRecord(uuids[0].getUuid());
mBtSocket.connect();
mInStream = mBtSocket.getInputStream();
mOutStream = mBtSocket.getOutputStream();
setUpdateState(GBDevice.State.CONNECTED);
} catch (IOException e) {
LOG.error("Server socket cannot be started.");
//LOG.error(e.getMessage());
setUpdateState(originalState);
mInStream = null;
mOutStream = null;
mBtSocket = null;
return false;
}
write(mLiveviewProtocol.encodeSetTime());
setUpdateState(GBDevice.State.INITIALIZED);
return true;
}
private void setUpdateState(GBDevice.State state) {
gbDevice.setState(state);
gbDevice.sendDeviceUpdateIntent(getContext());
}
private byte[] parseIncoming() throws IOException {
ByteArrayOutputStream msgStream = new ByteArrayOutputStream();
boolean finished = false;
ReaderState state = ReaderState.ID;
byte[] incoming = new byte[1];
while (!finished) {
mInStream.read(incoming);
msgStream.write(incoming);
switch (state) {
case ID:
state = ReaderState.HEADER_LEN;
incoming = new byte[1];
break;
case HEADER_LEN:
int headerSize = 0xff & incoming[0];
if (headerSize < 0)
throw new IOException();
state = ReaderState.HEADER;
incoming = new byte[headerSize];
break;
case HEADER:
int payloadSize = getLastInt(msgStream);
if (payloadSize < 0 || payloadSize > 8000) //this will possibly be changed in the future
throw new IOException();
state = ReaderState.PAYLOAD;
incoming = new byte[payloadSize];
break;
case PAYLOAD: //read is blocking, if we are here we have all the data
finished = true;
break;
}
}
byte[] msgArray = msgStream.toByteArray();
LOG.debug("received: " + GB.hexdump(msgArray, 0, msgArray.length));
return msgArray;
}
/**
* Enumeration containing the possible internal status of the reader.
*/
private enum ReaderState {
ID, HEADER_LEN, HEADER, PAYLOAD;
}
private int getLastInt(ByteArrayOutputStream stream) {
byte[] array = stream.toByteArray();
ByteBuffer buffer = ByteBuffer.wrap(array, array.length - 4, 4);
buffer.order(LiveviewConstants.BYTE_ORDER);
return buffer.getInt();
}
}

View File

@ -0,0 +1,132 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.liveview;
import java.nio.ByteBuffer;
import java.util.Calendar;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewConstants;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
public class LiveviewProtocol extends GBDeviceProtocol {
@Override
public byte[] encodeFindDevice(boolean start) {
return encodeVibrateRequest((short) 100, (short) 200);
}
protected LiveviewProtocol(GBDevice device) {
super(device);
}
@Override
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
int length = responseData.length;
if (length < 4) {
//empty message
return null;
} else {
ByteBuffer buffer = ByteBuffer.wrap(responseData, 0, length);
byte msgId = buffer.get();
buffer.get();
int payloadLen = buffer.getInt();
GBDeviceEventSendBytes reply = new GBDeviceEventSendBytes();
if (payloadLen + 6 == length) {
switch (msgId) {
case LiveviewConstants.MSG_DEVICESTATUS:
reply.encodedBytes = constructMessage(LiveviewConstants.MSG_DEVICESTATUS_ACK, new byte[]{LiveviewConstants.RESULT_OK});
break;
case LiveviewConstants.MSG_DISPLAYPANEL_ACK:
reply.encodedBytes = encodeVibrateRequest((short) 100, (short) 200); //hack to make the notifications vibrate!
break;
default:
}
GBDeviceEventSendBytes ack = new GBDeviceEventSendBytes();
ack.encodedBytes = constructMessage(LiveviewConstants.MSG_ACK, new byte[]{msgId});
return new GBDeviceEvent[]{ack, reply};
}
}
return super.decodeResponse(responseData);
}
@Override
public byte[] encodeSetTime() {
int time = (int) (Calendar.getInstance().getTimeInMillis() / 1000);
time += Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 1000;
time += Calendar.getInstance().get(Calendar.DST_OFFSET) / 1000;
ByteBuffer buffer = ByteBuffer.allocate(5);
buffer.order(LiveviewConstants.BYTE_ORDER);
buffer.putInt(time);
buffer.put(LiveviewConstants.CLOCK_24H);
return constructMessage(LiveviewConstants.MSG_GETTIME_RESP, buffer.array());
}
@Override
public byte[] encodeNotification(NotificationSpec notificationSpec) {
String headerText;
// for SMS and EMAIL that came in though SMS or K9 receiver
if (notificationSpec.sender != null) {
headerText = notificationSpec.sender;
} else {
headerText = notificationSpec.title;
}
String footerText = (null != notificationSpec.sourceName) ? notificationSpec.sourceName : "";
String bodyText = (null != notificationSpec.body) ? notificationSpec.body : "";
byte[] headerTextArray = headerText.getBytes(LiveviewConstants.ENCODING);
byte[] footerTextArray = footerText.getBytes(LiveviewConstants.ENCODING);
byte[] bodyTextArray = bodyText.getBytes(LiveviewConstants.ENCODING);
int size = 15 + headerTextArray.length + bodyTextArray.length + footerTextArray.length;
ByteBuffer buffer = ByteBuffer.allocate(size);
buffer.put((byte) 1);
buffer.putShort((short) 0);
buffer.putShort((short) 0);
buffer.putShort((short) 0);
buffer.put((byte) 80); //should alert but it doesn't make the liveview vibrate
buffer.put((byte) 0); //0 is for plaintext vs bitmapimage (1) strings
buffer.putShort((short) headerTextArray.length);
buffer.put(headerTextArray);
buffer.putShort((short) bodyTextArray.length);
buffer.put(bodyTextArray);
buffer.putShort((short) footerTextArray.length);
buffer.put(footerTextArray);
return constructMessage(LiveviewConstants.MSG_DISPLAYPANEL, buffer.array());
}
//specific messages
public static byte[] constructMessage(byte messageType, byte[] payload) {
ByteBuffer msgBuffer = ByteBuffer.allocate(payload.length + 6);
msgBuffer.order(LiveviewConstants.BYTE_ORDER);
msgBuffer.put(messageType);
msgBuffer.put((byte) 4);
msgBuffer.putInt(payload.length);
msgBuffer.put(payload);
return msgBuffer.array();
}
public byte[] encodeVibrateRequest(short delay, short time) {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.order(LiveviewConstants.BYTE_ORDER);
buffer.putShort(delay);
buffer.putShort(time);
return constructMessage(LiveviewConstants.MSG_SETVIBRATE, buffer.array());
}
public byte[] encodeCapabilitiesRequest() {
byte[] version = LiveviewConstants.CLIENT_SOFTWARE_VERSION.getBytes(LiveviewConstants.ENCODING);
ByteBuffer buffer = ByteBuffer.allocate(version.length + 1);
buffer.order(LiveviewConstants.BYTE_ORDER);
buffer.put((byte) version.length);
buffer.put(version);
return constructMessage(LiveviewConstants.MSG_GETCAPS, buffer.array());
}
}

View File

@ -0,0 +1,106 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.liveview;
import android.net.Uri;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
public class LiveviewSupport extends AbstractSerialDeviceSupport {
@Override
public boolean connect() {
getDeviceIOThread().start();
return true;
}
@Override
protected GBDeviceProtocol createDeviceProtocol() {
return new LiveviewProtocol(getDevice());
}
@Override
protected GBDeviceIoThread createDeviceIOThread() {
return new LiveviewIoThread(getDevice(), getContext(), getDeviceProtocol(), LiveviewSupport.this, getBluetoothAdapter());
}
@Override
public boolean useAutoConnect() {
return false;
}
@Override
public void onInstallApp(Uri uri) {
//nothing to do ATM
}
@Override
public void onAppConfiguration(UUID uuid, String config) {
//nothing to do ATM
}
@Override
public void onHeartRateTest() {
//nothing to do ATM
}
@Override
public void onSetConstantVibration(int intensity) {
//nothing to do ATM
}
@Override
public synchronized LiveviewIoThread getDeviceIOThread() {
return (LiveviewIoThread) super.getDeviceIOThread();
}
@Override
public void onNotification(NotificationSpec notificationSpec) {
super.onNotification(notificationSpec);
}
@Override
public void onSetCallState(CallSpec callSpec) {
//nothing to do ATM
}
@Override
public void onSetMusicState(MusicStateSpec musicStateSpec) {
//nothing to do ATM
}
@Override
public void onSetMusicInfo(MusicSpec musicSpec) {
//nothing to do ATM
}
@Override
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
//nothing to do ATM
}
@Override
public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) {
//nothing to do ATM
}
@Override
public void onDeleteCalendarEvent(byte type, long id) {
//nothing to do ATM
}
@Override
public void onTestNewFunction() {
//nothing to do ATM
}
}

View File

@ -22,6 +22,7 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
@ -165,6 +166,7 @@ public class DeviceHelper {
result.add(new MiBandCoordinator()); result.add(new MiBandCoordinator());
result.add(new PebbleCoordinator()); result.add(new PebbleCoordinator());
result.add(new VibratissimoCoordinator()); result.add(new VibratissimoCoordinator());
result.add(new LiveviewCoordinator());
return result; return result;
} }