From 132d97ee955ee24228b65a60ec9b00d17bc2c6ed Mon Sep 17 00:00:00 2001 From: Daniel Dakhno Date: Sun, 19 Jan 2020 04:01:57 +0100 Subject: [PATCH] created UI to design custom widgets --- app/src/main/AndroidManifest.xml | 64 ++-- .../devices/qhybrid/HRConfigActivity.java | 297 +++++++++++++++++- .../qhybrid/WidgetSettingsActivity.java | 208 ++++++++++++ .../devices/qhybrid/QHybridSupport.java | 24 +- .../devices/qhybrid/adapter/WatchAdapter.java | 9 + .../adapter/fossil/FossilWatchAdapter.java | 20 ++ .../fossil_hr/FossilHRWatchAdapter.java | 131 +++++--- .../ConfigurationGetRequest.java | 3 + .../fossil_hr/json/JsonPutRequest.java | 2 +- .../fossil_hr/widget/CustomWidget.java | 29 +- .../fossil_hr/widget/CustomWidgetElement.java | 51 ++- .../requests/fossil_hr/widget/Widget.java | 48 ++- .../fossil_hr/widget/WidgetsPutRequest.java | 6 +- .../layout/activity_qhybrid_hr_settings.xml | 47 +++ .../qhybrid_activity_widget_settings.xml | 73 +++++ .../res/layout/qhybrid_element_popup_view.xml | 79 +++++ app/src/main/res/values/strings.xml | 7 + 17 files changed, 991 insertions(+), 107 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/WidgetSettingsActivity.java create mode 100644 app/src/main/res/layout/qhybrid_activity_widget_settings.xml create mode 100644 app/src/main/res/layout/qhybrid_element_popup_view.xml 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"/> + + + + + + + + + + + + +