diff --git a/app/src/main/assets/fossil_hr/openSourceWatchface.bin b/app/src/main/assets/fossil_hr/openSourceWatchface.bin index 17987ff4f..11c5bd35d 100644 Binary files a/app/src/main/assets/fossil_hr/openSourceWatchface.bin and b/app/src/main/assets/fossil_hr/openSourceWatchface.bin differ diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceDesignerActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceDesignerActivity.java index ef481e5b3..e482b3371 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceDesignerActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceDesignerActivity.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -39,6 +40,7 @@ import android.view.DragEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; @@ -73,6 +75,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport; +import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; import nodomain.freeyourgadget.gadgetbridge.util.BitmapUtil; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.GB; @@ -154,6 +157,14 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem findViewById(R.id.watchface_rotate_left).setOnClickListener(this); findViewById(R.id.watchface_rotate_right).setOnClickListener(this); findViewById(R.id.watchface_remove_image).setOnClickListener(this); + findViewById(R.id.button_watchface_open_menu_companion).setOnClickListener(this); + findViewById(R.id.button_watchface_reset_menu_structure).setOnClickListener(this); + } + + @Override + protected void onResume() { + super.onResume(); + reloadMenuStructureIndicator(); } @Override @@ -207,7 +218,8 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem @Override public void onClick(View v) { - if (v.getId() == R.id.button_edit_name) { + int buttonId = v.getId(); + if (buttonId == R.id.button_edit_name) { final EditText input = new EditText(this); input.setText(watchfaceName); input.setId(0); @@ -226,7 +238,7 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem }) .setTitle(R.string.watchface_dialog_title_set_name) .show(); - } else if (v.getId() == R.id.watchface_invert_colors) { + } else if (buttonId == R.id.watchface_invert_colors) { if (selectedBackgroundImage != null) { selectedBackgroundImage = BitmapUtil.invertBitmapColors(selectedBackgroundImage); for (int i=0; i widgets = new ArrayList<>(); + private JSONObject menuStructure = new JSONObject(); public HybridHRWatchfaceFactory(String name) { watchfaceName = name.replaceAll("[^-A-Za-z0-9]", ""); @@ -130,6 +131,10 @@ public class HybridHRWatchfaceFactory { } } + public void setMenuStructure(JSONObject menuStructure){ + this.menuStructure = menuStructure; + } + public void addWidgets(ArrayList widgets) { for (HybridHRWatchfaceWidget widget : widgets) { addWidget(widget); @@ -311,6 +316,8 @@ public class HybridHRWatchfaceFactory { config.put("light_up_on_notification", settings.getLightUpOnNotification()); configuration.put("config", config); + configuration.put("menu_structure", menuStructure); + return configuration.toString(); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridConstants.java index 24e8b1ae3..f54f40fda 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridConstants.java @@ -22,7 +22,7 @@ import java.util.Map; import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; public final class QHybridConstants { - public static final String HYBRIDHR_WATCHFACE_VERSION = "1.10"; + public static final String HYBRIDHR_WATCHFACE_VERSION = "1.11"; public static final int HYBRID_HR_WATCHFACE_WIDGET_SIZE = 76; public static Map KNOWN_WAPP_VERSIONS = new HashMap() { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java index bfee4c841..3c757b304 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java @@ -30,6 +30,8 @@ import android.widget.Toast; import androidx.localbroadcastmanager.content.LocalBroadcastManager; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -99,6 +101,8 @@ public class QHybridSupport extends QHybridBaseSupport { public static final String QHYBRID_COMMAND_DOWNLOAD_FILE = "nodomain.freeyourgadget.gadgetbridge.Q_DOWNLOAD_FILE"; public static final String QHYBRID_COMMAND_UPLOAD_FILE = "nodomain.freeyourgadget.gadgetbridge.Q_UPLOAD_FILE"; + public static final String QHYBRID_COMMAND_SET_MENU_STRUCTURE = "nodomain.freeyourgadget.gadgetbridge.Q_SET_MENU_STRUCTURE"; + public static final String QHYBRID_ACTION_DOWNLOADED_FILE = "nodomain.freeyourgadget.gadgetbridge.Q_DOWNLOADED_FILE"; public static final String QHYBRID_ACTION_UPLOADED_FILE = "nodomain.freeyourgadget.gadgetbridge.Q_UPLOADED_FILE"; @@ -305,6 +309,7 @@ public class QHybridSupport extends QHybridBaseSupport { globalFilter.addAction(QHYBRID_COMMAND_UPLOAD_FILE); globalFilter.addAction(QHYBRID_COMMAND_PUSH_CONFIG); globalFilter.addAction(QHYBRID_COMMAND_SWITCH_WATCHFACE); + globalFilter.addAction(QHYBRID_COMMAND_SET_MENU_STRUCTURE); globalCommandReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -380,6 +385,10 @@ public class QHybridSupport extends QHybridBaseSupport { handleSwitchWatchfaceIntent(intent); break; } + case QHYBRID_COMMAND_SET_MENU_STRUCTURE:{ + handleSetMenuStructure(intent); + break; + } } } }; @@ -398,6 +407,30 @@ public class QHybridSupport extends QHybridBaseSupport { } } + private void handleSetMenuStructure(Intent intent){ + if(intent == null){ + logger.error("intent null"); + return; + } + String menuStructureJson = intent.getStringExtra("EXTRA_MENU_STRUCTURE_JSON"); + if(menuStructureJson == null){ + logger.error("Menu structure json null"); + return; + } + if(menuStructureJson.isEmpty()){ + logger.error("Menu structure json empty"); + return; + } + try { + JSONObject menuStructure = new JSONObject(menuStructureJson); + watchAdapter.handleSetMenuStructure(menuStructure); + GB.toast(getContext().getString(R.string.info_menu_structure_set), Toast.LENGTH_SHORT, GB.INFO); + } catch (JSONException e) { + logger.error("Menu structure json empty"); + GB.toast(getContext().getString(R.string.error_invalid_menu_structure), Toast.LENGTH_SHORT, GB.ERROR); + } + } + private boolean dangerousIntentsAllowed(){ return GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREF_HYBRID_HR_DANGEROUS_EXTERNAL_INTENTS, true); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java index ee4aa24b4..68cef9193 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java @@ -21,6 +21,8 @@ import android.bluetooth.BluetoothGattCharacteristic; import android.content.Context; import android.net.Uri; +import org.json.JSONObject; + import java.util.ArrayList; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationConfiguration; @@ -165,4 +167,8 @@ public abstract class WatchAdapter { public void pushConfigJson(String configJson){ } + + public void handleSetMenuStructure(JSONObject menuStructure) { + + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java index db2b32d35..a55f6f68d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java @@ -1068,6 +1068,28 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { } } + @Override + public void handleSetMenuStructure(JSONObject menuStructure) { + String serialized = menuStructure.toString(); + getDeviceSpecificPreferences() + .edit() + .putString("MENU_STRUCTURE_JSON", serialized) + .apply(); + + try { + String payload = new JSONObject() + .put("push", new JSONObject() + .put("set", new JSONObject() + .put("customWatchFace._.config.menu_structure", menuStructure) + ) + ).toString(); + pushConfigJson(payload); + } catch (JSONException e) { + throw new RuntimeException(e); + } + + } + @Override public void setWidgetContent(String widgetID, String content, boolean renderOnWatch) { boolean update = false; @@ -1898,16 +1920,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { queueWrite(new JsonPutRequest(responseObject, this)); } } else if (request.optString("custom_menu").equals("request_config")) { - // watchface requests custom menu data to be initialized - LOG.info("Got custom_menu config request, sending intent to HR Menu Companion app..."); - Intent intent = new Intent(); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setClassName("d.d.hrmenucompanion", "d.d.hrmenucompanion.MainActivity"); - intent.putExtra("SEND_CONFIG", true); - try { - getContext().startActivity(intent); - } catch (Exception e) { - LOG.info("Couldn't send intent to Fossil-HR-Menu-Companion app, is it installed?"); + PackageManager manager = getContext().getPackageManager(); + try{ + // only show toast when companion app is installed + manager.getApplicationInfo("d.d.hrmenucompanion", 0); + GB.toast(getContext().getString(R.string.info_fossil_rebuild_watchface_custom_menu), Toast.LENGTH_SHORT, GB.INFO); + }catch (PackageManager.NameNotFoundException e){ } } else { LOG.warn("Unhandled request from watch: " + requestJson.toString()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java index 71079c585..af101a6e6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/AndroidUtils.java @@ -317,4 +317,20 @@ public class AndroidUtils { Toast.makeText(context, R.string.activity_error_share_failed, Toast.LENGTH_LONG).show(); } } + + public static void openWebsite(String url){ + Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + GBApplication.getContext().startActivity(i); + } + + public static void openApp(String packageName) throws ClassNotFoundException { + Context context = GBApplication.getContext(); + + Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName); + if(launchIntent == null){ + throw new ClassNotFoundException("App " + packageName + " cannot be found"); + } + GBApplication.getContext().startActivity(launchIntent); + } } diff --git a/app/src/main/res/layout/activity_hybridhr_watchface_designer.xml b/app/src/main/res/layout/activity_hybridhr_watchface_designer.xml index 9d26b67e0..69d067922 100644 --- a/app/src/main/res/layout/activity_hybridhr_watchface_designer.xml +++ b/app/src/main/res/layout/activity_hybridhr_watchface_designer.xml @@ -112,21 +112,53 @@