diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ac2381898..6494fcba3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,7 +1,6 @@
-
-
@@ -44,16 +42,19 @@
android:allowBackup="false"
android:fullBackupContent="false"
android:icon="@mipmap/ic_launcher"
- android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/GadgetbridgeTheme">
+
+
+
@@ -78,9 +79,9 @@
android:label="@string/activity_summaries"
android:parentActivityName=".activities.ControlCenterv2" />
-
+
@@ -306,7 +307,6 @@
-
@@ -331,18 +331,19 @@
-
+
-
+
-
@@ -365,16 +366,13 @@
-
-
-
+ android:exported="false">
+ -->
+ android:label="@string/title_activity_watch9_pairing" />
+ android:label="@string/title_activity_watch9_calibration" />
+ android:parentActivityName=".activities.AppBlacklistActivity"
+ android:windowSoftInputMode="stateHidden|adjustPan" />
@@ -439,7 +437,6 @@
android:name=".contentprovider.PebbleContentProvider"
android:authorities="com.getpebble.android.provider"
android:exported="true" />
-
-
@@ -461,41 +459,41 @@
android:name="android.appwidget.provider"
android:resource="@xml/sleep_alarm_widget_info" />
-
-
+
-
-
+ android:theme="@style/Theme.AppCompat.Light.Dialog" />
+
-
-
-
+
+
+
+
+
@@ -510,4 +508,4 @@
android:exported="true" />
-
+
\ No newline at end of file
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HRConfigActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HRConfigActivity.java
index aa5326ed6..b22b30bb6 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HRConfigActivity.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HRConfigActivity.java
@@ -1,15 +1,11 @@
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import android.app.AlertDialog;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.graphics.Color;
import android.os.Bundle;
-import android.util.Log;
-import android.view.Menu;
-import android.view.TextureView;
+import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -25,21 +21,33 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONArray;
import org.json.JSONException;
-import org.w3c.dom.Text;
+import org.json.JSONObject;
-import java.sql.Array;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomBackgroundWidgetElement;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomTextWidgetElement;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidget;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidgetElement;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.Widget;
+
+import static nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.WidgetSettingsActivity.RESULT_CODE_WIDGET_DELETED;
+import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport.QHYBRID_COMMAND_UPDATE_WIDGETS;
public class HRConfigActivity extends AbstractGBActivity implements View.OnClickListener, DialogInterface.OnClickListener, AdapterView.OnItemClickListener {
private SharedPreferences sharedPreferences;
private ActionListAdapter actionListAdapter;
+ private WidgetListAdapter widgetListAdapter;
private ArrayList menuActions = new ArrayList<>();
+ private ArrayList customWidgets = new ArrayList<>();
+
+ SparseArray widgetButtonsMapping = new SparseArray<>(4);
static public final String CONFIG_KEY_Q_ACTIONS = "Q_ACTIONS";
@@ -52,14 +60,266 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
sharedPreferences = GBApplication.getPrefs().getPreferences();
+ initMappings();
+ loadWidgetConfigs();
+
+
ListView actionListView = findViewById(R.id.qhybrid_action_list);
actionListAdapter = new ActionListAdapter(menuActions);
actionListView.setAdapter(actionListAdapter);
actionListView.setOnItemClickListener(this);
+ final ListView widgetListView = findViewById(R.id.qhybrid_widget_list);
+ widgetListAdapter = new WidgetListAdapter(customWidgets);
+ widgetListView.setAdapter(widgetListAdapter);
+ widgetListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ Widget widget = widgetListAdapter.getItem(position);
+
+ Intent startIntent = new Intent(HRConfigActivity.this, WidgetSettingsActivity.class);
+ startIntent.putExtra("EXTRA_WIDGET", widget);
+ startIntent.putExtra("EXTRA_WIDGET_IDNEX", position);
+
+ startActivityForResult(startIntent, 0);
+ }
+ });
+ loadCustomWidgetList();
+
+ findViewById(R.id.qhybrid_widget_add).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent startIntent = new Intent(HRConfigActivity.this, WidgetSettingsActivity.class);
+
+ startActivityForResult(startIntent, 0);
+ }
+ });
+
+ for (int i = 0; i < widgetButtonsMapping.size(); i++) {
+ final int widgetButtonId = widgetButtonsMapping.keyAt(i);
+ findViewById(widgetButtonId).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Widget.WidgetType[] types = Widget.WidgetType.values();
+ final ArrayList names = new ArrayList<>(types.length);
+
+ for (Widget.WidgetType type : types) {
+ names.add(getResources().getString(type.getStringResource()));
+ }
+
+ for(CustomWidget customWidget : customWidgets){
+ names.add(customWidget.getName());
+ }
+
+ final String[] nameStrings = names.toArray(new String[0]);
+ new AlertDialog.Builder(HRConfigActivity.this)
+ .setItems(
+ nameStrings,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ saveWidgetSetting(widgetButtonId, which, nameStrings);
+ }
+ }
+ )
+ .show();
+
+ }
+ });
+ }
+
updateSettings();
}
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if(data == null) return;
+ if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_CREATED) {
+ CustomWidget widget = (CustomWidget) data.getExtras().get("EXTRA_WIDGET");
+ this.customWidgets.add(widget);
+ refreshWidgetList();
+ saveCustomWidgetList();
+
+ LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
+ } else if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_UPDATED) {
+ CustomWidget widget = (CustomWidget) data.getExtras().get("EXTRA_WIDGET");
+ int updateIndex = data.getIntExtra("EXTRA_WIDGET_IDNEX", -1);
+
+ this.customWidgets.set(updateIndex, widget);
+
+ refreshWidgetList();
+ saveCustomWidgetList();
+
+ LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
+ } else if (resultCode == WidgetSettingsActivity.RESULT_CODE_WIDGET_DELETED){
+ int updateIndex = data.getIntExtra("EXTRA_WIDGET_IDNEX", -1);
+
+ this.customWidgets.remove(updateIndex);
+
+ refreshWidgetList();
+ saveCustomWidgetList();
+
+ LocalBroadcastManager.getInstance(HRConfigActivity.this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
+ }
+
+ }
+
+ private void saveCustomWidgetList() {
+ try {
+ JSONArray widgetArray = new JSONArray();
+ for(CustomWidget widget : customWidgets){
+ JSONArray elementArray = new JSONArray();
+
+ for(CustomWidgetElement element : widget.getElements()){
+ JSONObject elementObject = new JSONObject();
+ elementObject
+ .put("type", element.getWidgetElementType().getJsonIdentifier())
+ .put("id", element.getId())
+ .put("value", element.getValue())
+ .put("x", element.getX())
+ .put("y", element.getY());
+ elementArray.put(elementObject);
+ }
+
+ JSONObject widgetObject = new JSONObject();
+ widgetObject
+ .put("name", widget.getName())
+ .put("elements", elementArray);
+
+ widgetArray.put(widgetObject);
+ }
+ sharedPreferences.edit().putString("QHYBRID_CUSTOM_WIDGETS", widgetArray.toString()).apply();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void loadCustomWidgetList() {
+ String customWidgetJson = sharedPreferences.getString("QHYBRID_CUSTOM_WIDGETS", "[]");
+
+ try {
+ JSONArray customWidgets = new JSONArray(customWidgetJson);
+ this.customWidgets.clear();
+
+ for (int i = 0; i < customWidgets.length(); i++) {
+ JSONObject customWidgetObject = customWidgets.getJSONObject(i);
+ CustomWidget widget = new CustomWidget(
+ customWidgetObject.getString("name"), 0, 0
+ );
+ JSONArray elements = customWidgetObject.getJSONArray("elements");
+
+ for (int i2 = 0; i2 < elements.length(); i2++) {
+ JSONObject element = elements.getJSONObject(i2);
+ if (element.getString("type").equals("text")) {
+ widget.addElement(new CustomTextWidgetElement(
+ element.getString("id"),
+ element.getString("value"),
+ element.getInt("x"),
+ element.getInt("y")
+ ));
+ } else if (element.getString("type").equals("background")) {
+ widget.addElement(new CustomBackgroundWidgetElement(
+ element.getString("id"),
+ element.getString("value")
+ ));
+ }
+ }
+
+ this.customWidgets.add(widget);
+ }
+
+ refreshWidgetList();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void refreshWidgetList() {
+ widgetListAdapter.notifyDataSetChanged();
+ }
+
+ private void saveWidgetSetting(int buttonId, int option, String[] names) {
+ String jsonKey = widgetButtonsMapping.get(buttonId);
+ Widget.WidgetType[] types = Widget.WidgetType.values();
+ String identifier = null;
+ if(option < types.length){
+ Widget.WidgetType type = types[option];
+ identifier = type.getIdentifier();
+ }else{
+ identifier = "custom_" + names[option];
+ }
+
+ try {
+ JSONObject keyConfig = new JSONObject(sharedPreferences.getString("FOSSIL_HR_WIDGETS", "{}"));
+ if (identifier != null) {
+ keyConfig.put(jsonKey, identifier);
+ } else {
+ keyConfig.remove(jsonKey);
+ }
+ sharedPreferences.edit().putString("FOSSIL_HR_WIDGETS", keyConfig.toString()).apply();
+ LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(QHYBRID_COMMAND_UPDATE_WIDGETS));
+
+ loadWidgetConfigs();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+
+ private void loadWidgetConfigs() {
+ try {
+ for (int i = 0; i < widgetButtonsMapping.size(); i++) {
+ ((TextView) findViewById(widgetButtonsMapping.keyAt(i))).setText(widgetButtonsMapping.valueAt(i) + " widget");
+ }
+
+ JSONObject keyConfig = new JSONObject(sharedPreferences.getString("FOSSIL_HR_WIDGETS", "{}"));
+ Iterator keyIterator = keyConfig.keys();
+
+ loop:
+ while (keyIterator.hasNext()) {
+ String position = keyIterator.next();
+
+ for (int widgetButtonIndex = 0; widgetButtonIndex < widgetButtonsMapping.size(); widgetButtonIndex++) {
+ if (position.equals(widgetButtonsMapping.valueAt(widgetButtonIndex))) {
+ int buttonId = widgetButtonsMapping.keyAt(widgetButtonIndex);
+ String function = keyConfig.getString(position);
+
+ Widget.WidgetType[] types = Widget.WidgetType.values();
+ if(function.startsWith("custom_")){
+ ((TextView) findViewById(buttonId)).setText(
+ position + " widget: " + function.substring(7)
+ );
+ continue loop;
+ }
+ for (int widgetIdIndex = 0; widgetIdIndex < types.length; widgetIdIndex++) {
+ String widgetIdMappingValue = types[widgetIdIndex].getIdentifier();
+ if (widgetIdMappingValue != null && widgetIdMappingValue.equals(function)) {
+ ((TextView) findViewById(buttonId)).setText(
+ position + " widget: "
+ + getResources().getText(
+ types[widgetIdIndex].getStringResource()
+ )
+ );
+ break;
+ }
+ }
+ }
+ }
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void initMappings() {
+ widgetButtonsMapping.put(R.id.qhybrid_button_widget_top, "top");
+ widgetButtonsMapping.put(R.id.qhybrid_button_widget_right, "right");
+ widgetButtonsMapping.put(R.id.qhybrid_button_widget_bottom, "bottom");
+ widgetButtonsMapping.put(R.id.qhybrid_button_widget_left, "left");
+ }
+
@Override
public void onClick(View v) {
if (v.getId() == R.id.qhybrid_action_add) {
@@ -147,7 +407,7 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
.show();
}
- private void putActionItems(List actions){
+ private void putActionItems(List actions) {
JSONArray array = new JSONArray();
for (MenuAction action : actions) array.put(action.getAction());
@@ -170,6 +430,25 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
}
}
+ class WidgetListAdapter extends ArrayAdapter {
+ public WidgetListAdapter(@NonNull List objects) {
+ super(HRConfigActivity.this, 0, objects);
+ }
+
+ @NonNull
+ @Override
+ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
+ if (convertView == null) convertView = new TextView(getContext());
+ TextView view = (TextView) convertView;
+
+ view.setText(getItem(position).getName());
+ // view.setTextColor(Color.WHITE);
+ view.setTextSize(25);
+
+ return view;
+ }
+ }
+
class ActionListAdapter extends ArrayAdapter {
public ActionListAdapter(@NonNull ArrayList objects) {
super(HRConfigActivity.this, 0, objects);
@@ -183,7 +462,7 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
view.setText(getItem(position).getAction());
// view.setTextColor(Color.WHITE);
- view.setTextSize(30);
+ view.setTextSize(25);
return view;
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/WidgetSettingsActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/WidgetSettingsActivity.java
new file mode 100644
index 000000000..6746ae6c9
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/WidgetSettingsActivity.java
@@ -0,0 +1,208 @@
+package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import java.util.List;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.Widget;
+import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomBackgroundWidgetElement;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomTextWidgetElement;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidget;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidgetElement;
+
+public class WidgetSettingsActivity extends AbstractGBActivity {
+ private CustomWidget subject;
+ private WidgetElementAdapter widgetElementAdapter;
+
+ public static final int RESULT_CODE_WIDGET_CREATED = 0;
+ public static final int RESULT_CODE_WIDGET_UPDATED = 1;
+ public static final int RESULT_CODE_WIDGET_DELETED = 2;
+ public static final int RESULT_CODE_CANCELED = 3;
+
+ private int resultCode;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.qhybrid_activity_widget_settings);
+
+ setResult(RESULT_CODE_CANCELED);
+
+ if(getIntent().hasExtra("EXTRA_WIDGET")){
+ subject = (CustomWidget) getIntent().getExtras().get("EXTRA_WIDGET");
+ ((EditText) findViewById(R.id.qhybrid_widget_name)).setText(subject.getName());
+ resultCode = RESULT_CODE_WIDGET_UPDATED;
+ }else{
+ subject = new CustomWidget("", 0, 63);
+ resultCode = RESULT_CODE_WIDGET_CREATED;
+ findViewById(R.id.qhybrid_widget_delete).setEnabled(false);
+ }
+
+ findViewById(R.id.qhybrid_widget_save).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ subject.setName(((EditText) findViewById(R.id.qhybrid_widget_name)).getText().toString());
+
+ Intent resultIntent = getIntent();
+ resultIntent.putExtra("EXTRA_WIDGET", WidgetSettingsActivity.this.subject);
+ setResult(resultCode, resultIntent);
+
+ finish();
+ }
+ });
+
+ findViewById(R.id.qhybrid_widget_delete).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setResult(RESULT_CODE_WIDGET_DELETED, getIntent());
+
+ finish();
+ }
+ });
+
+ widgetElementAdapter = new WidgetElementAdapter(subject.getElements());
+ ListView elementList = findViewById(R.id.qhybrid_widget_elements_list);
+ elementList.setAdapter(widgetElementAdapter);
+ elementList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ showElementDialog(widgetElementAdapter.getItem(position));
+ }
+ });
+
+ findViewById(R.id.qhybrid_widget_elements_add).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showElementDialog(null);
+ }
+ });
+ }
+
+ private void showElementDialog(@Nullable final CustomWidgetElement element){
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(WidgetSettingsActivity.this)
+ .setView(R.layout.qhybrid_element_popup_view);
+
+ if(element == null) {
+ dialogBuilder
+ .setTitle("create element")
+ .setNegativeButton("cancel", null)
+ .setPositiveButton("ok", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if(((RadioButton)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_elements_type_text)).isChecked()){
+ subject.addElement(new CustomTextWidgetElement(
+ ((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_id)).getText().toString(),
+ ((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_value)).getText().toString(),
+ CustomWidgetElement.X_CENTER,
+ ((RadioButton)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_elements_position_uppper)).isChecked() ? CustomTextWidgetElement.Y_UPPER_HALF : CustomTextWidgetElement.Y_LOWER_HALF
+ ));
+ }else{
+ subject.addElement(new CustomBackgroundWidgetElement(
+ ((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_id)).getText().toString(),
+ ((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_value)).getText().toString()
+ ));
+ }
+ refreshElementsList();
+ }
+ });
+ }else{
+ dialogBuilder
+ .setTitle("edit element")
+ .setNegativeButton("delete", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ WidgetSettingsActivity.this.subject.getElements().remove(element);
+
+ refreshElementsList();
+ }
+ })
+ .setPositiveButton("ok", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ element.setId(((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_id)).getText().toString());
+ element.setValue(((EditText)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_value)).getText().toString());
+ element.setY(((RadioButton)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_elements_position_uppper)).isChecked() ? CustomTextWidgetElement.Y_UPPER_HALF : CustomTextWidgetElement.Y_LOWER_HALF);
+ element.setWidgetElementType(CustomWidgetElement.WidgetElementType.fromRadioButtonRessource(((RadioGroup)((AlertDialog)dialog).findViewById(R.id.qhybrid_widget_element_type)).getCheckedRadioButtonId()));
+
+ refreshElementsList();
+ }
+ });
+ }
+
+ AlertDialog dialog = dialogBuilder.show();
+
+
+ if(element != null){
+ String elementId = element.getId();
+ String elementValue = element.getValue();
+ CustomWidgetElement.WidgetElementType type = element.getWidgetElementType();
+
+ ((EditText)dialog.findViewById(R.id.qhybrid_widget_element_id)).setText(elementId);
+ ((EditText)dialog.findViewById(R.id.qhybrid_widget_element_value)).setText(elementValue);
+ ((RadioGroup)dialog.findViewById(R.id.qhybrid_widget_element_type)).check(type.getRadioButtonResource());
+ ((RadioGroup)dialog.findViewById(R.id.qhybrid_widget_element_position)).check(element.getY() == CustomWidgetElement.Y_UPPER_HALF ? R.id.qhybrid_widget_elements_position_uppper : R.id.qhybrid_widget_elements_position_lower);
+ }
+ }
+
+ private void refreshElementsList(){
+ this.widgetElementAdapter.notifyDataSetChanged();
+ }
+
+ class WidgetElementAdapter extends ArrayAdapter{
+ public WidgetElementAdapter(@NonNull List objects) {
+ super(WidgetSettingsActivity.this, 0, objects);
+ }
+
+ @NonNull
+ @Override
+ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
+ RelativeLayout layout = new RelativeLayout(WidgetSettingsActivity.this);
+ layout.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+
+ TextView idView = new TextView(WidgetSettingsActivity.this);
+
+ idView.setText(getItem(position).getId());
+ // view.setTextColor(Color.WHITE);
+ idView.setTextSize(25);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.addRule(RelativeLayout.ALIGN_PARENT_START, RelativeLayout.TRUE);
+ idView.setLayoutParams(params);
+
+ TextView contentView = new TextView(WidgetSettingsActivity.this);
+ contentView.setText(getItem(position).getValue());
+ contentView.setTextSize(25);
+ params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.addRule(RelativeLayout.ALIGN_PARENT_END, RelativeLayout.TRUE);
+ contentView.setLayoutParams(params);
+
+ layout.addView(idView);
+ layout.addView(contentView);
+
+ return layout;
+ }
+ }
+}
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 951c6224e..245ae542c 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
@@ -87,6 +87,7 @@ public class QHybridSupport extends QHybridBaseSupport {
public static final String QHYBRID_COMMAND_NOTIFICATION = "qhybrid_command_notification";
public static final String QHYBRID_COMMAND_UPDATE_SETTINGS = "nodomain.freeyourgadget.gadgetbridge.Q_UPDATE_SETTINGS";
public static final String QHYBRID_COMMAND_OVERWRITE_BUTTONS = "nodomain.freeyourgadget.gadgetbridge.Q_OVERWRITE_BUTTONS";
+ public static final String QHYBRID_COMMAND_UPDATE_WIDGETS = "nodomain.freeyourgadget.gadgetbridge.Q_UPDATE_WIDGETS";
public static final String QHYBRID_COMMAND_SET_MENU_MESSAGE = "nodomain.freeyourgadget.gadgetbridge.Q_SET_MENU_MESSAGE";
public static final String QHYBRID_COMMAND_SEND_MENU_ITEMS = "nodomain.freeyourgadget.gadgetbridge.Q_SEND_MENU_ITEMS";
public static final String QHYBRID_COMMAND_SET_WIDGET_CONTENT = "nodomain.freeyourgadget.gadgetbridge.Q_SET_WIDGET_CONTENT";
@@ -143,6 +144,7 @@ public class QHybridSupport extends QHybridBaseSupport {
commandFilter.addAction(QHYBRID_COMMAND_UPDATE_SETTINGS);
commandFilter.addAction(QHYBRID_COMMAND_OVERWRITE_BUTTONS);
commandFilter.addAction(QHYBRID_COMMAND_NOTIFICATION_CONFIG_CHANGED);
+ commandFilter.addAction(QHYBRID_COMMAND_UPDATE_WIDGETS);
commandFilter.addAction(QHYBRID_COMMAND_SEND_MENU_ITEMS);
commandReceiver = new BroadcastReceiver() {
@@ -217,6 +219,10 @@ public class QHybridSupport extends QHybridBaseSupport {
watchAdapter.syncNotificationSettings();
break;
}
+ case QHYBRID_COMMAND_UPDATE_WIDGETS: {
+ watchAdapter.updateWidgets();
+ break;
+ }
}
}
};
@@ -278,6 +284,7 @@ public class QHybridSupport extends QHybridBaseSupport {
widgetValues.put(key.substring(16), String.valueOf(intent.getExtras().get(key)));
}
}
+ boolean render = intent.getBooleanExtra("EXTRA_RENDER", true);
if(widgetValues.size() > 0){
Iterator valuesIterator = widgetValues.keySet().iterator();
valuesIterator.next();
@@ -289,11 +296,10 @@ public class QHybridSupport extends QHybridBaseSupport {
valuesIterator = widgetValues.keySet().iterator();
String id = valuesIterator.next();
- watchAdapter.setWidgetContent(id, widgetValues.get(id), true);
+ watchAdapter.setWidgetContent(id, widgetValues.get(id), render);
}else {
String id = String.valueOf(intent.getExtras().get("EXTRA_WIDGET_ID"));
String content = String.valueOf(intent.getExtras().get("EXTRA_CONTENT"));
- boolean render = intent.getBooleanExtra("EXTRA_RENDER", true);
watchAdapter.setWidgetContent(id, content, render);
}
break;
@@ -352,7 +358,7 @@ public class QHybridSupport extends QHybridBaseSupport {
.read(getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")))
.read(getCharacteristic(UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb")))
.read(getCharacteristic(UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb")))
- .notify(getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")), true)
+ // .notify(getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")), true)
;
@@ -474,6 +480,12 @@ public class QHybridSupport extends QHybridBaseSupport {
return notificationProgress;
}
+ @Override
+ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+ super.onConnectionStateChange(gatt, status, newState);
+ watchAdapter.onConnectionStateChange(gatt, status, newState);
+ }
+
//TODO toggle "Notifications when screen on" options on this check
private void showNotificationCountOnActivityHand(double progress) {
if (useActivityHand) {
@@ -612,6 +624,12 @@ public class QHybridSupport extends QHybridBaseSupport {
}
+ @Override
+ public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ watchAdapter.onCharacteristicWrite(gatt, characteristic, status);
+ return super.onCharacteristicWrite(gatt, characteristic, status);
+ }
+
@Override
public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
switch (characteristic.getUuid().toString()) {
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 a493062b0..1de837b09 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
@@ -108,4 +108,13 @@ public abstract class WatchAdapter {
public void setWidgetContent(String widgetID, String content, boolean render) {
}
+
+ public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ }
+
+ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+ }
+
+ public void updateWidgets() {
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil/FossilWatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil/FossilWatchAdapter.java
index af79eb9f7..67aeb2377 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil/FossilWatchAdapter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil/FossilWatchAdapter.java
@@ -43,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.PackageConfigHelper;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.BTLEOperation;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter;
@@ -130,6 +131,25 @@ public class FossilWatchAdapter extends WatchAdapter {
overwriteButtons(buttonConfig);
}
+ @Override
+ public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ if(status != BluetoothGatt.GATT_SUCCESS){
+ log("characteristic write failed: " + status);
+ fossilRequest = null;
+
+ queueNextRequest();
+ }
+ }
+
+ @Override
+ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+ if(newState != BluetoothGatt.STATE_CONNECTED){
+ log("status " + newState + " clearing queue...");
+ requestQueue.clear();
+ fossilRequest = null;
+ }
+ }
+
private SharedPreferences getDeviceSpecificPreferences(){
return GBApplication.getDeviceSpecificSharedPrefs(
getDeviceSupport().getDevice().getAddress()
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 9ea67874b..dbad301f1 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
@@ -9,47 +9,39 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
+import android.os.CpuUsageInfo;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
-import java.util.Random;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.TimeZone;
-import java.util.UUID;
-import cyanogenmod.app.CustomTile;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
-import nodomain.freeyourgadget.gadgetbridge.Widget;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity;
-import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationConfiguration;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
-import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.TimeConfigItem;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileCloseRequest;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileDeleteRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.authentication.VerifyPrivateKeyRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.buttons.ButtonConfigurationPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationPutRequest;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFile;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory;
@@ -58,14 +50,12 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicInfoSetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationFilterPutHRRequest;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationImage;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationImagePutRequest;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.PlayNotificationHRRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomBackgroundWidgetElement;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomTextWidgetElement;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidget;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidgetElement;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.utils.StringUtils;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.Widget;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.WidgetsPutRequest;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest.MUSIC_PHONE_REQUEST;
@@ -75,7 +65,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
private byte[] phoneRandomNumber;
private byte[] watchRandomNumber;
- CustomWidget[] widgets = new CustomWidget[0];
+ ArrayList widgets = new ArrayList<>();
NotificationHRConfiguration[] notificationConfigurations;
@@ -176,37 +166,87 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
.decodeFile("/sdcard/DCIM/Camera/IMG_20191129_200726.jpg");
try {
- this.backGroundImage = AssetImageFactory.createAssetImage(backgroundBitmap, false, 0, 0, 0);
+ this.backGroundImage = AssetImageFactory.createAssetImage(backgroundBitmap, false, 0,:wq
+ 0, 0);
} catch (IOException e) {
GB.log("Backgroundimage error", GB.ERROR, e);
}*/
}
private void loadWidgets() {
- CustomWidget ethWidget = new CustomWidget(90, 63);
- // ethWidget.addElement(new CustomWidgetElement(CustomWidgetElement.WidgetElementType.TYPE_TEXT, "date", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
- ethWidget.addElement(new CustomTextWidgetElement("ETH", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
- ethWidget.addElement(new CustomTextWidgetElement("eth", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_LOWER_HALF));
+ this.widgets.clear();
+ String widgetJson = GBApplication.getPrefs().getPreferences().getString("FOSSIL_HR_WIDGETS", "{}");
+ String customWidgetJson = GBApplication.getPrefs().getString("QHYBRID_CUSTOM_WIDGETS", "[]");
+ try {
+ JSONObject widgetConfig = new JSONObject(widgetJson);
+ JSONArray customWidgets = new JSONArray(customWidgetJson);
- CustomWidget btcWidget = new CustomWidget(270, 63);
- btcWidget.addElement(new CustomTextWidgetElement("BTC", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
- btcWidget.addElement(new CustomTextWidgetElement("btc", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_LOWER_HALF));
+ Iterator keyIterator = widgetConfig.keys();
+ HashMap positionMap = new HashMap<>(4);
+ positionMap.put("top", 0);
+ positionMap.put("right", 90);
+ positionMap.put("bottom", 180);
+ positionMap.put("left", 270);
- CustomWidget dateWidget = new CustomWidget(0, 63);
- dateWidget.addElement(new CustomTextWidgetElement("Time", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
- dateWidget.addElement(new CustomTextWidgetElement("date", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_LOWER_HALF));
+ while(keyIterator.hasNext()){
+ String position = keyIterator.next();
+ String identifier = widgetConfig.getString(position);
+ Widget.WidgetType type = Widget.WidgetType.fromJsonIdentifier(identifier);
- CustomWidget helloWidget = new CustomWidget(180, 63);
- // helloWidget.addElement(new CustomTextWidgetElement("Hello", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF));
- // helloWidget.addElement(new CustomTextWidgetElement("Reddit", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_LOWER_HALF));
- helloWidget.addElement(new CustomBackgroundWidgetElement("reddit", "/sdcard/reddit.png"));
- this.widgets = new CustomWidget[]{
- ethWidget,
- btcWidget,
- dateWidget,
- helloWidget
- };
+ Widget widget = null;
+ if(type != null) {
+ widget = new Widget(type, positionMap.get(position), 63);
+ }else{
+ identifier = identifier.substring(7);
+ for(int i = 0; i < customWidgets.length(); i++){
+ JSONObject customWidget = customWidgets.getJSONObject(i);
+ if(customWidget.getString("name").equals(identifier)){
+ CustomWidget newWidget = new CustomWidget(
+ customWidget.getString("name"),
+ positionMap.get(position),
+ 63
+ );
+ JSONArray elements = customWidget.getJSONArray("elements");
+
+ for (int i2 = 0; i2 < elements.length(); i2++) {
+ JSONObject element = elements.getJSONObject(i2);
+ if (element.getString("type").equals("text")) {
+ newWidget.addElement(new CustomTextWidgetElement(
+ element.getString("id"),
+ element.getString("value"),
+ element.getInt("x"),
+ element.getInt("y")
+ ));
+ } else if (element.getString("type").equals("background")) {
+ newWidget.addElement(new CustomBackgroundWidgetElement(
+ element.getString("id"),
+ element.getString("value")
+ ));
+ }
+ }
+ widget = newWidget;
+ }
+ }
+ }
+
+ if(widget == null) continue;
+ this.widgets.add(widget);
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ uploadWidgets();
+ }
+
+ private void uploadWidgets(){
+ negotiateSymmetricKey();
+ ArrayList systemWidgets = new ArrayList<>(widgets.size());
+ for(Widget widget : this.widgets){
+ if(!(widget instanceof CustomWidget)) systemWidgets.add(widget);
+ }
+ queueWrite(new WidgetsPutRequest(systemWidgets.toArray(new Widget[0]), this));
}
private void renderWidgets() {
@@ -218,8 +258,10 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
}
- for (int i = 0; i < this.widgets.length; i++) {
- CustomWidget widget = widgets[i];
+ for (int i = 0; i < this.widgets.size(); i++) {
+ Widget w = widgets.get(i);
+ if(!(w instanceof CustomWidget)) continue;
+ CustomWidget widget = (CustomWidget) w;
Bitmap widgetBitmap = Bitmap.createBitmap(76, 76, Bitmap.Config.ARGB_8888);
@@ -312,8 +354,9 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
@Override
public void setWidgetContent(String widgetID, String content, boolean renderOnWatch) {
boolean update = false;
- for (CustomWidget widget : this.widgets) {
- if(widget.updateElementValue(widgetID, content)) update = true;
+ for (Widget widget : this.widgets) {
+ if(!(widget instanceof CustomWidget)) continue;
+ if(((CustomWidget) widget).updateElementValue(widgetID, content)) update = true;
}
if (renderOnWatch && update) renderWidgets();
@@ -374,6 +417,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
));
}
+ @Override
+ public void updateWidgets() {
+ loadWidgets();
+ renderWidgets();
+ }
+
private void setBackgroundImages(AssetImage background, AssetImage[] complications) {
queueWrite(new ImagesSetRequest(new AssetImage[]{background}, this));
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/configuration/ConfigurationGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/configuration/ConfigurationGetRequest.java
index 63bb0cde4..d5015f064 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/configuration/ConfigurationGetRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/configuration/ConfigurationGetRequest.java
@@ -8,6 +8,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSuppo
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedLookupAndGetRequest;
+import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class ConfigurationGetRequest extends FileEncryptedLookupAndGetRequest {
public ConfigurationGetRequest(FossilHRWatchAdapter adapter) {
@@ -49,6 +50,8 @@ public class ConfigurationGetRequest extends FileEncryptedLookupAndGetRequest {
}
}
+ GB.toast("got config", 0, GB.INFO);
+
device.sendDeviceUpdateIntent(getAdapter().getContext());
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/json/JsonPutRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/json/JsonPutRequest.java
index 40edc79c8..bd2c9237a 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/json/JsonPutRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/json/JsonPutRequest.java
@@ -9,6 +9,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
public class JsonPutRequest extends FilePutRawRequest {
public JsonPutRequest(JSONObject object, FossilHRWatchAdapter adapter) {
- super((short)(0x0500 | adapter.getJsonIndex()), object.toString().getBytes(), adapter);
+ super((short)(0x0500 | (adapter.getJsonIndex() & 0xFF)), object.toString().getBytes(), adapter);
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/CustomWidget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/CustomWidget.java
index 1f5bb1d0d..e10bdcee3 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/CustomWidget.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/CustomWidget.java
@@ -5,13 +5,16 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
-public class CustomWidget {
+public class CustomWidget extends Widget {
private ArrayList elements = new ArrayList<>();
private int angle, distance;
+ private String name;
- public CustomWidget(int angle, int distance) {
+ public CustomWidget(String name, int angle, int distance) {
+ super(null, angle, distance);
this.angle = angle;
this.distance = distance;
+ this.name = name;
}
public int getAngle() {
@@ -22,7 +25,23 @@ public class CustomWidget {
return distance;
}
- public Collection getElements(){
+ public void setElements(ArrayList elements) {
+ this.elements = elements;
+ }
+
+ public void setAngle(int angle) {
+ this.angle = angle;
+ }
+
+ public void setDistance(int distance) {
+ this.distance = distance;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public ArrayList getElements(){
return this.elements;
}
@@ -49,4 +68,8 @@ public class CustomWidget {
}
return null;
}
+
+ public String getName() {
+ return name;
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/CustomWidgetElement.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/CustomWidgetElement.java
index 9e24a40d5..dfaded275 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/CustomWidgetElement.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/CustomWidgetElement.java
@@ -1,10 +1,37 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget;
-public class CustomWidgetElement {
+import java.io.Serializable;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+
+public class CustomWidgetElement implements Serializable {
public enum WidgetElementType {
- TYPE_TEXT,
- TYPE_IMAGE,
- TYPE_BACKGROUND
+ TYPE_TEXT(R.id.qhybrid_widget_elements_type_text, "text"),
+ TYPE_IMAGE(0, "image"),
+ TYPE_BACKGROUND(R.id.qhybrid_widget_elements_type_background, "background");
+
+ private String jsonIdentifier;
+ private int radioButtonResource;
+
+ WidgetElementType(int radioButtonResource, String jsonIdentifier){
+ this.radioButtonResource = radioButtonResource;
+ this.jsonIdentifier = jsonIdentifier;
+ }
+
+ public int getRadioButtonResource() {
+ return radioButtonResource;
+ }
+
+ public String getJsonIdentifier() {
+ return jsonIdentifier;
+ }
+
+ static public WidgetElementType fromRadioButtonRessource(int radioButtonResource){
+ for(WidgetElementType type : values()){
+ if(type.getRadioButtonResource() == radioButtonResource) return type;
+ }
+ return null;
+ }
}
public final static int X_CENTER = 38;
@@ -15,6 +42,22 @@ public class CustomWidgetElement {
private String id, value;
private int x, y;
+ public void setWidgetElementType(WidgetElementType widgetElementType) {
+ this.widgetElementType = widgetElementType;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public void setY(int y) {
+ this.y = y;
+ }
+
protected CustomWidgetElement(WidgetElementType widgetElementType, String id, String value, int x, int y) {
this.widgetElementType = widgetElementType;
this.id = id;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/Widget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/Widget.java
index b819e1637..148815de0 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/Widget.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/Widget.java
@@ -5,12 +5,18 @@ import androidx.annotation.NonNull;
import org.json.JSONException;
import org.json.JSONObject;
-public abstract class Widget {
+import java.io.Serializable;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+
+public class Widget implements Serializable {
private WidgetType widgetType;
int angle, distance;
- public Widget(WidgetType type, int angle, int distance){
+ public Widget(WidgetType type, int angle, int distance) {
this.widgetType = type;
+ this.angle = angle;
+ this.distance = distance;
}
@NonNull
@@ -19,7 +25,7 @@ public abstract class Widget {
return toJson().toString();
}
- public JSONObject toJson(){
+ public JSONObject toJson() {
JSONObject object = new JSONObject();
try {
@@ -27,13 +33,13 @@ public abstract class Widget {
.put("name", widgetType.getIdentifier())
.put("pos",
new JSONObject()
- .put("angle", angle)
- .put("distance", distance)
- )
+ .put("angle", angle)
+ .put("distance", distance)
+ )
.put("data", new JSONObject())
.put("theme",
new JSONObject()
- .put("font_color", "default")
+ .put("font_color", "default")
);
} catch (JSONException e) {
e.printStackTrace();
@@ -43,17 +49,35 @@ public abstract class Widget {
}
- enum WidgetType{
- TIMEZONE("timeZone2SSE");
+ public enum WidgetType {
+ HEART_RATE("hrSSE", R.string.hr_widget_heart_rate),
+ STEPS("stepsSSE", R.string.hr_widget_steps),
+ DATE("dateSSE", R.string.hr_widget_date),
+ ACTIVE_MINUTES("activeMinutesSSE", R.string.hr_widget_active_minutes),
+ CALORIES("caloriesSSE", R.string.hr_widget_calories),
+ BATTERY("batterySSE", R.string.hr_widget_battery),
+ NOTHING(null, R.string.hr_widget_nothing);
private String identifier;
+ private int stringResource;
-
- WidgetType(String identifier){
+ WidgetType(String identifier, int stringResource) {
this.identifier = identifier;
+ this.stringResource = stringResource;
}
- public String getIdentifier(){
+ public static WidgetType fromJsonIdentifier(String jsonIdentifier){
+ for(WidgetType type : values()){
+ if(type.getIdentifier() != null && type.getIdentifier().equals(jsonIdentifier)) return type;
+ }
+ return null;
+ }
+
+ public int getStringResource() {
+ return stringResource;
+ }
+
+ public String getIdentifier() {
return this.identifier;
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/WidgetsPutRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/WidgetsPutRequest.java
index d911b274f..aecef97e0 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/WidgetsPutRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/WidgetsPutRequest.java
@@ -16,7 +16,11 @@ public class WidgetsPutRequest extends JsonPutRequest {
private static JSONObject prepareFile(Widget[] widgets){
try {
- JSONArray widgetArray = new JSONArray(widgets);
+ JSONArray widgetArray = new JSONArray();
+
+ for(Widget widget : widgets){
+ widgetArray.put(widget.toJson());
+ }
JSONObject object = new JSONObject()
.put(
diff --git a/app/src/main/res/layout/activity_qhybrid_hr_settings.xml b/app/src/main/res/layout/activity_qhybrid_hr_settings.xml
index 16fff6026..bdf5d56f7 100644
--- a/app/src/main/res/layout/activity_qhybrid_hr_settings.xml
+++ b/app/src/main/res/layout/activity_qhybrid_hr_settings.xml
@@ -37,4 +37,51 @@
android:id="@+id/qhybrid_button_bottom_single_press"
android:textSize="20dp"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/qhybrid_activity_widget_settings.xml b/app/src/main/res/layout/qhybrid_activity_widget_settings.xml
new file mode 100644
index 000000000..a5c25077b
--- /dev/null
+++ b/app/src/main/res/layout/qhybrid_activity_widget_settings.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/qhybrid_element_popup_view.xml b/app/src/main/res/layout/qhybrid_element_popup_view.xml
new file mode 100644
index 000000000..4820e0c16
--- /dev/null
+++ b/app/src/main/res/layout/qhybrid_element_popup_view.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index be131d35a..e1ccafa6b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -773,6 +773,13 @@
offset timezone by
change might take some seconds…
offset time by
+ Heart rate
+ Steps
+ Date
+ Active minutes
+ Calories
+ Battery
+ Nothing
- %d hour
- %d hours