Kaufen Sie ein chinesisches Armband, lassen Sie sich von der offiziellen Software enttäuschen, schreiben Sie Ihr eigenes!
Diese Geschichte wartet seit mehr als sechs Monaten auf ihre Veröffentlichung. In dieser Zeit hat sich viel geändert, Firmware und Software wurden aktualisiert und viele meiner Entwicklungen sind bereits veraltet.Vorwort
Die aktive Arbeit einer Vielzahl von Unternehmen auf dem Gebiet der tragbaren Technologie und der intelligenten Uhren hat meiner Seele keinen Frieden gelassen. Ich sah großes Potenzial in tragbaren Geräten mit einem Bildschirm. Nein, ich spreche nicht über das Zählen von Schritten und anderen Fitness-Dingen, sie sind sicherlich cool, aber weit entfernt von dem banalen „Herzlichen Glückwunsch! Du bist 4 km gelaufen und hast mehr als 20 km gemacht! “ und schöne Grafiken von Fortschritt und Regression, sie haben sich nichts Besonderes ausgedacht.Die Tatsache, dass ich Benachrichtigungen direkt auf dem Display an meinem Handgelenk erhalten kann, ist praktisch. Wenn ich auch irgendwie mit ihm oder mit etwas in der Nähe interagieren kann, indem ich 1-2-3 Tasten drücke, ist das noch cooler.Wieder einmal stieß ich beim Pflügen der Aliexpress-Weiten auf ein iWown i5-Fitnessarmband. Er erregte sofort meine Aufmerksamkeit zu einem unglaublich niedrigen Preis (zu dieser Zeit ungefähr 800r mit kostenlosem Versand) und dem Vorhandensein eines OLED-Displays. Nachdem ich die Beschreibung des Verkäufers und die Kundenbewertungen sorgfältig gelesen hatte, entschied ich mich, dieses Wunder zu bestellen.Deklarierte Spezifikationen (Übersetzungsbeschreibung von aliexpress):- Anzeige: OLED
- Batterie: Li-Polymer
- Aufladen: Standard-USB-Aufladung
- Standby-Zeit: mehr als 72 Stunden
- Abmessungen: 69,1 * 15,8 * 11,2 mm
- Gewicht: 18g
- Material: ABS-Armband, Stahlverschluss
- Wasserbeständigkeit: IP55
- Betriebstemperatur: -20 ° C ~ + 45 ° C.
- Betriebstemperatur-Flash-Medien: -40 ° C ~ + 45 ° C.
Fähigkeiten:- Sportmonitor: Jeder Schritt zeichnet Schritte und Bewegungen, zurückgelegte Strecken und verbrannte Kalorien auf. Alle Zahlen werden unter Berücksichtigung Ihres Gewichts und Ihrer Größe berechnet.
- Überwachen der Schlafqualität: Während Sie schlafen, zeichnet der Tracker die Schlafphasen auf und bestimmt den tiefen und schnellen Schlaf. Mit 8 Gruppen stiller Alarme können Sie Sie wecken, ohne andere Familienmitglieder zu stören
- Bluetooth 4.0 Wireless-Synchronisierung mit geringem Stromverbrauch
- Unterstützt die PC-Synchronisierung über USB
- IP55-Schutz: Schützt das Gerät bei starkem Regen, jedoch nicht mehr
und andere "weit hergeholte" Vorteile im Stil des chinesischen MarketingsIch war sehr interessiert an der Möglichkeit, einen Traum zu verfolgen und in der richtigen Phase aufzuwachen. Viele meiner Freunde kauften gerade wegen dieser Funktion preiswerte Fitness-Tracker und waren mit mi band und dergleichen zufrieden. Mir fehlte immer ein Bildschirm, aber hier ist alles in einem.In meiner Arbeit muss ich oft einfache Anwendungen für Android entwickeln. Ich habe beschlossen, dass ich meine eigenen schreiben werde, wenn ich nicht über genügend Funktionen meiner nativen Anwendung verfüge.Das Paket kam ziemlich schnell an und ich beeilte mich sofort, ein wundervolles Armband zu studieren. Nachdem ich eine Stunde lang mit der Zeroner-Anwendung gespielt hatte, die gemäß den Anweisungen auf meinem Android-Gerät installiert sein muss, stellte ich fest, dass die Funktionalität eher schlecht und traurig ist. Zeroner hat sich wie alle anderen Hersteller darauf konzentriert, Schritte und Kalorien zu zählen, schöne Grafiken anzuzeigen, verfügt über eine Telefonsuchfunktion (ich werde später darauf eingehen), kann Sie über einen eingehenden Anruf, das Eintreffen einer Nachricht auf Facebook und WhatsApp benachrichtigen und Benachrichtigungen von EINER ausgewählten Anwendung senden , die als Anwendung für SMS betrachtet wird.Die Vibration des Armbands ist sehr umstritten, sie schreiben in den Foren, dass es eher schwach ist, manche sagen, es sei normal. Für mich hätte es stärker sein können. Das Armband reagiert auf die Geste „Watch the Watch“. Wenn Sie das Armband wie eine Uhr betrachten, Ihre Hand heben und sich am Ellbogen beugen, wird der Bildschirm automatisch eingeschaltet und zeigt die Uhrzeit oder die verpasste Benachrichtigung an.
Im Allgemeinen habe ich mich ohne zu zögern entschlossen, meine Bewerbung mit Benachrichtigungen, Vibrationen und Synchronisation zu schreiben. Ich renne voran, es dauerte 4 Tage und mehrere lange Abende ...Zum Geschäft
Da ich mit Bluetooth kein Blue-Tooth-Toe bin, habe ich mich entschlossen, die zwischen dem Telefon und dem Armband ausgetauschten Daten mit einem Narren abzufangen. Zu diesem Zweck bin ich auf die Registerkarte für Entwickler geklettert und habe das Kontrollkästchen "HCI Bluetooth Broadcast Log aktivieren " aktiviert . Nachdem Sie diese Option aktiviert haben, wird der gesamte Speicherauszug der Android-Kommunikation mit Bluetooth-Geräten zur Datei /sdcard/Android/data/btsnoop_hci.log hinzugefügt (der Pfad kann sich für verschiedene Geräte ändern, der Dateiname scheint immer der gleiche zu sein).Nachdem ich WireShark heruntergeladen hatte, begann ich, die Protokolle der Kommunikation mit dem Armband zu studieren und sah etwas Ähnliches:
Nachdem ich fast zwei Stunden damit verbracht hatte, die Protokolle zu studieren, Suchtprobleme zu lösen und Protokolle im Internet zu googeln, wurde mir klar, dass ein solcher Weg nichts für mich ist.Da mein Telefon das Armband dennoch als normales BLE-Gerät interpretierte und es im Abschnitt "Verbundene Geräte" zeigte, entschied ich mich, Beispiele für die Arbeit mit BLE aus dem Android SDK zu verwenden.Nachdem Sie das Repository https://github.com/googlesamples/android-BluetoothLeGatt geklont haben , setzen Sie Android Studio mit dem Quellcode auf den Nabel, erstellen und starten Sie die Anwendung. ( Link zur Beschreibung des Android SDK mit Bluetooth LE )Es stellte sich wie auf den Bildern vom Github heraus:
Nachdem der Scan ausgeführt wurde, sah die Anwendung das Gerät nicht. Es stellte sich heraus, dass die native Anwendung durch Verbinden mit dem Armband BLE nicht erlaubte, das Gerät zu finden. Alles wurde durch einfaches Entfernen von Zeroner entschieden, es war möglich, einfach die Verbindung zu trennen, aber es war zuverlässiger, es vollständig abzureißen.Bluetooth LE ist eine Technologie, die auf Geräten mit geringem Stromverbrauch aufbaut und in neuen Sensoren, Tags und vielen anderen Geräten verwendet wird. Die Basis dieser Technologie ist das generische Attributprofil (GATT) . Hierbei handelt es sich um ein Bluetooth-Profil, mit dem Sie kleine Daten, „Attribute“ , austauschen können . Ich werde lange nicht darüber schreiben, wie das alles funktioniert, es gibt viele Informationen im Hub und im Internet, die ich auch nach Lösungen durchsuchen musste.Ich hoffte, dass alle benötigten Daten in den Merkmalen und Deskriptoren des Armbands gespeichert waren und ich problemlos Daten empfangen und aufzeichnen konnte. Ich habe mich geirrt ... DieTest-BLE-Anwendung zeigte mir nur 4 Dienste:0000180f-0000-1000-8000-00805f9b34fb00001800-0000-1000-8000-00805f9b34fb0000ff20-0000-1000-8000-00805f9b34fb00001801-0000-1000-8000-00805f9b34fb Esgab nur sehr wenige Merkmale in ihnen, die gelesen wurden, gaben Leerzeichen oder Nullen zurück, und das Schreiben war nutzlos. Aber ich wurde ermutigt, dass ich mich verbinden und zumindest einige Daten erhalten konnte.Außerdem entschied ich, dass es nicht möglich war, blind zu handeln, und beschloss, die Zeroner-Anwendung zu zerlegen. Nachdem ich ein paar Online-APK-Dekompilierer im Internet gesammelt hatte, fütterte ich sie zeroner.apk und bekam 2 Zip-Archive auf der Ausgabe.Die erste war eine JADX-Version und die zweite enthielt das Ergebnis von apktool.Beim Stöbern im Quellcode hatte ich Angst vor dem chinesischen Code(Obwohl ich in meiner Arbeit oft in Form von Backends für Websites und Dienste auf ihn stoße, überrascht er mich immer wieder mit seiner Tortuosität und seinem Einfallsreichtum, aber es ist schrecklich schwer zu lesen.)Nach langem Suchen bin ich schließlich auf die Datei WristBandDevice.java gestoßen . Das war auf dem Weg com.kunekt / bluetooth.In dieser Klasse versteckte sich die ganze Arbeit mit dem Gerät nur, aber wieder wartete ein Hinterhalt auf mich.Wie sich später herausstellte, wurden in der vorherigen Firmware des Armbands mehr Dienste in den Merkmalen verwendet (wie ich zuvor erwartet hatte), aber später ließen die Entwickler nur 2 übrig, einen zum Lesen, den zweiten zum Schreiben. Alle Befehle werden in einem Paket übertragen.Es war nicht so einfach zu verstehen, wie das Paket aussehen sollte. Ich entschied mich zunächst klar zu bestimmen, was ich vom Armband möchte, damit ich beginnen konnte, die Funktionsaufrufe zu verfolgen. Und ich wollte benutzerdefinierte Nachrichten auf dem Armband anzeigen.Ohne zu zögern stieg ich in com.kunekt / recept / CallReceiver.java ein , da eingehende Anrufe sehr stabil angezeigt wurden und selbst mit russischen Zeichen entschied ich, dass dies ein guter Anfang war, da ich bereits auf ein eingehendes Anrufereignis in Android gestoßen war wie es funktionieren könnte war schon.Beim Öffnen der Datei sah ich Folgendes:Ein großes Stück chinesischen Codespublic void onReceive(Context context, Intent intent) {
Log.e(this.TAG, "+++ ON RECEIVE +++");
switch (((TelephonyManager) context.getSystemService("phone")).getCallState()) {
case C08571.POSITION_OPEN :
if (ZeronerApplication.newAPI) {
BackgroundThreadManager.getInstance().addTask(new WriteOneDataTask(context, WristBandDevice.getInstance(context).setPhoneStatue()));
}
case BitmapCacheManagementTask.MESSAGE_INIT_DISK_CACHE :
incomingNumber = intent.getStringExtra("incoming_number");
Contact contact = getContact(context, incomingNumber);
if (!WristBandDevice.getInstance(context).isConnected() || !ZeronerApplication.phoneAlert) {
return;
}
if (ZeronerApplication.newAPI) {
this.fMdeviceInfo = jsonToFMdeviceInfo(UserConfig.getInstance(context).getDevicesInfo());
if (this.fMdeviceInfo.getModel().indexOf("5+") != -1) {
if (UserConfig.getInstance(context).getFont_lib() == 1 || UserConfig.getInstance(context).getFont_lib() == 2 || UserConfig.getInstance(context).getSysFont().equalsIgnoreCase("en") || UserConfig.getInstance(context).getSysFont().equalsIgnoreCase("es")) {
if (contact.getDisplayName().length() > 11) {
WristBandDevice.getInstance(context).writeWristBandFontLibrary(context, 1, contact.getDisplayName().substring(0, 11));
} else if (contact.getDisplayName().length() <= 6 || contact.getDisplayName().length() > 11) {
WristBandDevice.getInstance(context).writeWristBandFontLibrary(context, 1, contact.getDisplayName());
} else {
WristBandDevice.getInstance(context).writeWristBandFontLibrary(context, 1, contact.getDisplayName().substring(0, contact.getDisplayName().length()));
}
} else if (contact.getDisplayName().length() > 11) {
WristBandDevice.getInstance(context).writeWristBandPhoneAlertNew(context, contact.getDisplayName().substring(0, 11));
} else if (contact.getDisplayName().length() <= 6 || contact.getDisplayName().length() > 11) {
WristBandDevice.getInstance(context).writeWristBandPhoneAlertNew(context, contact.getDisplayName());
} else {
WristBandDevice.getInstance(context).writeWristBandPhoneAlertNew(context, contact.getDisplayName().substring(0, contact.getDisplayName().length()));
}
} else if (contact.getDisplayName().length() > 11) {
WristBandDevice.getInstance(context).writeWristBandPhoneAlertNew(context, contact.getDisplayName().substring(0, 11));
} else if (contact.getDisplayName().length() <= 6 || contact.getDisplayName().length() > 11) {
WristBandDevice.getInstance(context).writeWristBandPhoneAlertNew(context, contact.getDisplayName());
} else {
WristBandDevice.getInstance(context).writeWristBandPhoneAlertNew(context, contact.getDisplayName().substring(0, contact.getDisplayName().length()));
}
} else if (contact.getDisplayName().length() > 11) {
WristBandDevice.getInstance(context).writeWristBandPhoneAlert(context, contact.getDisplayName().substring(0, 11));
} else if (contact.getDisplayName().length() <= 6 || contact.getDisplayName().length() > 11) {
WristBandDevice.getInstance(context).writeWristBandPhoneAlert(context, contact.getDisplayName());
} else {
WristBandDevice.getInstance(context).writeWristBandPhoneAlert(context, contact.getDisplayName().substring(0, contact.getDisplayName().length()));
}
case BitmapCacheManagementTask.MESSAGE_FLUSH :
if (ZeronerApplication.newAPI) {
BackgroundThreadManager.getInstance().addTask(new WriteOneDataTask(context, WristBandDevice.getInstance(context).setPhoneStatue()));
}
default:
}
}
Hier sehen wir deutlich, dass es zwei Optionen für die API gibt und die Namen, die sie haben, sehr logisch sind, newAPI und die zweite, oldAPI. Bei all dieser Fülle von Bedingungen war ich nur an einer sich wiederholenden Zeile interessiert:WristBandDevice.getInstance (Kontext) .writeWristBandPhoneAlertNew (Kontext, contact.getDisplayName .....)Dies war, wonach ich suchte. Mit Blick auf die Zukunft werde ich sagen, dass iWown auch i5 + - und i6-Modelle hat, einen größeren Bildschirm hat und dementsprechend mehr Zeichen platziert werden, dafür sind all diese Überprüfungen erforderlich. Es ist nicht klar, warum sie keine Klasse oder ähnliches geschrieben haben. Vielleicht sind dies Dekompiler-Streiche, aber dieser Code wird an vielen Stellen wiederholt.Bei der Definition dieser Funktion habe ich Folgendes gesehen: public void writeWristBandPhoneAlertNew(Context context, String displayName) {
writeAlertNew(context, displayName, 1);
}
public void writeWristBandSmsAlertNew(Context context, String displayName) {
writeAlertNew(context, displayName, 2);
}
Großartig, es verwendet dieselbe Funktion zum Senden von Text, nur mit unterschiedlichen Parametern. Alle Funktionen mit dem Wort Neu sind nur unsere Option, da ich, wie oben herausgestellt, eine neue API habe.Als ich gerne zur Definition der Funktion writeAlertNew überging , sah ich Folgendes:private void writeAlertNew(Context context, String displayName, int type) {
ArrayList<Byte> datas = new ArrayList();
datas.add(Byte.valueOf((byte) type));
int i = 0;
while (i < displayName.length()) {
if (displayName.charAt(i) < '@' || (displayName.charAt(i) < '\u0080' && displayName.charAt(i) > '`')) {
char e = displayName.charAt(i);
datas.add(Byte.valueOf((byte) 0));
for (byte valueOf : PebbleBitmap.fromString(context, String.valueOf(e), 8, 1).data) {
datas.add(Byte.valueOf(valueOf));
}
} else {
char c = displayName.charAt(i);
datas.add(Byte.valueOf((byte) 1));
for (byte valueOf2 : PebbleBitmap.fromString(context, String.valueOf(c), 16, 1).data) {
datas.add(Byte.valueOf(valueOf2));
}
}
i++;
}
byte[] data = writeWristBandDataByte(true, form_Header(3, 1), datas);
for (i = 0; i < data.length; i += 20) {
byte[] writeData;
if (i + 20 > data.length) {
writeData = Arrays.copyOfRange(data, i, data.length);
} else {
writeData = Arrays.copyOfRange(data, i, i + 20);
}
NewAgreementBackgroundThreadManager.getInstance().addTask(new WriteOneDataTask(context, writeData));
}
}
Es war klar, dass einige Funktionen, die hier verwendet werden, mich vom Gewinn trennen.writeWristBandDataByte - bildet ein Paket mit einer Nachricht für das Armband. Es ist interessant, dass es eine spezielle Funktion form_Header (3, 1) gibt , die den Header des Pakets bildet, anhand dessen das Armband versteht, was es von ihm will. 3 ist die Nummer der Teamgruppe und 1 ist das Team selbstpublic static byte form_Header(int grp, int cmd) {
return (byte) (((((byte) grp) & 15) << 4) | (((byte) cmd) & 15));
}
Die Funktion ist einfach und wird ohne Änderungen in mein Projekt kopiert. Als nächstes kamNewAgreementBackgroundThreadManager.getInstance (). AddTask (new WriteOneDataTask (context, writeData));Wie sich herausstellte, erstellt die Anwendung einen Stream, in dem die Warteschlange der zu sendenden Pakete ständig überprüft wird. Wenn ein Paket in der Warteschlange erscheint, schreibt der Stream in die angegebene Geräteeigenschaft. Wenn mehr als ein Paket vorhanden ist, sendet er sie mit einer Verzögerung von 240 Millisekunden.Als nächstes kam das Unverständlichste:PebbleBitmap.fromString (Kontext, String.valueOf (e), 8, 1) .data)Warum die Klasse so heißt, ist nicht klar, da dieses Gerät nichts mit Pebble zu tun hat. Beim Öffnen der Klassenquelle sah ich Folgendes:PebbleBitmap-Klassenquellepublic class PebbleBitmap {
public static boolean f1285D;
public final byte[] data;
public final UnsignedInteger flags;
public final short height;
public int index;
public int offset;
public final UnsignedInteger rowLengthBytes;
public final short width;
public final short f1286x;
public final short f1287y;
static {
f1285D = true;
}
private PebbleBitmap(UnsignedInteger _rowLengthBytes, UnsignedInteger _flags, short _x, short _y, short _width, short _height, byte[] _data) {
this.offset = 0;
this.index = 0;
this.rowLengthBytes = _rowLengthBytes;
this.flags = _flags;
this.f1286x = _x;
this.f1287y = _y;
this.width = _width;
this.height = _height;
this.data = _data;
}
public static PebbleBitmap fromString(Context context, String text, int w, int l) {
TextPaint textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setTextSize(16.5f);
if (w == 32) {
textPaint.setTextAlign(Align.CENTER);
}
textPaint.setTypeface(ZeronerApplication.unifont);
StaticLayout sl = new StaticLayout(text, textPaint, w, Alignment.ALIGN_NORMAL, 1.0f, 0.49f, false);
int h = sl.getHeight();
if (h > l * 16) {
h = l * 16;
}
Bitmap newBitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
sl.draw(new Canvas(newBitmap));
return fromAndroidBitmap(newBitmap);
}
public static PebbleBitmap fromAndroidBitmap(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int rowLengthBytes = width / 8;
ByteBuffer data = ByteBuffer.allocate(rowLengthBytes * height);
data.order(ByteOrder.LITTLE_ENDIAN);
StringBuffer stringBuffer = new StringBuffer(StatConstants.MTA_COOPERATION_TAG);
for (int y = 0; y < height; y++) {
int[] pixels = new int[width];
bitmap.getPixels(pixels, 0, width * 2, 0, y, width, 1);
stringBuffer = new StringBuffer(StatConstants.MTA_COOPERATION_TAG);
for (int x = 0; x < width; x++) {
if (pixels[x] == 0) {
stringBuffer.append(Constants.VIA_RESULT_SUCCESS);
if (f1285D) {
stringBuffer.append("-");
}
} else {
stringBuffer.append(Constants.VIA_TO_TYPE_QQ_GROUP);
if (f1285D) {
stringBuffer.append("#");
}
}
}
for (int k = 0; k < rowLengthBytes * 8; k += 8) {
ByteBuffer byteBuffer = data;
byteBuffer.put(Byte.valueOf((byte) new BigInteger(stringBuffer.substring(k, k + 8), 2).intValue()).byteValue());
}
if (f1285D) {
stringBuffer.append("\n");
}
Log.i("info", stringBuffer.toString());
}
if (f1285D) {
System.out.println(stringBuffer.toString());
}
if (!(bitmap == null || bitmap.isRecycled())) {
bitmap.recycle();
}
System.gc();
return new PebbleBitmap(UnsignedInteger.fromIntBits(rowLengthBytes), UnsignedInteger.fromIntBits(DfuSettingsConstants.SETTINGS_DEFAULT_MBR_SIZE), (short) 0, (short) 0, (short) width, (short) height, data.array());
}
public static PebbleBitmap fromPng(InputStream paramInputStream) throws IOException {
return fromAndroidBitmap(BitmapFactory.decodeStream(paramInputStream));
}
}
Nach langer Überlegung kam ich zu dem Schluss, dass fromString ein Bild mit einem Buchstaben unter Verwendung einer bestimmten Schriftart (die in die Anwendung eingebettet ist) erstellt und dann die Pixel je nach Füllung in 0 oder 1 konvertiert, sodass der Buchstabe Oungefähr soaussieht : 00011100 01100011011000110110001100011100Ohne wirklich auf die Details einzugehen , habe ich alles anhand des Google-Beispiels BLE GATT in mein Projekt kopiert.Und ... Oh, ein Wunder !!! Das Armband vibrierte! Die Nachricht wurde jedoch nicht angezeigt, eine leere Zeile und ein Symbol für eingehende Anrufe.Es stellte sich heraus, dass eine Reihe von Größenprüfungen nicht zufällig sind. Das Armband ignoriert dumm zu lange Nachrichten und Nachrichten mit einer Länge von 11 Zeichen, obwohl 12 normalerweise angezeigt werden. Ein paar Stunden Tanzen um diese Funktionen herum führten schließlich zu Ergebnissen. Ich lernte, sowohl russischen als auch englischen Text anzuzeigen, und gleichzeitig erfuhr ich, dass es in der Nachrichtengruppe mehrere Betriebsmodi gibt:- Eingehender Anruf. Das Mobilteil wird angezeigt, der Name des Anrufers und das Armband vibrieren
- Nachricht Das Text- und Umschlagsymbol wird angezeigt. Wenn es 2 mal vibriert
- Bewölkt. Das gleiche wie 2, jedoch anstelle des Umschlags das Wolkensymbol
- Der Fehler. Gleich wie 2, dass nur ein Symbol mit einem Ausrufezeichen.
Nachdem ich meiner Anwendung beigebracht hatte, mir Benachrichtigungen von verschiedenen Anwendungen zu senden, WhatsApp, VK, Viber, Telegramm und anderen, entschied ich, dass es Zeit war, dem Armband beizubringen, auf eingehende Anrufe zu reagieren und schließlich mit einer einzigen Taste eingehende Anrufe zurückzusetzen.Ich werde diesen Vorgang nicht beschreiben. Der Beitrag erwies sich als aufgebläht. Ich möchte nur sagen, dass es nicht schwierig war, auf eingehende Nachrichten zu antworten, aber die Schaltfläche nicht zu verwenden.Alle eingehenden Nachrichten aus dem Armband hat Zeroner in einer speziellen Klasse abgefangen. Das eingehende Paket hatte die Überschrift der Befehlsgruppe und die Befehlsnummer. Nach einem langen Debug und Tests habe ich die verwendeten Gruppen herausgefischt und dann eine Beschreibung im Zeroner-Code gefunden.Armbandgruppen und Teams// HEADER GROUPS //
DEVICE = 0
CONFIG = 1
DATALOG = 2
MSG = 3
PHONE_MSG = 4
// CONFIG = 1 ///
CMD_ID_CONFIG_GET_AC = 5
CMD_ID_CONFIG_GET_BLE = 3
CMD_ID_CONFIG_GET_HW_OPTION = 9
CMD_ID_CONFIG_GET_NMA = 7
CMD_ID_CONFIG_GET_TIME = 1
CMD_ID_CONFIG_SET_AC = 4
CMD_ID_CONFIG_SET_BLE = 2
CMD_ID_CONFIG_SET_HW_OPTION = 8
CMD_ID_CONFIG_SET_NMA = 6
CMD_ID_CONFIG_SET_TIME = 0
// DATALOG = 2 //
CMD_ID_DATALOG_CLEAR_ALL = 2
CMD_ID_DATALOG_GET_BODY_PARAM = 1
CMD_ID_DATALOG_SET_BODY_PARAM = 0
CMD_ID_DATALOG_GET_CUR_DAY_DATA = 7
CMD_ID_DATALOG_START_GET_DAY_DATA = 3
CMD_ID_DATALOG_START_GET_MINUTE_DATA = 5
CMD_ID_DATALOG_STOP_GET_DAY_DATA = 4
CMD_ID_DATALOG_STOP_GET_MINUTE_DATA = 6
// DEVICE = 0 //
CMD_ID_DEVICE_GET_BATTERY = 1
CMD_ID_DEVICE_GET_INFORMATION = 0
CMD_ID_DEVICE_RESE = 2
CMD_ID_DEVICE_UPDATE = 3
// MSG = 3 //
CMD_ID_MSG_DOWNLOAD = 1
CMD_ID_MSG_MULTI_DOWNLOAD_CONTINUE = 3
CMD_ID_MSG_MULTI_DOWNLOAD_END = 4
CMD_ID_MSG_MULTI_DOWNLOAD_START = 2
CMD_ID_MSG_UPLOAD = 0
// PHONE_MSG = 4 //
CMD_ID_PHONE_ALERT = 1
CMD_ID_PHONE_PRESSKEY = 0
Dank dessen konnte ich eine vollwertige Arbeit mit dem Armband realisieren. Ich kann Daten über Schritte, über Schlaf erhalten. Ich kann die Einstellungen verwalten, Alarme einstellen. Ich habe es geschafft, die Byte-Bezeichnung des Pakets selbst von den Klassen zu erhalten, die Daten in der Datenbank speichern. Ich habe sie alle zu Hause implementiert.Zusammenfassend
Nach einigem Überlegen entschied ich, dass all dies nicht nur für mich nützlich sein könnte, sondern schrieb eine neue Anwendung, die alle erforderlichen Daten und Funktionen für die Arbeit mit dem Armband enthält und eine einfache Schnittstelle zum Senden von Benachrichtigungen von jeder Anwendung an das Armband implementiert.WiliX iWown für GeekSeitdem ist viel Zeit vergangen, und viele nach dem Update auf Android 6 funktionierte die Anwendung nicht mehr. Es funktioniert auch nicht stabil mit der Firmware von Armbändern der 2. Version. Aber ich hoffe, Zeit für eine Überarbeitung zu finden.Der Quellcode wird auf GitHub veröffentlicht . Sie können sich teilen und Spaß haben, wie Sie möchten. Alle Pull-Anfragen nach der Überprüfung werden akzeptiert und nach den Tests sofort auf Google Play hochgeladen.Im Moment kann die Anwendung:- Benachrichtigungen von jeder Anwendung anzeigen
- BT
Eine Verbindung zu Google Fit wurde implementiert, um Trainingsdaten zu speichern. Da ich jedoch nicht das SDK für Fit ausgewählt habe, habe ich eine Reihe von Links und Foren durchsucht, aber immer noch nicht verstanden, wie die Fit-Anzeigedaten von benutzerdefinierten Geräten erstellt werden. Es ist dann nicht klar, warum diese Funktion überhaupt da ist.Wenn jemand mit Google Fit zusammengearbeitet hat und weiß, wie er Daten von einem benutzerdefinierten Sensor zum Anzeigen von Grafiken verwenden kann, teilen Sie mir dies in Kommentaren mit oder schreiben Sie mir, Benutzer und ich sind sehr dankbar!Es war auch eine Idee, das Armband als Adnroid mit Sleep zu verbinden. Um den Schlaf zu überwachen, wurde ein Armband gekauft. Wie sich herausstellte, kann iWown jedoch nur die Dauer der Schlafphasen zurückgeben. Das heißt, die bereits berechneten Daten vom Beschleunigungsmesser.Und Sleep as Android benötigt nackte Daten vom Beschleunigungsmesser und mit einer gewünschten Frequenz von 10 Sekunden.Zusammenfassend. Ich lade Entwickler und Eigentümer ein, das Projekt mit ihrem Code, Tipps und allem zu unterstützen. Lassen Sie Pull-Requist, Ausgabe auf Github.Die Anwendung erwies sich im Ausland als sehr beliebt. Ausländer schreiben mir oft und bitten mich, etwas hinzuzufügen / zu reparieren / zu übersetzen.Übrigens hat iWown i5 mehrere Klone mit ähnlicher Firmware:Vidonn X5Harper BFB-301Excelvan i5Referenzen
Google Play - iWown für GeekRepository auf GitHubDiskussion auf w3bsit3-dns.comPS Ab der 5. Version wurde eine zusätzliche Kategorie in Androiden im Vorhang angezeigt, die nicht auf dem Sperrbildschirm angezeigt wird.Kann mir jemand sagen, wie ich meine Benachrichtigung in diese Kategorie übertragen soll? Danke!