mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-25 01:55:50 +01:00
Huawei: Contacts uploading support
This commit is contained in:
parent
287fdd87d8
commit
fc450882cb
@ -169,6 +169,11 @@ public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordin
|
||||
return huaweiCoordinator.getAlarmSlotCount(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContactsSlotCount(GBDevice device) {
|
||||
return huaweiCoordinator.getContactsSlotCount(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsActivityDataFetching() {
|
||||
return true;
|
||||
|
@ -65,6 +65,8 @@ public class HuaweiCoordinator {
|
||||
|
||||
private boolean transactionCrypted=true;
|
||||
|
||||
private int maxContactsCount = 0;
|
||||
|
||||
public HuaweiCoordinator(HuaweiCoordinatorSupplier parent) {
|
||||
this.parent = parent;
|
||||
for (String key : getCapabilitiesSharedPreferences().getAll().keySet()) {
|
||||
@ -84,6 +86,9 @@ public class HuaweiCoordinator {
|
||||
key,
|
||||
GB.hexdump(Notifications.defaultConstraints)
|
||||
)));
|
||||
if (key.equals("maxContactsCount"))
|
||||
this.maxContactsCount = getCapabilitiesSharedPreferences().getInt(key, 0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,6 +126,11 @@ public class HuaweiCoordinator {
|
||||
getCapabilitiesSharedPreferences().edit().putString("notificationConstraints", GB.hexdump(constraints.array())).apply();
|
||||
}
|
||||
|
||||
public void saveMaxContactsCount(int maxContactsCount) {
|
||||
this.maxContactsCount = maxContactsCount;
|
||||
getCapabilitiesSharedPreferences().edit().putInt("maxContactsCount", maxContactsCount).apply();
|
||||
}
|
||||
|
||||
public void addCommandsForService(int service, byte[] commands) {
|
||||
if (!commandsPerService.containsKey(service)) {
|
||||
saveCommandsForService(service, commands);
|
||||
@ -232,6 +242,11 @@ public class HuaweiCoordinator {
|
||||
if (supportsCameraRemote())
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_camera_remote);
|
||||
|
||||
//Contacts
|
||||
if (getContactsSlotCount(device) > 0) {
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_contacts);
|
||||
}
|
||||
|
||||
// Time
|
||||
if (supportsDateFormat()) {
|
||||
final List<Integer> dateTime = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DATE_TIME);
|
||||
@ -297,6 +312,10 @@ public class HuaweiCoordinator {
|
||||
return supportsCommandForService(0x01, 0x29) && CameraActivity.supportsCamera();
|
||||
}
|
||||
|
||||
public boolean supportsContacts() {
|
||||
return supportsCommandForService(0x03, 0x1);
|
||||
}
|
||||
|
||||
public boolean supportsAcceptAgreement() {
|
||||
return supportsCommandForService(0x01, 0x30);
|
||||
}
|
||||
@ -550,6 +569,10 @@ public class HuaweiCoordinator {
|
||||
return alarmCount;
|
||||
}
|
||||
|
||||
public int getContactsSlotCount(GBDevice device) {
|
||||
return supportsContacts()?maxContactsCount:0;
|
||||
}
|
||||
|
||||
public void setTransactionCrypted(boolean crypted) {
|
||||
this.transactionCrypted = crypted;
|
||||
}
|
||||
|
@ -175,6 +175,11 @@ public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator i
|
||||
return huaweiCoordinator.getAlarmSlotCount(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContactsSlotCount(GBDevice device) {
|
||||
return huaweiCoordinator.getContactsSlotCount(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsActivityDataFetching() {
|
||||
return true;
|
||||
|
@ -34,6 +34,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.AccountRelate
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Calls;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.CameraRemote;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Contacts;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService0A;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService2C;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
|
||||
@ -476,6 +477,15 @@ public class HuaweiPacket {
|
||||
default:
|
||||
return this;
|
||||
}
|
||||
case Contacts.id:
|
||||
switch (this.commandId) {
|
||||
case Contacts.ContactsSet.id:
|
||||
return new Contacts.ContactsSet.Response(paramsProvider).fromPacket(this);
|
||||
case Contacts.ContactsCount.id:
|
||||
return new Contacts.ContactsCount.Response(paramsProvider).fromPacket(this);
|
||||
}
|
||||
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
||||
return this;
|
||||
case Calls.id:
|
||||
if (this.commandId == Calls.AnswerCallResponse.id)
|
||||
return new Calls.AnswerCallResponse(paramsProvider).fromPacket(this);
|
||||
|
@ -0,0 +1,93 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Contact;
|
||||
|
||||
public class Contacts {
|
||||
public static final byte id = 0x03;
|
||||
|
||||
public static class ContactsSet {
|
||||
public static final byte id = 0x01;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider, ArrayList<? extends Contact> contacts, int maxCount) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = Contacts.id;
|
||||
this.commandId = id;
|
||||
|
||||
HuaweiTLV contacts_tlv = new HuaweiTLV();
|
||||
for(int i = 0; i < maxCount; i++) {
|
||||
HuaweiTLV contact= new HuaweiTLV()
|
||||
.put(0x03, (byte) (i + 1));
|
||||
if(i < contacts.size()) {
|
||||
contact.put(0x4, contacts.get(i).getName())
|
||||
.put(0x85, new HuaweiTLV().put(0x86, new HuaweiTLV().put(0x7, "Mobile").put(0x8, contacts.get(i).getNumber())));
|
||||
}
|
||||
contacts_tlv.put(0x82, contact);
|
||||
}
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x81, contacts_tlv);
|
||||
|
||||
this.complete = true;
|
||||
this.isEncrypted = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
|
||||
public boolean isOk;
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Contacts.id;
|
||||
this.commandId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
isOk = this.tlv.getInteger(0x7f) == 0x000186A0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ContactsCount {
|
||||
public static final byte id = 0x02;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = Contacts.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x1)
|
||||
.put(0x2);
|
||||
|
||||
this.complete = true;
|
||||
this.isEncrypted = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
|
||||
public int maxCount;
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Contacts.id;
|
||||
this.commandId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
maxCount = this.tlv.getByte(0x01);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,12 +24,14 @@ import android.net.Uri;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCameraRemote;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Contact;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
@ -170,6 +172,11 @@ public class HuaweiBRSupport extends AbstractBTBRDeviceSupport {
|
||||
supportProvider.onCameraStatusChange(event, filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetContacts(ArrayList<? extends Contact> contacts) {
|
||||
supportProvider.onSetContacts(contacts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
supportProvider.dispose();
|
||||
|
@ -34,6 +34,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCameraRemo
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Contact;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
@ -178,6 +179,11 @@ public class HuaweiLESupport extends AbstractBTLEDeviceSupport {
|
||||
supportProvider.onCameraStatusChange(event, filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetContacts(ArrayList<? extends Contact> contacts) {
|
||||
supportProvider.onSetContacts(contacts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
supportProvider.dispose();
|
||||
|
@ -85,6 +85,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Contact;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
@ -94,6 +95,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.AcceptAgreementsRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetAppInfoParams;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetContactsCount;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetEventAlarmList;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetGpsParameterRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetNotificationConstraintsRequest;
|
||||
@ -105,6 +107,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Send
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGpsAndTimeToDeviceRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGpsDataRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendFileUploadInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendSetContactsRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherCurrentRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyHeartRateCapabilityRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyRestHeartRateCapabilityRequest;
|
||||
@ -791,6 +794,7 @@ public class HuaweiSupportProvider {
|
||||
if (getHuaweiCoordinator().supportsActivityReminder()) {
|
||||
setActivityReminder();
|
||||
}
|
||||
|
||||
if (getHuaweiCoordinator().supportsTruSleep()) {
|
||||
setTrusleep();
|
||||
}
|
||||
@ -803,20 +807,55 @@ public class HuaweiSupportProvider {
|
||||
getNotificationConstraintsReq.doPerform();
|
||||
}
|
||||
|
||||
if (getHuaweiCoordinator().supportsWatchfaceParams()) {
|
||||
GetWatchfaceParams getWatchfaceParams = new GetWatchfaceParams(this);
|
||||
getWatchfaceParams.doPerform();
|
||||
}
|
||||
|
||||
if (getHuaweiCoordinator().supportsCameraRemote() && GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREF_CAMERA_REMOTE, false)) {
|
||||
SendCameraRemoteSetupEvent sendCameraRemoteSetupEvent = new SendCameraRemoteSetupEvent(this, CameraRemote.CameraRemoteSetup.Request.Event.ENABLE_CAMERA);
|
||||
sendCameraRemoteSetupEvent.doPerform();
|
||||
}
|
||||
|
||||
if (getHuaweiCoordinator().supportsAppParams()) {
|
||||
GetAppInfoParams getAppInfoParams = new GetAppInfoParams(this);
|
||||
getAppInfoParams.doPerform();
|
||||
// FIXME: Limit number of simultaneous commands
|
||||
// Huawei watch, for example the Watch GT4 has limited buffer for incoming commands.
|
||||
// So sending a lot of command broke connection or cause that watch does not answer to requests.
|
||||
// To avoid this issue I perform some commands in the chain, but we should limit number of simultaneous commands
|
||||
|
||||
RequestCallback contactsCallback = new RequestCallback() {
|
||||
@Override
|
||||
public void call() {
|
||||
if (getHuaweiCoordinator().supportsContacts()) {
|
||||
GetContactsCount getContactsCount = new GetContactsCount(HuaweiSupportProvider.this);
|
||||
try {
|
||||
getContactsCount.doPerform();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error perform contacts count request", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RequestCallback appsCallback= new RequestCallback() {
|
||||
@Override
|
||||
public void call() {
|
||||
if (getHuaweiCoordinator().supportsAppParams()) {
|
||||
GetAppInfoParams getAppInfoParams = new GetAppInfoParams(HuaweiSupportProvider.this);
|
||||
getAppInfoParams.setFinalizeReq(contactsCallback);
|
||||
try {
|
||||
getAppInfoParams.doPerform();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error perform app info request", e);
|
||||
}
|
||||
} else {
|
||||
contactsCallback.call();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (getHuaweiCoordinator().supportsWatchfaceParams()) {
|
||||
GetWatchfaceParams getWatchfaceParams = new GetWatchfaceParams(this);
|
||||
getWatchfaceParams.setFinalizeReq(appsCallback);
|
||||
getWatchfaceParams.doPerform();
|
||||
} else {
|
||||
appsCallback.call();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
GB.toast(getContext(), "Initialize dynamic services of Huawei device failed", Toast.LENGTH_SHORT, GB.ERROR,
|
||||
e);
|
||||
@ -2103,6 +2142,22 @@ public class HuaweiSupportProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public void onSetContacts(ArrayList<? extends Contact> contacts) {
|
||||
SendSetContactsRequest sendSetContactsRequest = new SendSetContactsRequest(
|
||||
this,
|
||||
contacts,
|
||||
this.getHuaweiCoordinator().getContactsSlotCount(getDevice())
|
||||
);
|
||||
try {
|
||||
sendSetContactsRequest.doPerform();
|
||||
} catch (IOException e) {
|
||||
// TODO: Use translatable string
|
||||
GB.toast(context, "Failed to set contacts", Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||
LOG.error("Failed to send set contacts request", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean startBatteryRunnerDelayed() {
|
||||
int interval_minutes = GBApplication.getDevicePrefs(gbDevice).getBatteryPollingIntervalMinutes();
|
||||
int interval = interval_minutes * 60 * 1000;
|
||||
|
@ -0,0 +1,40 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Contacts;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class GetContactsCount extends Request {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GetContactsCount.class);
|
||||
|
||||
public GetContactsCount(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
this.serviceId = Contacts.id;
|
||||
this.commandId = Contacts.ContactsCount.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
return new Contacts.ContactsCount.Request(paramsProvider).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws ResponseParseException {
|
||||
LOG.debug("handle contacts count");
|
||||
|
||||
if (!(receivedPacket instanceof Contacts.ContactsCount.Response))
|
||||
throw new ResponseTypeMismatchException(receivedPacket, Contacts.ContactsCount.Response.class);
|
||||
|
||||
int count = ((Contacts.ContactsCount.Response) receivedPacket).maxCount;
|
||||
this.supportProvider.getHuaweiCoordinator().saveMaxContactsCount(count);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Contacts;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Contact;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SendSetContactsRequest extends Request {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SendSetContactsRequest.class);
|
||||
|
||||
private final ArrayList<? extends Contact> contacts;
|
||||
int maxCount;
|
||||
|
||||
public SendSetContactsRequest(HuaweiSupportProvider support,ArrayList<? extends Contact> contacts, int maxCount) {
|
||||
super(support);
|
||||
this.serviceId = Contacts.id;
|
||||
this.commandId = Contacts.ContactsSet.id;
|
||||
this.contacts = contacts;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
return new Contacts.ContactsSet.Request(paramsProvider, this.contacts, this.maxCount).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() {
|
||||
if (receivedPacket instanceof Contacts.ContactsSet.Response) {
|
||||
if (((Contacts.ContactsSet.Response) receivedPacket).isOk) {
|
||||
LOG.debug("Contacts set");
|
||||
} else {
|
||||
LOG.warn("Error set contacts");
|
||||
}
|
||||
} else {
|
||||
LOG.error("Set Contacts response is not of type ContactsSet response");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user