mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-10 17:11:56 +01:00
Huawei: notifications: remove from watch and replies support
This commit is contained in:
parent
9ca2cd4e8f
commit
559ccda676
@ -654,6 +654,36 @@ public class HuaweiCoordinator {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsNotificationsTimestamp() {
|
||||||
|
if (supportsExpandCapability())
|
||||||
|
return supportsExpandCapability(77);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsNotificationsReply() {
|
||||||
|
if (supportsExpandCapability())
|
||||||
|
return supportsExpandCapability(73);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsNotificationsRepeatedNotify() {
|
||||||
|
if (supportsExpandCapability())
|
||||||
|
return supportsExpandCapability(94);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsNotificationsSyncKey() {
|
||||||
|
if (supportsExpandCapability())
|
||||||
|
return supportsExpandCapability(89);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public boolean supportsNotificationsRemoveSingle() {
|
||||||
|
if (supportsExpandCapability())
|
||||||
|
return supportsExpandCapability(120);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean supportsPromptPushMessage () {
|
public boolean supportsPromptPushMessage () {
|
||||||
// do not ask for capabilities under specific condition
|
// do not ask for capabilities under specific condition
|
||||||
|
@ -482,6 +482,8 @@ public class HuaweiPacket {
|
|||||||
return new Notifications.NotificationConstraints.Response(paramsProvider).fromPacket(this);
|
return new Notifications.NotificationConstraints.Response(paramsProvider).fromPacket(this);
|
||||||
case Notifications.NotificationCapabilities.id:
|
case Notifications.NotificationCapabilities.id:
|
||||||
return new Notifications.NotificationCapabilities.Response(paramsProvider).fromPacket(this);
|
return new Notifications.NotificationCapabilities.Response(paramsProvider).fromPacket(this);
|
||||||
|
case Notifications.NotificationReply.id:
|
||||||
|
return new Notifications.NotificationReply.ReplyResponse(paramsProvider).fromPacket(this);
|
||||||
default:
|
default:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets;
|
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||||
@ -33,6 +35,23 @@ public class Notifications {
|
|||||||
public static class NotificationActionRequest extends HuaweiPacket {
|
public static class NotificationActionRequest extends HuaweiPacket {
|
||||||
public static final byte id = 0x01;
|
public static final byte id = 0x01;
|
||||||
|
|
||||||
|
public static class AdditionalParams {
|
||||||
|
|
||||||
|
public boolean supportsSyncKey = false;
|
||||||
|
public boolean supportsRepeatedNotify = false;
|
||||||
|
public boolean supportsRemoveSingle = false;
|
||||||
|
public boolean supportsReply = false;
|
||||||
|
public boolean supportsTimestamp = false;
|
||||||
|
|
||||||
|
public String notificationKey = "";
|
||||||
|
public int notificationId = -1;
|
||||||
|
public String channelId = "";
|
||||||
|
public byte subscriptionId = 0;
|
||||||
|
public String address = "";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: support other types of notifications
|
// TODO: support other types of notifications
|
||||||
// public static final int send = 0x01;
|
// public static final int send = 0x01;
|
||||||
// public static final int notificationId = 0x01;
|
// public static final int notificationId = 0x01;
|
||||||
@ -54,13 +73,14 @@ public class Notifications {
|
|||||||
|
|
||||||
public NotificationActionRequest(
|
public NotificationActionRequest(
|
||||||
ParamsProvider paramsProvider,
|
ParamsProvider paramsProvider,
|
||||||
short notificationId,
|
short msgId,
|
||||||
byte notificationType,
|
byte notificationType,
|
||||||
int encoding,
|
int encoding,
|
||||||
String titleContent,
|
String titleContent,
|
||||||
String senderContent,
|
String senderContent,
|
||||||
String bodyContent,
|
String bodyContent,
|
||||||
String sourceAppId
|
String sourceAppId,
|
||||||
|
AdditionalParams addParams
|
||||||
) {
|
) {
|
||||||
super(paramsProvider);
|
super(paramsProvider);
|
||||||
|
|
||||||
@ -70,7 +90,7 @@ public class Notifications {
|
|||||||
// TODO: Add notification information per type if necessary
|
// TODO: Add notification information per type if necessary
|
||||||
|
|
||||||
this.tlv = new HuaweiTLV()
|
this.tlv = new HuaweiTLV()
|
||||||
.put(0x01, notificationId)
|
.put(0x01, msgId)
|
||||||
.put(0x02, notificationType)
|
.put(0x02, notificationType)
|
||||||
.put(0x03, true); // This used to be vibrate, but doesn't work
|
.put(0x03, true); // This used to be vibrate, but doesn't work
|
||||||
|
|
||||||
@ -105,6 +125,32 @@ public class Notifications {
|
|||||||
if (sourceAppId != null)
|
if (sourceAppId != null)
|
||||||
this.tlv.put(0x11, sourceAppId);
|
this.tlv.put(0x11, sourceAppId);
|
||||||
|
|
||||||
|
if(addParams != null) {
|
||||||
|
if (addParams.supportsSyncKey)
|
||||||
|
this.tlv.put(0x18, (addParams.notificationKey != null) ? addParams.notificationKey : "");
|
||||||
|
|
||||||
|
//this.tlv.put(0x12, "msg"); //"msg" or "imcall", maybe other - category, if not empty and productType>=34
|
||||||
|
|
||||||
|
//if(addParams.repeatedNotifySupports) {
|
||||||
|
// this.tlv.put(0x13, 0); // 0x13 - reminder 15 = vibrate, 0 - default
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (addParams.supportsReply && notificationType == NotificationType.sms) {
|
||||||
|
this.tlv.put(0x14, addParams.subscriptionId);
|
||||||
|
this.tlv.put(0x17, addParams.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addParams.supportsRepeatedNotify || addParams.supportsRemoveSingle) {
|
||||||
|
this.tlv.put(0x19, (addParams.notificationKey != null) ? addParams.notificationKey : "");
|
||||||
|
this.tlv.put(0x20, addParams.notificationId);
|
||||||
|
this.tlv.put(0x1d, (addParams.channelId != null) ? addParams.channelId : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addParams.supportsTimestamp) {
|
||||||
|
this.tlv.put(0x15, (int) (System.currentTimeMillis() / 1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.complete = true;
|
this.complete = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,23 +204,23 @@ public class Notifications {
|
|||||||
.getObject(0x90);
|
.getObject(0x90);
|
||||||
for (HuaweiTLV subContainer : container.getObjects(0x91)) {
|
for (HuaweiTLV subContainer : container.getObjects(0x91)) {
|
||||||
if (subContainer.getByte(0x12) == 0x01) {
|
if (subContainer.getByte(0x12) == 0x01) {
|
||||||
putByteBuffer(constraints, NotificationConstraintsType.contentFormat, new byte[] {0x02}); //Always 0x02 even if gadget report 0x03
|
putByteBuffer(constraints, NotificationConstraintsType.contentFormat, new byte[]{0x02}); //Always 0x02 even if gadget report 0x03
|
||||||
putByteBuffer(constraints, NotificationConstraintsType.contentLength, subContainer.getBytes(0x14));
|
putByteBuffer(constraints, NotificationConstraintsType.contentLength, subContainer.getBytes(0x14));
|
||||||
}
|
}
|
||||||
if (subContainer.getByte(0x12) == 0x05) {
|
if (subContainer.getByte(0x12) == 0x05) {
|
||||||
constraints.putShort(NotificationConstraintsType.yellowPagesSupport,(short)0x01);
|
constraints.putShort(NotificationConstraintsType.yellowPagesSupport, (short) 0x01);
|
||||||
putByteBuffer(constraints, NotificationConstraintsType.yellowPagesFormat,subContainer.getBytes(0x13));
|
putByteBuffer(constraints, NotificationConstraintsType.yellowPagesFormat, subContainer.getBytes(0x13));
|
||||||
putByteBuffer(constraints, NotificationConstraintsType.yellowPagesLength,subContainer.getBytes(0x14));
|
putByteBuffer(constraints, NotificationConstraintsType.yellowPagesLength, subContainer.getBytes(0x14));
|
||||||
}
|
}
|
||||||
if (subContainer.getByte(0x12) == 0x06) {
|
if (subContainer.getByte(0x12) == 0x06) {
|
||||||
constraints.putShort(NotificationConstraintsType.contentSignSupport,(short)0x01);
|
constraints.putShort(NotificationConstraintsType.contentSignSupport, (short) 0x01);
|
||||||
putByteBuffer(constraints, NotificationConstraintsType.contentSignFormat,subContainer.getBytes(0x13));
|
putByteBuffer(constraints, NotificationConstraintsType.contentSignFormat, subContainer.getBytes(0x13));
|
||||||
putByteBuffer(constraints, NotificationConstraintsType.contentSignLength,subContainer.getBytes(0x14));
|
putByteBuffer(constraints, NotificationConstraintsType.contentSignLength, subContainer.getBytes(0x14));
|
||||||
}
|
}
|
||||||
if (subContainer.getByte(0x12) == 0x07 ) {
|
if (subContainer.getByte(0x12) == 0x07) {
|
||||||
constraints.putShort(NotificationConstraintsType.incomingNumberSupport,(short)0x01);
|
constraints.putShort(NotificationConstraintsType.incomingNumberSupport, (short) 0x01);
|
||||||
putByteBuffer(constraints, NotificationConstraintsType.incomingNumberFormat,subContainer.getBytes(0x13));
|
putByteBuffer(constraints, NotificationConstraintsType.incomingNumberFormat, subContainer.getBytes(0x13));
|
||||||
putByteBuffer(constraints, NotificationConstraintsType.incomingNumberLength,subContainer.getBytes(0x14));
|
putByteBuffer(constraints, NotificationConstraintsType.incomingNumberLength, subContainer.getBytes(0x14));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
constraints.rewind();
|
constraints.rewind();
|
||||||
@ -250,7 +296,7 @@ public class Notifications {
|
|||||||
public static class Request extends HuaweiPacket {
|
public static class Request extends HuaweiPacket {
|
||||||
public Request(
|
public Request(
|
||||||
ParamsProvider paramsProvider
|
ParamsProvider paramsProvider
|
||||||
){
|
) {
|
||||||
super(paramsProvider);
|
super(paramsProvider);
|
||||||
this.serviceId = Notifications.id;
|
this.serviceId = Notifications.id;
|
||||||
this.commandId = id;
|
this.commandId = id;
|
||||||
@ -278,6 +324,36 @@ public class Notifications {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class NotificationRemoveAction extends HuaweiPacket {
|
||||||
|
public static final byte id = 0x06;
|
||||||
|
|
||||||
|
public NotificationRemoveAction(
|
||||||
|
ParamsProvider paramsProvider,
|
||||||
|
byte msgType,
|
||||||
|
String sourceAppId,
|
||||||
|
String notificationKey,
|
||||||
|
int notificationId,
|
||||||
|
String notificationChannelId,
|
||||||
|
String notificationCategory
|
||||||
|
) {
|
||||||
|
super(paramsProvider);
|
||||||
|
|
||||||
|
this.serviceId = Notifications.id;
|
||||||
|
this.commandId = id;
|
||||||
|
|
||||||
|
this.tlv = new HuaweiTLV()
|
||||||
|
.put(0x01, msgType)
|
||||||
|
.put(0x02, sourceAppId)
|
||||||
|
.put(0x03, notificationKey)
|
||||||
|
.put(0x04, notificationId)
|
||||||
|
.put(0x05, notificationChannelId);
|
||||||
|
if (notificationCategory != null && !TextUtils.isEmpty(notificationCategory))
|
||||||
|
this.tlv.put(0x06, notificationCategory); // category
|
||||||
|
|
||||||
|
this.complete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class WearMessagePushRequest extends HuaweiPacket {
|
public static class WearMessagePushRequest extends HuaweiPacket {
|
||||||
public static final byte id = 0x08;
|
public static final byte id = 0x08;
|
||||||
|
|
||||||
@ -297,4 +373,62 @@ public class Notifications {
|
|||||||
this.complete = true;
|
this.complete = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class NotificationReply {
|
||||||
|
public static final byte id = 0x10;
|
||||||
|
public static class ReplyResponse extends HuaweiPacket {
|
||||||
|
public int type = 0;
|
||||||
|
public int encoding = 0; // 3 - "utf-16"
|
||||||
|
public int subId = 0;
|
||||||
|
public String sender;
|
||||||
|
public String key;
|
||||||
|
public String text;
|
||||||
|
|
||||||
|
public ReplyResponse(ParamsProvider paramsProvider) {
|
||||||
|
super(paramsProvider);
|
||||||
|
|
||||||
|
this.serviceId = MusicControl.id;
|
||||||
|
this.commandId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTlv() throws ParseException {
|
||||||
|
if (this.tlv.contains(0x01))
|
||||||
|
this.type = this.tlv.getAsInteger(0x01);
|
||||||
|
if (this.tlv.contains(0x02))
|
||||||
|
this.encoding = this.tlv.getAsInteger(0x02);
|
||||||
|
if (this.tlv.contains(0x03))
|
||||||
|
this.subId = this.tlv.getAsInteger(0x03);
|
||||||
|
if (this.tlv.contains(0x04))
|
||||||
|
this.key = this.tlv.getString(0x04);
|
||||||
|
if (this.tlv.contains(0x05))
|
||||||
|
this.sender = this.tlv.getString(0x05);
|
||||||
|
if (this.tlv.contains(0x06))
|
||||||
|
this.text = this.tlv.getString(0x06);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: send ack if required, 7f on error.
|
||||||
|
public static class ReplyAck extends HuaweiPacket {
|
||||||
|
|
||||||
|
public ReplyAck(
|
||||||
|
ParamsProvider paramsProvider,
|
||||||
|
byte code
|
||||||
|
) {
|
||||||
|
super(paramsProvider);
|
||||||
|
|
||||||
|
this.serviceId = Notifications.id;
|
||||||
|
this.commandId = id;
|
||||||
|
|
||||||
|
this.tlv = new HuaweiTLV()
|
||||||
|
.put(0x07, code);
|
||||||
|
|
||||||
|
this.complete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Menstrual;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Menstrual;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.MusicControl;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.MusicControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.P2P;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.P2P;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Watchface;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Watchface;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather;
|
||||||
@ -127,6 +128,7 @@ public class AsynchronousResponse {
|
|||||||
handleEphemeris(response);
|
handleEphemeris(response);
|
||||||
handleEphemerisUploadService(response);
|
handleEphemerisUploadService(response);
|
||||||
handleAsyncBattery(response);
|
handleAsyncBattery(response);
|
||||||
|
handleNotifications(response);
|
||||||
} catch (Request.ResponseParseException e) {
|
} catch (Request.ResponseParseException e) {
|
||||||
LOG.error("Response parse exception", e);
|
LOG.error("Response parse exception", e);
|
||||||
}
|
}
|
||||||
@ -725,4 +727,14 @@ public class AsynchronousResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleNotifications(HuaweiPacket response) {
|
||||||
|
if (response.serviceId == Notifications.id && response.commandId == Notifications.NotificationReply.id) {
|
||||||
|
if (!(response instanceof Notifications.NotificationReply.ReplyResponse)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG.info("Notification response");
|
||||||
|
support.getHuaweiNotificationsManager().onReplyResponse((Notifications.NotificationReply.ReplyResponse) response);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,11 @@ public class HuaweiBRSupport extends AbstractBTBRDeviceSupport {
|
|||||||
supportProvider.onNotification(notificationSpec);
|
supportProvider.onNotification(notificationSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeleteNotification(int id) {
|
||||||
|
supportProvider.onDeleteNotification(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSetTime() {
|
public void onSetTime() {
|
||||||
supportProvider.onSetTime();
|
supportProvider.onSetTime();
|
||||||
|
@ -0,0 +1,140 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotificationRequest;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotificationRemoveRequest;
|
||||||
|
|
||||||
|
public class HuaweiNotificationsManager {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(HuaweiNotificationsManager.class);
|
||||||
|
|
||||||
|
private final HuaweiSupportProvider support;
|
||||||
|
private final Queue<NotificationSpec> notificationSpecCache = new LinkedList<>();
|
||||||
|
|
||||||
|
public HuaweiNotificationsManager(HuaweiSupportProvider support) {
|
||||||
|
this.support = support;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNotificationToCache(NotificationSpec notificationSpec) {
|
||||||
|
// TODO: rewrite this
|
||||||
|
if (notificationSpecCache.size() > 10)
|
||||||
|
notificationSpecCache.poll();
|
||||||
|
|
||||||
|
Iterator<NotificationSpec> iterator = notificationSpecCache.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
NotificationSpec e = iterator.next();
|
||||||
|
if (e.getId() == notificationSpec.getId()) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notificationSpecCache.offer(notificationSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onNotification(NotificationSpec notificationSpec) {
|
||||||
|
|
||||||
|
addNotificationToCache(notificationSpec);
|
||||||
|
|
||||||
|
SendNotificationRequest sendNotificationReq = new SendNotificationRequest(this.support);
|
||||||
|
try {
|
||||||
|
sendNotificationReq.buildNotificationTLVFromNotificationSpec(notificationSpec);
|
||||||
|
sendNotificationReq.doPerform();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("Sending notification failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDeleteNotification(int id) {
|
||||||
|
if (!support.getHuaweiCoordinator().supportsNotificationsRepeatedNotify() && !support.getHuaweiCoordinator().supportsNotificationsRemoveSingle()) {
|
||||||
|
LOG.info("Delete notification is not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NotificationSpec notificationSpec = null;
|
||||||
|
Iterator<NotificationSpec> iterator = notificationSpecCache.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
notificationSpec = iterator.next();
|
||||||
|
if (notificationSpec.getId() == id) {
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (notificationSpec == null) {
|
||||||
|
LOG.info("Notification is not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
SendNotificationRemoveRequest sendNotificationReq = new SendNotificationRemoveRequest(this.support,
|
||||||
|
SendNotificationRequest.getNotificationType(notificationSpec.type), // notificationType
|
||||||
|
notificationSpec.sourceAppId,
|
||||||
|
notificationSpec.key,
|
||||||
|
id,
|
||||||
|
"", // TODO:
|
||||||
|
null);
|
||||||
|
sendNotificationReq.doPerform();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("Sending notification remove failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onReplyResponse(Notifications.NotificationReply.ReplyResponse response) {
|
||||||
|
LOG.info(" KEY: {}, Text: {}", response.key, response.text);
|
||||||
|
if(!this.support.getHuaweiCoordinator().supportsNotificationsReply()) {
|
||||||
|
LOG.info("Reply is not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (TextUtils.isEmpty(response.key) || TextUtils.isEmpty(response.text)) {
|
||||||
|
LOG.info("Reply is empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(response.type != 1 && response.type != 2) {
|
||||||
|
LOG.info("Reply: only type 1 and 2 supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NotificationSpec notificationSpec = null;
|
||||||
|
for (NotificationSpec spec : notificationSpecCache) {
|
||||||
|
notificationSpec = spec;
|
||||||
|
if (notificationSpec.key.equals(response.key)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (notificationSpec == null) {
|
||||||
|
LOG.info("Notification for reply is not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final GBDeviceEventNotificationControl deviceEvtNotificationControl = new GBDeviceEventNotificationControl();
|
||||||
|
deviceEvtNotificationControl.handle = notificationSpec.getId();
|
||||||
|
deviceEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.REPLY;
|
||||||
|
deviceEvtNotificationControl.reply = response.text;
|
||||||
|
if (notificationSpec.type.equals(NotificationType.GENERIC_PHONE) || notificationSpec.type.equals(NotificationType.GENERIC_SMS)) {
|
||||||
|
deviceEvtNotificationControl.phoneNumber = notificationSpec.phoneNumber;
|
||||||
|
} else {
|
||||||
|
final boolean hasActions = (null != notificationSpec.attachedActions && !notificationSpec.attachedActions.isEmpty());
|
||||||
|
if (hasActions) {
|
||||||
|
for (int i = 0; i < notificationSpec.attachedActions.size(); i++) {
|
||||||
|
final NotificationSpec.Action action = notificationSpec.attachedActions.get(i);
|
||||||
|
if (action.type == NotificationSpec.Action.TYPE_WEARABLE_REPLY || action.type == NotificationSpec.Action.TYPE_SYNTECTIC_REPLY_PHONENR) {
|
||||||
|
deviceEvtNotificationControl.handle = action.handle; //handle of wearable action is needed
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
this.support.evaluateGBDeviceEvent(deviceEvtNotificationControl);
|
||||||
|
//TODO: maybe should be send reply. Service: 0x2, command: 0x10, tlv 7 and/or 1, type byte, 7f on error
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -245,9 +245,12 @@ public class HuaweiSupportProvider {
|
|||||||
|
|
||||||
protected HuaweiMusicManager huaweiMusicManager = new HuaweiMusicManager(this);
|
protected HuaweiMusicManager huaweiMusicManager = new HuaweiMusicManager(this);
|
||||||
|
|
||||||
|
protected HuaweiNotificationsManager huaweiNotificationsManager = new HuaweiNotificationsManager(this);
|
||||||
|
|
||||||
//TODO: we need only one instance of manager and all it services.
|
//TODO: we need only one instance of manager and all it services.
|
||||||
protected HuaweiP2PManager huaweiP2PManager = new HuaweiP2PManager(this);
|
protected HuaweiP2PManager huaweiP2PManager = new HuaweiP2PManager(this);
|
||||||
|
|
||||||
|
|
||||||
public HuaweiCoordinatorSupplier getCoordinator() {
|
public HuaweiCoordinatorSupplier getCoordinator() {
|
||||||
return ((HuaweiCoordinatorSupplier) this.gbDevice.getDeviceCoordinator());
|
return ((HuaweiCoordinatorSupplier) this.gbDevice.getDeviceCoordinator());
|
||||||
}
|
}
|
||||||
@ -276,6 +279,10 @@ public class HuaweiSupportProvider {
|
|||||||
return huaweiEphemerisManager;
|
return huaweiEphemerisManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HuaweiNotificationsManager getHuaweiNotificationsManager() {
|
||||||
|
return huaweiNotificationsManager;
|
||||||
|
}
|
||||||
|
|
||||||
public HuaweiMusicManager getHuaweiMusicManager() {
|
public HuaweiMusicManager getHuaweiMusicManager() {
|
||||||
return huaweiMusicManager;
|
return huaweiMusicManager;
|
||||||
}
|
}
|
||||||
@ -1408,21 +1415,17 @@ public class HuaweiSupportProvider {
|
|||||||
}
|
}
|
||||||
return msgId;
|
return msgId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onNotification(NotificationSpec notificationSpec) {
|
public void onNotification(NotificationSpec notificationSpec) {
|
||||||
if (!GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREF_NOTIFICATION_ENABLE, false)) {
|
if (!GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREF_NOTIFICATION_ENABLE, false)) {
|
||||||
// Don't send notifications when they are disabled
|
// Don't send notifications when they are disabled
|
||||||
LOG.info("Stopped notification as they are disabled.");
|
LOG.info("Stopped notification as they are disabled.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
huaweiNotificationsManager.onNotification(notificationSpec);
|
||||||
SendNotificationRequest sendNotificationReq = new SendNotificationRequest(this);
|
|
||||||
try {
|
|
||||||
sendNotificationReq.buildNotificationTLVFromNotificationSpec(notificationSpec);
|
|
||||||
sendNotificationReq.doPerform();
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.error("Sending notification failed", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onDeleteNotification(int id) {
|
||||||
|
huaweiNotificationsManager.onDeleteNotification(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDateFormat() {
|
public void setDateFormat() {
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
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.Notifications;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||||
|
|
||||||
|
public class SendNotificationRemoveRequest extends Request {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(SendNotificationRemoveRequest.class);
|
||||||
|
|
||||||
|
private final byte notificationType;
|
||||||
|
private final String sourceAppId;
|
||||||
|
private final String notificationKey;
|
||||||
|
private final int notificationId;
|
||||||
|
private final String notificationChannelId;
|
||||||
|
private final String notificationCategory;
|
||||||
|
|
||||||
|
public SendNotificationRemoveRequest(HuaweiSupportProvider support, byte notificationType, String sourceAppId, String notificationKey, int notificationId, String notificationChannelId, String notificationCategory) {
|
||||||
|
super(support);
|
||||||
|
this.serviceId = Notifications.id;
|
||||||
|
this.commandId = Notifications.NotificationRemoveAction.id;
|
||||||
|
this.notificationType = notificationType;
|
||||||
|
this.sourceAppId = sourceAppId;
|
||||||
|
this.notificationKey = notificationKey;
|
||||||
|
this.notificationId = notificationId;
|
||||||
|
this.notificationChannelId = notificationChannelId;
|
||||||
|
this.notificationCategory = notificationCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||||
|
try {
|
||||||
|
return new Notifications.NotificationRemoveAction(
|
||||||
|
paramsProvider,
|
||||||
|
this.notificationType,
|
||||||
|
this.sourceAppId,
|
||||||
|
this.notificationKey,
|
||||||
|
this.notificationId,
|
||||||
|
this.notificationChannelId,
|
||||||
|
this.notificationCategory).serialize();
|
||||||
|
} catch (HuaweiPacket.CryptoException e) {
|
||||||
|
throw new RequestCreationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processResponse() {
|
||||||
|
LOG.debug("handle NotificationRemove");
|
||||||
|
}
|
||||||
|
}
|
@ -66,6 +66,18 @@ public class SendNotificationRequest extends Request {
|
|||||||
body = notificationSpec.body.substring(0x0, supportProvider.getHuaweiCoordinator().getContentLength() - 0xD);
|
body = notificationSpec.body.substring(0x0, supportProvider.getHuaweiCoordinator().getContentLength() - 0xD);
|
||||||
body += "...";
|
body += "...";
|
||||||
}
|
}
|
||||||
|
Notifications.NotificationActionRequest.AdditionalParams params = new Notifications.NotificationActionRequest.AdditionalParams();
|
||||||
|
|
||||||
|
params.supportsSyncKey = supportProvider.getHuaweiCoordinator().supportsNotificationsSyncKey();
|
||||||
|
params.supportsRepeatedNotify = supportProvider.getHuaweiCoordinator().supportsNotificationsRepeatedNotify();
|
||||||
|
params.supportsRemoveSingle = supportProvider.getHuaweiCoordinator().supportsNotificationsRemoveSingle();
|
||||||
|
params.supportsReply = supportProvider.getHuaweiCoordinator().supportsNotificationsReply();
|
||||||
|
params.supportsTimestamp = supportProvider.getHuaweiCoordinator().supportsNotificationsTimestamp();
|
||||||
|
|
||||||
|
params.notificationId = notificationSpec.getId();
|
||||||
|
params.notificationKey = notificationSpec.key;
|
||||||
|
|
||||||
|
|
||||||
this.packet = new Notifications.NotificationActionRequest(
|
this.packet = new Notifications.NotificationActionRequest(
|
||||||
paramsProvider,
|
paramsProvider,
|
||||||
supportProvider.getNotificationId(),
|
supportProvider.getNotificationId(),
|
||||||
@ -74,7 +86,8 @@ public class SendNotificationRequest extends Request {
|
|||||||
title,
|
title,
|
||||||
notificationSpec.sender,
|
notificationSpec.sender,
|
||||||
body,
|
body,
|
||||||
notificationSpec.sourceAppId
|
notificationSpec.sourceAppId,
|
||||||
|
params
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +101,7 @@ public class SendNotificationRequest extends Request {
|
|||||||
callSpec.name,
|
callSpec.name,
|
||||||
callSpec.name,
|
callSpec.name,
|
||||||
callSpec.name,
|
callSpec.name,
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ public class StopNotificationRequest extends Request {
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
).serialize();
|
).serialize();
|
||||||
} catch (HuaweiPacket.CryptoException e) {
|
} catch (HuaweiPacket.CryptoException e) {
|
||||||
|
@ -106,7 +106,8 @@ public class TestNotifications {
|
|||||||
titleContent,
|
titleContent,
|
||||||
senderContent,
|
senderContent,
|
||||||
bodyContent,
|
bodyContent,
|
||||||
sourceAppId
|
sourceAppId,
|
||||||
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
Assert.assertEquals(0x02, request.serviceId);
|
Assert.assertEquals(0x02, request.serviceId);
|
||||||
|
Loading…
Reference in New Issue
Block a user