mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-26 02:25:50 +01:00
Amazfit Cor: support custom emoji font
This commit refactors code and implements a custom device specific string filter, which does nothing by default. The implementation in HuamiSupport does the custom emoji conversion. The setting has been moved from devicesettings_amazfitbip.xml to an extra file As soon as there is a custom font for Mi Band 2/3/4 it is sufficient to add "devicesettings_custom_emoji_font.xml" to the list of supported settings in the appropriate coordinator and everything will work.
This commit is contained in:
parent
aa8c41f722
commit
876515f1fd
@ -167,9 +167,6 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
|||||||
@Override
|
@Override
|
||||||
public boolean supportsUnicodeEmojis() { return false; }
|
public boolean supportsUnicodeEmojis() { return false; }
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supportsCustomFont() { return false; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
|
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -280,11 +280,6 @@ public interface DeviceCoordinator {
|
|||||||
*/
|
*/
|
||||||
boolean supportsUnicodeEmojis();
|
boolean supportsUnicodeEmojis();
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether the device supports using a custom font.
|
|
||||||
*/
|
|
||||||
boolean supportsCustomFont();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates which device specific settings the device supports (not per device type or family, but unique per device).
|
* Indicates which device specific settings the device supports (not per device type or family, but unique per device).
|
||||||
*/
|
*/
|
||||||
|
@ -77,15 +77,11 @@ public class AmazfitBipCoordinator extends HuamiCoordinator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supportsCustomFont() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
|
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
|
||||||
return new int[]{
|
return new int[]{
|
||||||
R.xml.devicesettings_amazfitbip,
|
R.xml.devicesettings_amazfitbip,
|
||||||
|
R.xml.devicesettings_custom_emoji_font,
|
||||||
R.xml.devicesettings_liftwrist_display,
|
R.xml.devicesettings_liftwrist_display,
|
||||||
R.xml.devicesettings_disconnectnotification,
|
R.xml.devicesettings_disconnectnotification,
|
||||||
R.xml.devicesettings_expose_hr_thirdparty,
|
R.xml.devicesettings_expose_hr_thirdparty,
|
||||||
|
@ -84,6 +84,7 @@ public class AmazfitCorCoordinator extends HuamiCoordinator {
|
|||||||
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
|
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
|
||||||
return new int[]{
|
return new int[]{
|
||||||
R.xml.devicesettings_amazfitcor,
|
R.xml.devicesettings_amazfitcor,
|
||||||
|
R.xml.devicesettings_custom_emoji_font,
|
||||||
R.xml.devicesettings_liftwrist_display,
|
R.xml.devicesettings_liftwrist_display,
|
||||||
R.xml.devicesettings_disconnectnotification,
|
R.xml.devicesettings_disconnectnotification,
|
||||||
R.xml.devicesettings_expose_hr_thirdparty,
|
R.xml.devicesettings_expose_hr_thirdparty,
|
||||||
|
@ -409,4 +409,8 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
|||||||
|
|
||||||
LocalBroadcastManager.getInstance(context).sendBroadcast(messageIntent);
|
LocalBroadcastManager.getInstance(context).sendBroadcast(messageIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String customStringFilter(String inputString) {
|
||||||
|
return inputString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,6 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
|||||||
private CMWeatherReceiver mCMWeatherReceiver = null;
|
private CMWeatherReceiver mCMWeatherReceiver = null;
|
||||||
private LineageOsWeatherReceiver mLineageOsWeatherReceiver = null;
|
private LineageOsWeatherReceiver mLineageOsWeatherReceiver = null;
|
||||||
private OmniJawsObserver mOmniJawsObserver = null;
|
private OmniJawsObserver mOmniJawsObserver = null;
|
||||||
private Random mRandom = new Random();
|
|
||||||
|
|
||||||
private final String[] mMusicActions = {
|
private final String[] mMusicActions = {
|
||||||
"com.android.music.metachanged",
|
"com.android.music.metachanged",
|
||||||
@ -370,21 +369,9 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
|||||||
if (text == null || text.length() == 0)
|
if (text == null || text.length() == 0)
|
||||||
return text;
|
return text;
|
||||||
|
|
||||||
|
text = mDeviceSupport.customStringFilter(text);
|
||||||
|
|
||||||
if (!mCoordinator.supportsUnicodeEmojis()) {
|
if (!mCoordinator.supportsUnicodeEmojis()) {
|
||||||
|
|
||||||
// use custom font for emoji, if it is supported and enabled
|
|
||||||
if (mCoordinator.supportsCustomFont()) {
|
|
||||||
switch (mCoordinator.getDeviceType()) {
|
|
||||||
case AMAZFITBIP:
|
|
||||||
if (((HuamiCoordinator)mCoordinator).getUseCustomFont(mGBDevice.getAddress()))
|
|
||||||
return StringUtils.toCustomFont(text);
|
|
||||||
break;
|
|
||||||
// TODO: implement for Amazfit Cor
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return EmojiConverter.convertUnicodeEmojiToAscii(text, getApplicationContext());
|
return EmojiConverter.convertUnicodeEmojiToAscii(text, getApplicationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,7 +750,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
|||||||
if (mOmniJawsObserver == null && coordinator != null && coordinator.supportsWeather()) {
|
if (mOmniJawsObserver == null && coordinator != null && coordinator.supportsWeather()) {
|
||||||
try {
|
try {
|
||||||
mOmniJawsObserver = new OmniJawsObserver(new Handler());
|
mOmniJawsObserver = new OmniJawsObserver(new Handler());
|
||||||
getContentResolver().registerContentObserver(mOmniJawsObserver.WEATHER_URI, true, mOmniJawsObserver);
|
getContentResolver().registerContentObserver(OmniJawsObserver.WEATHER_URI, true, mOmniJawsObserver);
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
//Nothing wrong, it just means we're not running on omnirom.
|
//Nothing wrong, it just means we're not running on omnirom.
|
||||||
}
|
}
|
||||||
|
@ -130,4 +130,9 @@ public interface DeviceSupport extends EventHandler {
|
|||||||
* Returns the Android context to use, e.g. to look up resources.
|
* Returns the Android context to use, e.g. to look up resources.
|
||||||
*/
|
*/
|
||||||
Context getContext();
|
Context getContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts String in a device specific way, e.g. re-map characters for a custom font
|
||||||
|
*/
|
||||||
|
String customStringFilter(String inputString);
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,11 @@ public class ServiceDeviceSupport implements DeviceSupport {
|
|||||||
return delegate.getContext();
|
return delegate.getContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String customStringFilter(String inputString) {
|
||||||
|
return delegate.customStringFilter(inputString);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean useAutoConnect() {
|
public boolean useAutoConnect() {
|
||||||
return delegate.useAutoConnect();
|
return delegate.useAutoConnect();
|
||||||
|
@ -127,6 +127,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
||||||
|
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_VIBRATION_COUNT;
|
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.DEFAULT_VALUE_VIBRATION_COUNT;
|
||||||
@ -414,7 +415,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
|
|||||||
int userid = alias.hashCode(); // hash from alias like mi1
|
int userid = alias.hashCode(); // hash from alias like mi1
|
||||||
|
|
||||||
// FIXME: Do encoding like in PebbleProtocol, this is ugly
|
// FIXME: Do encoding like in PebbleProtocol, this is ugly
|
||||||
byte bytes[] = new byte[]{
|
byte[] bytes = new byte[]{
|
||||||
HuamiService.COMMAND_SET_USERINFO,
|
HuamiService.COMMAND_SET_USERINFO,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -913,7 +914,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getLatency(int minConnectionInterval, int maxConnectionInterval, int latency, int timeout, int advertisementInterval) {
|
private byte[] getLatency(int minConnectionInterval, int maxConnectionInterval, int latency, int timeout, int advertisementInterval) {
|
||||||
byte result[] = new byte[12];
|
byte[] result = new byte[12];
|
||||||
result[0] = (byte) (minConnectionInterval & 0xff);
|
result[0] = (byte) (minConnectionInterval & 0xff);
|
||||||
result[1] = (byte) (0xff & minConnectionInterval >> 8);
|
result[1] = (byte) (0xff & minConnectionInterval >> 8);
|
||||||
result[2] = (byte) (maxConnectionInterval & 0xff);
|
result[2] = (byte) (maxConnectionInterval & 0xff);
|
||||||
@ -2079,6 +2080,42 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String customStringFilter(String inputString) {
|
||||||
|
if (HuamiCoordinator.getUseCustomFont(gbDevice.getAddress())) {
|
||||||
|
return convertEmojiToCustomFont(inputString);
|
||||||
|
}
|
||||||
|
return inputString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String convertEmojiToCustomFont(String str) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int i = 0;
|
||||||
|
while (i < str.length()) {
|
||||||
|
char charAt = str.charAt(i);
|
||||||
|
if (Character.isHighSurrogate(charAt)) {
|
||||||
|
int i2 = i + 1;
|
||||||
|
try {
|
||||||
|
int codePoint = Character.toCodePoint(charAt, str.charAt(i2));
|
||||||
|
if (codePoint < 127744 || codePoint > 129510) {
|
||||||
|
sb.append(charAt);
|
||||||
|
} else {
|
||||||
|
sb.append((char) (codePoint - 83712));
|
||||||
|
i = i2;
|
||||||
|
}
|
||||||
|
} catch (StringIndexOutOfBoundsException e) {
|
||||||
|
LOG.warn("error while converting emoji to custom font", e);
|
||||||
|
sb.append(charAt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append(charAt);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public void phase2Initialize(TransactionBuilder builder) {
|
public void phase2Initialize(TransactionBuilder builder) {
|
||||||
LOG.info("phase2Initialize...");
|
LOG.info("phase2Initialize...");
|
||||||
requestBatteryInfo(builder);
|
requestBatteryInfo(builder);
|
||||||
|
@ -96,36 +96,4 @@ public class StringUtils {
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param str original text
|
|
||||||
* @return str with the emoticons in a format that can be displayed on an
|
|
||||||
* Amazfit Bip by using a custom font firmware with emoji support
|
|
||||||
*/
|
|
||||||
public static String toCustomFont(String str) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
int i = 0;
|
|
||||||
while (i < str.length()) {
|
|
||||||
char charAt = str.charAt(i);
|
|
||||||
if (Character.isHighSurrogate(charAt)) {
|
|
||||||
int i2 = i + 1;
|
|
||||||
try {
|
|
||||||
int codePoint = Character.toCodePoint(charAt, str.charAt(i2));
|
|
||||||
if (codePoint < 127744 || codePoint > 129510) {
|
|
||||||
sb.append(charAt);
|
|
||||||
} else {
|
|
||||||
sb.append(Character.toString((char) (codePoint - 83712)));
|
|
||||||
i = i2;
|
|
||||||
}
|
|
||||||
} catch (StringIndexOutOfBoundsException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
sb.append(charAt);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sb.append(charAt);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,4 @@
|
|||||||
android:key="language"
|
android:key="language"
|
||||||
android:summary="%s"
|
android:summary="%s"
|
||||||
android:title="@string/pref_title_language" />
|
android:title="@string/pref_title_language" />
|
||||||
<CheckBoxPreference
|
|
||||||
android:icon="@drawable/ic_font_download"
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="use_custom_font"
|
|
||||||
android:summary="@string/pref_summary_use_custom_font"
|
|
||||||
android:title="@string/pref_title_use_custom_font" />
|
|
||||||
</androidx.preference.PreferenceScreen>
|
</androidx.preference.PreferenceScreen>
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:icon="@drawable/ic_font_download"
|
||||||
|
android:key="use_custom_font"
|
||||||
|
android:summary="@string/pref_summary_use_custom_font"
|
||||||
|
android:title="@string/pref_title_use_custom_font" />
|
||||||
|
</androidx.preference.PreferenceScreen>
|
Loading…
Reference in New Issue
Block a user