mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-09 03:37:03 +01:00
Huawei: Basic support for the installation of the applications
This commit is contained in:
parent
d75ae6b54d
commit
e54fd95a8b
@ -0,0 +1,65 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class HuaweiAppParser {
|
||||||
|
|
||||||
|
public static class AppFileEntry {
|
||||||
|
public String filename;
|
||||||
|
public String folder;
|
||||||
|
public String unknown;
|
||||||
|
public byte[] content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String packageName;
|
||||||
|
private final ArrayList<AppFileEntry> entries = new ArrayList<>();
|
||||||
|
|
||||||
|
public String getPackageName() {
|
||||||
|
return packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getEntryContent(String filename) {
|
||||||
|
for(AppFileEntry en: entries) {
|
||||||
|
if(en.filename.equals(filename)) {
|
||||||
|
return en.content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] readData(ByteBuffer data) {
|
||||||
|
int len = data.getInt();
|
||||||
|
byte[] newPayload = new byte[len];
|
||||||
|
data.get(newPayload, 0, len);
|
||||||
|
return newPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readString(ByteBuffer data) {
|
||||||
|
return new String(readData(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parseData(byte[] in) throws Exception {
|
||||||
|
|
||||||
|
ByteBuffer data = ByteBuffer.wrap(in);
|
||||||
|
|
||||||
|
byte magic = data.get();
|
||||||
|
if(magic != (byte)0xbe){
|
||||||
|
throw new Exception("Invalid magic");
|
||||||
|
}
|
||||||
|
this.packageName = readString(data);
|
||||||
|
while(data.remaining() > 0) {
|
||||||
|
int pos = data.position();
|
||||||
|
byte a = data.get();
|
||||||
|
if(a != 0x00)
|
||||||
|
break;
|
||||||
|
data.position(pos);
|
||||||
|
AppFileEntry ent = new AppFileEntry();
|
||||||
|
ent.filename = readString(data);
|
||||||
|
ent.folder = readString(data);
|
||||||
|
ent.unknown = readString(data);
|
||||||
|
ent.content = readData(data);
|
||||||
|
entries.add(ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,6 @@ import android.content.SharedPreferences;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
@ -37,6 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActi
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications.NotificationConstraintsType;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Notifications.NotificationConstraintsType;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Watchface;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Watchface;
|
||||||
@ -59,6 +59,8 @@ public class HuaweiCoordinator {
|
|||||||
|
|
||||||
private Watchface.WatchfaceDeviceParams watchfaceDeviceParams;
|
private Watchface.WatchfaceDeviceParams watchfaceDeviceParams;
|
||||||
|
|
||||||
|
private App.AppDeviceParams appDeviceParams;
|
||||||
|
|
||||||
private final HuaweiCoordinatorSupplier parent;
|
private final HuaweiCoordinatorSupplier parent;
|
||||||
|
|
||||||
private boolean transactionCrypted=true;
|
private boolean transactionCrypted=true;
|
||||||
@ -405,6 +407,8 @@ public class HuaweiCoordinator {
|
|||||||
|
|
||||||
public boolean supportsWatchfaceParams(){ return supportsCommandForService(0x27, 0x01);}
|
public boolean supportsWatchfaceParams(){ return supportsCommandForService(0x27, 0x01);}
|
||||||
|
|
||||||
|
public boolean supportsAppParams(){ return supportsCommandForService(0x2a, 0x06);}
|
||||||
|
|
||||||
public boolean supportsWeather() {
|
public boolean supportsWeather() {
|
||||||
return supportsCommandForService(0x0f, 0x01);
|
return supportsCommandForService(0x0f, 0x01);
|
||||||
}
|
}
|
||||||
@ -584,20 +588,26 @@ public class HuaweiCoordinator {
|
|||||||
this.watchfaceDeviceParams = watchfaceDeviceParams;
|
this.watchfaceDeviceParams = watchfaceDeviceParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAppDeviceParams(App.AppDeviceParams appDeviceParams) {
|
||||||
|
this.appDeviceParams = appDeviceParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public App.AppDeviceParams getAppDeviceParams() {
|
||||||
|
return appDeviceParams;
|
||||||
|
}
|
||||||
|
|
||||||
public Class<? extends Activity> getAppManagerActivity() {
|
public Class<? extends Activity> getAppManagerActivity() {
|
||||||
return AppManagerActivity.class;
|
return AppManagerActivity.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getSupportsAppListFetching() {
|
public boolean getSupportsAppListFetching() { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getSupportsAppsManagement(GBDevice device) {
|
public boolean getSupportsAppsManagement(GBDevice device) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getSupportsInstalledAppManagement(GBDevice device) {
|
public boolean getSupportsInstalledAppManagement(GBDevice device) {
|
||||||
return false;
|
return this.supportsAppParams(); // NOTE: this check can be incorrect. But looks like it works
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getSupportsCachedAppManagement(GBDevice device) {
|
public boolean getSupportsCachedAppManagement(GBDevice device) {
|
||||||
|
@ -29,6 +29,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiAppManager;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiFwHelper;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiFwHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWatchfaceManager;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWatchfaceManager;
|
||||||
|
|
||||||
@ -56,6 +57,7 @@ public class HuaweiInstallHandler implements InstallHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(helper.isWatchface()) {
|
||||||
final HuaweiCoordinatorSupplier huaweiCoordinatorSupplier = (HuaweiCoordinatorSupplier) coordinator;
|
final HuaweiCoordinatorSupplier huaweiCoordinatorSupplier = (HuaweiCoordinatorSupplier) coordinator;
|
||||||
|
|
||||||
HuaweiWatchfaceManager.WatchfaceDescription description = helper.getWatchfaceDescription();
|
HuaweiWatchfaceManager.WatchfaceDescription description = helper.getWatchfaceDescription();
|
||||||
@ -99,13 +101,63 @@ public class HuaweiInstallHandler implements InstallHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
installItem.setDetails(description.version);
|
||||||
//installItem.setDetails(description.version);
|
|
||||||
|
|
||||||
installItem.setIcon(R.drawable.ic_watchface);
|
installItem.setIcon(R.drawable.ic_watchface);
|
||||||
installActivity.setInfoText(context.getString(R.string.watchface_install_info, installItem.getName(), description.version, description.author));
|
installActivity.setInfoText(context.getString(R.string.watchface_install_info, installItem.getName(), description.version, description.author));
|
||||||
|
|
||||||
LOG.debug("Initialized HuaweiInstallHandler");
|
LOG.debug("Initialized HuaweiInstallHandler");
|
||||||
|
} else if (helper.isAPP()) {
|
||||||
|
final HuaweiCoordinatorSupplier huaweiCoordinatorSupplier = (HuaweiCoordinatorSupplier) coordinator;
|
||||||
|
|
||||||
|
String screenWindow = String.format("%d*%d", huaweiCoordinatorSupplier.getHuaweiCoordinator().getAppDeviceParams().height,
|
||||||
|
huaweiCoordinatorSupplier.getHuaweiCoordinator().getAppDeviceParams().width);
|
||||||
|
|
||||||
|
String screenShape = huaweiCoordinatorSupplier.getHuaweiCoordinator().getAppDeviceParams().screenShape;
|
||||||
|
|
||||||
|
HuaweiAppManager.AppConfig config = helper.getAppconfig();
|
||||||
|
|
||||||
|
this.valid = config.checkDistroFilters(screenShape, screenWindow);
|
||||||
|
|
||||||
|
installActivity.setInstallEnabled(true);
|
||||||
|
|
||||||
|
GenericItem installItem = new GenericItem();
|
||||||
|
|
||||||
|
if (helper.getWatchfacePreviewBitmap() != null) {
|
||||||
|
installItem.setPreview(helper.getWatchfacePreviewBitmap());
|
||||||
|
}
|
||||||
|
|
||||||
|
installItem.setName(config.bundleName);
|
||||||
|
installActivity.setInstallItem(installItem);
|
||||||
|
if (device.isBusy()) {
|
||||||
|
LOG.error("Firmware cannot be installed (device busy)");
|
||||||
|
installActivity.setInfoText("Firmware cannot be installed (device busy)");
|
||||||
|
installActivity.setInfoText(device.getBusyTask());
|
||||||
|
installActivity.setInstallEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device.isConnected()) {
|
||||||
|
LOG.error("Firmware cannot be installed (not connected or wrong device)");
|
||||||
|
installActivity.setInfoText("Firmware cannot be installed (not connected or wrong device)");
|
||||||
|
installActivity.setInstallEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.valid) {
|
||||||
|
LOG.error("App cannot be installed");
|
||||||
|
installActivity.setInstallEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
installItem.setDetails(config.version);
|
||||||
|
|
||||||
|
installItem.setIcon(R.drawable.ic_watchapp);
|
||||||
|
|
||||||
|
installActivity.setInfoText(context.getString(R.string.app_install_info, installItem.getName(), config.version, config.vendor));
|
||||||
|
|
||||||
|
LOG.debug("Initialized HuaweiInstallHandler");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Alarms;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Alarms;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.AccountRelated;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.AccountRelated;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Calls;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Calls;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.CameraRemote;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.CameraRemote;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService0A;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService0A;
|
||||||
@ -616,6 +617,16 @@ public class HuaweiPacket {
|
|||||||
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
case App.id:
|
||||||
|
switch (this.commandId) {
|
||||||
|
case App.AppNames.id:
|
||||||
|
return new App.AppNames.Response(paramsProvider).fromPacket(this);
|
||||||
|
case App.AppInfoParams.id:
|
||||||
|
return new App.AppInfoParams.Response(paramsProvider).fromPacket(this);
|
||||||
|
default:
|
||||||
|
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
||||||
|
return this;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
||||||
return this;
|
return this;
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
||||||
|
|
||||||
|
public class App {
|
||||||
|
public static final byte id = 0x2a;
|
||||||
|
|
||||||
|
public static class AppDeviceParams {
|
||||||
|
public byte unknown1 = 0;
|
||||||
|
public int unknown2 = 0;
|
||||||
|
public String osVersion = "";
|
||||||
|
public String screenShape = "";
|
||||||
|
public int width = 0;
|
||||||
|
public int height = 0;
|
||||||
|
public int unknown3 = 0;
|
||||||
|
public String buildType = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InstalledAppInfo {
|
||||||
|
public String packageName;
|
||||||
|
public String version;
|
||||||
|
public int unknown1;
|
||||||
|
public String appName;
|
||||||
|
public int unknown2;
|
||||||
|
public int versionCode;
|
||||||
|
public byte unknown4;
|
||||||
|
public byte unknown6;
|
||||||
|
|
||||||
|
public InstalledAppInfo(HuaweiTLV tlv) throws HuaweiPacket.MissingTagException {
|
||||||
|
this.packageName = tlv.getString(0x03);
|
||||||
|
this.version = tlv.getString(0x04);
|
||||||
|
this.unknown1 = tlv.getInteger(0x05);
|
||||||
|
this.appName = tlv.getString(0x06);
|
||||||
|
this.unknown2 = tlv.getInteger(0x07);
|
||||||
|
this.versionCode = tlv.getInteger(0x09);
|
||||||
|
this.unknown4 = tlv.getByte(0x0a);
|
||||||
|
//{tag: b - Value: } -
|
||||||
|
this.unknown6 = tlv.getByte(0x0d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AppDelete {
|
||||||
|
public static final byte id = 0x01;
|
||||||
|
|
||||||
|
public static class Request extends HuaweiPacket {
|
||||||
|
public Request(ParamsProvider paramsProvider,
|
||||||
|
String packageName) {
|
||||||
|
super(paramsProvider);
|
||||||
|
this.serviceId = App.id;
|
||||||
|
this.commandId = id;
|
||||||
|
this.tlv = new HuaweiTLV()
|
||||||
|
.put(0x01, (byte)1)
|
||||||
|
.put(0x02, packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Response extends HuaweiPacket {
|
||||||
|
public Response (ParamsProvider paramsProvider) {
|
||||||
|
super(paramsProvider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AppNames {
|
||||||
|
public static final byte id = 0x03;
|
||||||
|
|
||||||
|
public static class Request extends HuaweiPacket {
|
||||||
|
public Request(ParamsProvider paramsProvider) {
|
||||||
|
super(paramsProvider);
|
||||||
|
this.serviceId = App.id;
|
||||||
|
this.commandId = id;
|
||||||
|
this.tlv = new HuaweiTLV()
|
||||||
|
.put(0x81);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Response extends HuaweiPacket {
|
||||||
|
|
||||||
|
public List<App.InstalledAppInfo> appInfoList;
|
||||||
|
public Response (ParamsProvider paramsProvider) {
|
||||||
|
super(paramsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTlv() throws HuaweiPacket.ParseException {
|
||||||
|
appInfoList = new ArrayList<>();
|
||||||
|
if(this.tlv.contains(0x81)) {
|
||||||
|
for (HuaweiTLV subTlv : this.tlv.getObject(0x81).getObjects(0x82)) {
|
||||||
|
appInfoList.add(new InstalledAppInfo(subTlv));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AppInfoParams {
|
||||||
|
public static final byte id = 0x06;
|
||||||
|
public static class Request extends HuaweiPacket {
|
||||||
|
|
||||||
|
public Request(ParamsProvider paramsProvider) {
|
||||||
|
super(paramsProvider);
|
||||||
|
this.serviceId = App.id;
|
||||||
|
this.commandId = id;
|
||||||
|
|
||||||
|
this.tlv = new HuaweiTLV()
|
||||||
|
.put(0x81);
|
||||||
|
|
||||||
|
this.complete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Response extends HuaweiPacket {
|
||||||
|
public AppDeviceParams params = new AppDeviceParams();
|
||||||
|
public Response (ParamsProvider paramsProvider) {
|
||||||
|
super(paramsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTlv() throws ParseException {
|
||||||
|
if(this.tlv.contains(0x81)) {
|
||||||
|
HuaweiTLV subTlv = this.tlv.getObject(0x81).getObject(0x82);
|
||||||
|
this.params.unknown1 = subTlv.getByte(0x03);
|
||||||
|
this.params.unknown2 = subTlv.getInteger(0x04);
|
||||||
|
this.params.osVersion = subTlv.getString(0x05);
|
||||||
|
this.params.screenShape = subTlv.getString(0x06);
|
||||||
|
this.params.width = subTlv.getShort(0x07);
|
||||||
|
this.params.height = subTlv.getShort(0x08);
|
||||||
|
this.params.unknown3 = subTlv.getInteger(0x09);
|
||||||
|
this.params.buildType = subTlv.getString(0x0a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -39,7 +39,8 @@ public class FileUpload {
|
|||||||
public static final byte watchface = 1;
|
public static final byte watchface = 1;
|
||||||
public static final byte music = 2;
|
public static final byte music = 2;
|
||||||
public static final byte backgroundImage = 3;
|
public static final byte backgroundImage = 3;
|
||||||
public static final byte app = 7;
|
public static final byte app = 6;
|
||||||
|
public static final byte firmware = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMes
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Calls;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Calls;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.CameraRemote;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.CameraRemote;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DeviceConfig;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DeviceConfig;
|
||||||
@ -117,6 +118,7 @@ public class AsynchronousResponse {
|
|||||||
handleFileUpload(response);
|
handleFileUpload(response);
|
||||||
handleWatchface(response);
|
handleWatchface(response);
|
||||||
handleCameraRemote(response);
|
handleCameraRemote(response);
|
||||||
|
handleApp(response);
|
||||||
} catch (Request.ResponseParseException e) {
|
} catch (Request.ResponseParseException e) {
|
||||||
LOG.error("Response parse exception", e);
|
LOG.error("Response parse exception", e);
|
||||||
}
|
}
|
||||||
@ -503,6 +505,22 @@ public class AsynchronousResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleApp(HuaweiPacket response) throws Request.ResponseParseException {
|
||||||
|
if (response.serviceId == App.id) {
|
||||||
|
if (response.commandId == 0x2) {
|
||||||
|
try {
|
||||||
|
byte status = response.getTlv().getByte(0x1);
|
||||||
|
if(status == (byte)0x66 || status == (byte)0x69) {
|
||||||
|
this.support.getHuaweiAppManager().requestAppList();
|
||||||
|
}
|
||||||
|
} catch (HuaweiPacket.MissingTagException e) {
|
||||||
|
LOG.error("Could not send watchface confirm request", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleWeatherCheck(HuaweiPacket response) {
|
private void handleWeatherCheck(HuaweiPacket response) {
|
||||||
if (response.serviceId == Weather.id && response.commandId == 0x04) {
|
if (response.serviceId == Weather.id && response.commandId == 0x04) {
|
||||||
// Send back ok
|
// Send back ok
|
||||||
|
@ -0,0 +1,162 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetAppNames;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendAppDelete;
|
||||||
|
|
||||||
|
public class HuaweiAppManager {
|
||||||
|
|
||||||
|
static Logger LOG = LoggerFactory.getLogger(HuaweiAppManager.class);
|
||||||
|
|
||||||
|
public static class AppConfig {
|
||||||
|
|
||||||
|
public String bundleName;
|
||||||
|
public String vendor;
|
||||||
|
public String version;
|
||||||
|
|
||||||
|
JSONObject distroFilters = null;
|
||||||
|
|
||||||
|
public AppConfig(String jsonStr) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject config = new JSONObject(jsonStr);
|
||||||
|
this.bundleName = config.getJSONObject("app").getString("bundleName");
|
||||||
|
this.vendor = config.getJSONObject("app").getString("vendor");
|
||||||
|
this.version = config.getJSONObject("app").getJSONObject("version").getString("name");
|
||||||
|
|
||||||
|
parseDistroFilters(config);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Error decode app config", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseDistroFilters(JSONObject config) {
|
||||||
|
try {
|
||||||
|
distroFilters = config.getJSONObject("module").getJSONObject("distroFilter");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Error decode app config distroFilter", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValInArray(JSONArray arr, String value) throws JSONException {
|
||||||
|
for (int i = 0; i < arr.length(); i++) {
|
||||||
|
if (arr.getString(i).equals(value))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkDistroFilters(String screenShape, String screenWindow) {
|
||||||
|
if (distroFilters == null)
|
||||||
|
return false;
|
||||||
|
try {
|
||||||
|
boolean screenShapeSupported = false;
|
||||||
|
boolean screenWindowSupported = false;
|
||||||
|
if (distroFilters.has("screenShape")) {
|
||||||
|
JSONArray values = distroFilters.getJSONObject("screenShape").getJSONArray("value");
|
||||||
|
String policy = distroFilters.getJSONObject("screenShape").getString("policy");
|
||||||
|
screenShapeSupported = isValInArray(values, screenShape) && policy.equals("include");
|
||||||
|
}
|
||||||
|
if (distroFilters.has("screenWindow")) {
|
||||||
|
JSONArray values = distroFilters.getJSONObject("screenWindow").getJSONArray("value");
|
||||||
|
String policy = distroFilters.getJSONObject("screenWindow").getString("policy");
|
||||||
|
screenWindowSupported = isValInArray(values, screenWindow) && policy.equals("include");
|
||||||
|
}
|
||||||
|
return screenShapeSupported && screenWindowSupported;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Error decode app config distroFilter", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final HuaweiSupportProvider support;
|
||||||
|
|
||||||
|
private List<App.InstalledAppInfo> installedAppList = null;
|
||||||
|
|
||||||
|
public HuaweiAppManager(HuaweiSupportProvider support) {
|
||||||
|
this.support = support;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInstalledAppList(List<App.InstalledAppInfo> installedAppList) {
|
||||||
|
this.installedAppList = installedAppList;
|
||||||
|
handleAppList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleAppList() {
|
||||||
|
if (this.installedAppList == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<GBDeviceApp> gbDeviceApps = new ArrayList<>();
|
||||||
|
|
||||||
|
for (final App.InstalledAppInfo appInfo : installedAppList) {
|
||||||
|
final UUID uuid = UUID.nameUUIDFromBytes(appInfo.packageName.getBytes());
|
||||||
|
GBDeviceApp gbDeviceApp = new GBDeviceApp(
|
||||||
|
uuid,
|
||||||
|
appInfo.appName,
|
||||||
|
"",
|
||||||
|
appInfo.version,
|
||||||
|
GBDeviceApp.Type.APP_GENERIC
|
||||||
|
);
|
||||||
|
gbDeviceApps.add(gbDeviceApp);
|
||||||
|
}
|
||||||
|
support.setGbWatchApps(gbDeviceApps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestAppList() {
|
||||||
|
if (!this.support.getHuaweiCoordinator().supportsAppParams())
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
GetAppNames getAppNames = new GetAppNames(support);
|
||||||
|
getAppNames.doPerform();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("Error request applications list", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean startApp(UUID uuid) {
|
||||||
|
if (this.installedAppList == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (final App.InstalledAppInfo appInfo : installedAppList) {
|
||||||
|
final UUID appUuid = UUID.nameUUIDFromBytes(appInfo.packageName.getBytes());
|
||||||
|
if (appUuid.equals(uuid))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean deleteApp(UUID uuid) {
|
||||||
|
if (this.installedAppList == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (final App.InstalledAppInfo appInfo : installedAppList) {
|
||||||
|
final UUID appUuid = UUID.nameUUIDFromBytes(appInfo.packageName.getBytes());
|
||||||
|
if (appUuid.equals(uuid)) {
|
||||||
|
try {
|
||||||
|
SendAppDelete sendAppDelete = new SendAppDelete(support, appInfo.packageName);
|
||||||
|
sendAppDelete.doPerform();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("Could not delete app: " + appInfo.packageName, e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -25,10 +25,13 @@ import android.net.Uri;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiAppParser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GBZipFile;
|
import nodomain.freeyourgadget.gadgetbridge.util.GBZipFile;
|
||||||
@ -47,6 +50,7 @@ public class HuaweiFwHelper {
|
|||||||
|
|
||||||
Bitmap watchfacePreviewBitmap;
|
Bitmap watchfacePreviewBitmap;
|
||||||
HuaweiWatchfaceManager.WatchfaceDescription watchfaceDescription;
|
HuaweiWatchfaceManager.WatchfaceDescription watchfaceDescription;
|
||||||
|
HuaweiAppManager.AppConfig appConfig;
|
||||||
Context mContext;
|
Context mContext;
|
||||||
|
|
||||||
public HuaweiFwHelper(final Uri uri, final Context context) {
|
public HuaweiFwHelper(final Uri uri, final Context context) {
|
||||||
@ -65,13 +69,67 @@ public class HuaweiFwHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void parseFile() {
|
private void parseFile() {
|
||||||
if (parseAsWatchFace()) {
|
if(parseAsApp()) {
|
||||||
|
assert appConfig.bundleName != null;
|
||||||
|
assert appConfig.distroFilters != null;
|
||||||
|
fileType = FileUpload.Filetype.app;
|
||||||
|
} else if (parseAsWatchFace()) {
|
||||||
assert watchfaceDescription.screen != null;
|
assert watchfaceDescription.screen != null;
|
||||||
assert watchfaceDescription.title != null;
|
assert watchfaceDescription.title != null;
|
||||||
fileType = FileUpload.Filetype.watchface;
|
fileType = FileUpload.Filetype.watchface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean parseAsApp() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
final UriHelper uriHelper = UriHelper.get(uri, this.mContext);
|
||||||
|
|
||||||
|
InputStream inputStream = uriHelper.openInputStream();
|
||||||
|
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
int nRead;
|
||||||
|
byte[] data = new byte[4];
|
||||||
|
|
||||||
|
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
|
||||||
|
buffer.write(data, 0, nRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.flush();
|
||||||
|
byte[] hap_data = buffer.toByteArray();
|
||||||
|
|
||||||
|
HuaweiAppParser app = new HuaweiAppParser();
|
||||||
|
app.parseData(hap_data);
|
||||||
|
|
||||||
|
byte[] config = app.getEntryContent("config.json");
|
||||||
|
if(config == null)
|
||||||
|
return false;
|
||||||
|
appConfig = new HuaweiAppManager.AppConfig(new String(config));
|
||||||
|
fileName = app.getPackageName() + "_INSTALL"; //TODO: INSTALL or UPDATE suffix
|
||||||
|
|
||||||
|
fw = hap_data;
|
||||||
|
fileSize = fw.length;
|
||||||
|
|
||||||
|
byte[] icon = app.getEntryContent("icon_small.png");
|
||||||
|
if(icon != null) {
|
||||||
|
watchfacePreviewBitmap = BitmapFactory.decodeByteArray(icon, 0, icon.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
LOG.error("The watchface file was not found.", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("General IO error occurred.", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Unknown error occurred.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
return fw;
|
return fw;
|
||||||
}
|
}
|
||||||
@ -137,8 +195,13 @@ public class HuaweiFwHelper {
|
|||||||
public boolean isWatchface() {
|
public boolean isWatchface() {
|
||||||
return fileType == FileUpload.Filetype.watchface;
|
return fileType == FileUpload.Filetype.watchface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAPP() {
|
||||||
|
return fileType == FileUpload.Filetype.app;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return isWatchface();
|
return isWatchface() || isAPP();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bitmap getWatchfacePreviewBitmap() {
|
public Bitmap getWatchfacePreviewBitmap() {
|
||||||
@ -149,6 +212,10 @@ public class HuaweiFwHelper {
|
|||||||
return watchfaceDescription;
|
return watchfaceDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HuaweiAppManager.AppConfig getAppconfig() {
|
||||||
|
return appConfig;
|
||||||
|
}
|
||||||
|
|
||||||
public byte getFileType() {
|
public byte getFileType() {
|
||||||
return fileType;
|
return fileType;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSett
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCameraRemote;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCameraRemote;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||||
@ -78,6 +79,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Alarm;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||||
@ -89,6 +91,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
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.AcceptAgreementsRequest;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetAppInfoParams;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetEventAlarmList;
|
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.GetGpsParameterRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetNotificationConstraintsRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetNotificationConstraintsRequest;
|
||||||
@ -204,6 +207,8 @@ public class HuaweiSupportProvider {
|
|||||||
|
|
||||||
protected HuaweiFileDownloadManager huaweiFileDownloadManager = new HuaweiFileDownloadManager(this);
|
protected HuaweiFileDownloadManager huaweiFileDownloadManager = new HuaweiFileDownloadManager(this);
|
||||||
|
|
||||||
|
protected HuaweiAppManager huaweiAppManager = new HuaweiAppManager(this);
|
||||||
|
|
||||||
public HuaweiCoordinatorSupplier getCoordinator() {
|
public HuaweiCoordinatorSupplier getCoordinator() {
|
||||||
return ((HuaweiCoordinatorSupplier) this.gbDevice.getDeviceCoordinator());
|
return ((HuaweiCoordinatorSupplier) this.gbDevice.getDeviceCoordinator());
|
||||||
}
|
}
|
||||||
@ -215,6 +220,9 @@ public class HuaweiSupportProvider {
|
|||||||
return huaweiWatchfaceManager;
|
return huaweiWatchfaceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HuaweiAppManager getHuaweiAppManager() {
|
||||||
|
return huaweiAppManager;
|
||||||
|
}
|
||||||
public HuaweiSupportProvider(HuaweiBRSupport support) {
|
public HuaweiSupportProvider(HuaweiBRSupport support) {
|
||||||
this.brSupport = support;
|
this.brSupport = support;
|
||||||
}
|
}
|
||||||
@ -802,6 +810,11 @@ public class HuaweiSupportProvider {
|
|||||||
SendCameraRemoteSetupEvent sendCameraRemoteSetupEvent = new SendCameraRemoteSetupEvent(this, CameraRemote.CameraRemoteSetup.Request.Event.ENABLE_CAMERA);
|
SendCameraRemoteSetupEvent sendCameraRemoteSetupEvent = new SendCameraRemoteSetupEvent(this, CameraRemote.CameraRemoteSetup.Request.Event.ENABLE_CAMERA);
|
||||||
sendCameraRemoteSetupEvent.doPerform();
|
sendCameraRemoteSetupEvent.doPerform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getHuaweiCoordinator().supportsAppParams()) {
|
||||||
|
GetAppInfoParams getAppInfoParams = new GetAppInfoParams(this);
|
||||||
|
getAppInfoParams.doPerform();
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
GB.toast(getContext(), "Initialize dynamic services of Huawei device failed", Toast.LENGTH_SHORT, GB.ERROR,
|
GB.toast(getContext(), "Initialize dynamic services of Huawei device failed", Toast.LENGTH_SHORT, GB.ERROR,
|
||||||
e);
|
e);
|
||||||
@ -2029,20 +2042,51 @@ public class HuaweiSupportProvider {
|
|||||||
LOG.error("Failed to update progress notification", e);
|
LOG.error("Failed to update progress notification", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private List<GBDeviceApp> gbWatchFaces = null;
|
||||||
|
private List<GBDeviceApp> gbWatchApps = null;
|
||||||
|
|
||||||
|
public void setGbWatchFaces(List<GBDeviceApp> gbWatchFaces) {
|
||||||
|
this.gbWatchFaces = gbWatchFaces;
|
||||||
|
updateAppList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGbWatchApps(List<GBDeviceApp> gbWatchApps) {
|
||||||
|
this.gbWatchApps = gbWatchApps;
|
||||||
|
updateAppList();
|
||||||
|
}
|
||||||
|
private void updateAppList() {
|
||||||
|
ArrayList<GBDeviceApp> gbDeviceApps=new ArrayList<>();
|
||||||
|
if(this.gbWatchFaces != null)
|
||||||
|
gbDeviceApps.addAll(this.gbWatchFaces);
|
||||||
|
if(this.gbWatchApps != null)
|
||||||
|
gbDeviceApps.addAll(this.gbWatchApps);
|
||||||
|
final GBDeviceEventAppInfo appInfoCmd = new GBDeviceEventAppInfo();
|
||||||
|
appInfoCmd.apps = gbDeviceApps.toArray(new GBDeviceApp[0]);
|
||||||
|
evaluateGBDeviceEvent(appInfoCmd);
|
||||||
|
}
|
||||||
|
|
||||||
public void onAppInfoReq() {
|
public void onAppInfoReq() {
|
||||||
|
this.gbWatchFaces = null;
|
||||||
|
this.gbWatchApps = null;
|
||||||
huaweiWatchfaceManager.requestWatchfaceList();
|
huaweiWatchfaceManager.requestWatchfaceList();
|
||||||
|
huaweiAppManager.requestAppList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAppStart(final UUID uuid, boolean start) {
|
public void onAppStart(final UUID uuid, boolean start) {
|
||||||
if (start) {
|
if (start) {
|
||||||
|
//NOTE: to prevent exception in watchfaces code
|
||||||
|
if(!huaweiAppManager.startApp(uuid)) {
|
||||||
huaweiWatchfaceManager.setWatchface(uuid);
|
huaweiWatchfaceManager.setWatchface(uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void onAppDelete(final UUID uuid) {
|
public void onAppDelete(final UUID uuid) {
|
||||||
|
//NOTE: to prevent exception in watchfaces code
|
||||||
|
if(!huaweiAppManager.deleteApp(uuid)){
|
||||||
huaweiWatchfaceManager.deleteWatchface(uuid);
|
huaweiWatchfaceManager.deleteWatchface(uuid);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void onCameraStatusChange(GBDeviceEventCameraRemote.Event event, String filename) {
|
public void onCameraStatusChange(GBDeviceEventCameraRemote.Event event, String filename) {
|
||||||
if (event == GBDeviceEventCameraRemote.Event.OPEN_CAMERA) {
|
if (event == GBDeviceEventCameraRemote.Event.OPEN_CAMERA) {
|
||||||
|
@ -24,6 +24,7 @@ import java.security.MessageDigest;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload.FileUploadParams;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileUpload.FileUploadParams;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
@ -132,7 +133,11 @@ public class HuaweiUploadManager {
|
|||||||
|
|
||||||
public void setDeviceBusy() {
|
public void setDeviceBusy() {
|
||||||
final GBDevice device = support.getDevice();
|
final GBDevice device = support.getDevice();
|
||||||
|
if(fileType == FileUpload.Filetype.watchface) {
|
||||||
device.setBusyTask(support.getContext().getString(R.string.uploading_watchface));
|
device.setBusyTask(support.getContext().getString(R.string.uploading_watchface));
|
||||||
|
} else {
|
||||||
|
device.setBusyTask(support.getContext().getString(R.string.updating_firmware));
|
||||||
|
}
|
||||||
device.sendDeviceUpdateIntent(support.getContext());
|
device.sendDeviceUpdateIntent(support.getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,20 +26,16 @@ import java.io.IOException;
|
|||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Watchface;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Watchface;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Watchface.WatchfaceDeviceParams;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWatchfacesList;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWatchfacesList;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWatchfacesNames;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWatchfacesNames;
|
||||||
@ -195,10 +191,7 @@ public class HuaweiWatchfaceManager
|
|||||||
);
|
);
|
||||||
gbDeviceApps.add(gbDeviceApp);
|
gbDeviceApps.add(gbDeviceApp);
|
||||||
}
|
}
|
||||||
|
support.setGbWatchFaces(gbDeviceApps);
|
||||||
final GBDeviceEventAppInfo appInfoCmd = new GBDeviceEventAppInfo();
|
|
||||||
appInfoCmd.apps = gbDeviceApps.toArray(new GBDeviceApp[0]);
|
|
||||||
support.evaluateGBDeviceEvent(appInfoCmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateWatchfaceNames() {
|
public void updateWatchfaceNames() {
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||||
|
|
||||||
|
public class GetAppInfoParams extends Request{
|
||||||
|
|
||||||
|
public GetAppInfoParams(HuaweiSupportProvider support) {
|
||||||
|
super(support);
|
||||||
|
this.serviceId = App.id;
|
||||||
|
this.commandId = App.AppInfoParams.id;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||||
|
try {
|
||||||
|
return new App.AppInfoParams.Request(paramsProvider).serialize();
|
||||||
|
} catch (HuaweiPacket.CryptoException e) {
|
||||||
|
throw new RequestCreationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processResponse() throws ResponseParseException {
|
||||||
|
if (!(receivedPacket instanceof App.AppInfoParams.Response))
|
||||||
|
throw new ResponseTypeMismatchException(receivedPacket, App.AppInfoParams.Response.class);
|
||||||
|
|
||||||
|
App.AppInfoParams.Response resp = (App.AppInfoParams.Response)(receivedPacket);
|
||||||
|
supportProvider.getHuaweiCoordinator().setAppDeviceParams(resp.params);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||||
|
|
||||||
|
public class GetAppNames extends Request{
|
||||||
|
public GetAppNames(HuaweiSupportProvider support) {
|
||||||
|
super(support);
|
||||||
|
this.serviceId = App.id;
|
||||||
|
this.commandId = App.AppNames.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||||
|
try {
|
||||||
|
return new App.AppNames.Request(paramsProvider).serialize();
|
||||||
|
} catch (HuaweiPacket.CryptoException e) {
|
||||||
|
throw new RequestCreationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processResponse() throws ResponseParseException {
|
||||||
|
if (!(receivedPacket instanceof App.AppNames.Response))
|
||||||
|
throw new ResponseTypeMismatchException(receivedPacket, App.AppNames.Response.class);
|
||||||
|
|
||||||
|
App.AppNames.Response resp = (App.AppNames.Response)(receivedPacket);
|
||||||
|
supportProvider.getHuaweiAppManager().setInstalledAppList(resp.appInfoList);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.App;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||||
|
|
||||||
|
public class SendAppDelete extends Request {
|
||||||
|
private final String packageName;
|
||||||
|
public SendAppDelete(HuaweiSupportProvider support, String packageName) {
|
||||||
|
super(support);
|
||||||
|
this.serviceId = App.id;
|
||||||
|
this.commandId = App.AppDelete.id;
|
||||||
|
this.packageName = packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||||
|
try {
|
||||||
|
return new App.AppDelete.Request(this.paramsProvider, this.packageName).serialize();
|
||||||
|
} catch (HuaweiPacket.CryptoException e) {
|
||||||
|
throw new RequestCreationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user