Beli gelang Cina, kecewa dengan perangkat lunak resmi, tulis sendiri!
Cerita ini telah menunggu untuk publikasi selama lebih dari enam bulan, selama ini banyak yang telah berubah, firmware dan perangkat lunak telah diperbarui dan banyak perkembangan saya sudah menjadi usang.Kata Pengantar
Pekerjaan aktif sejumlah besar perusahaan di bidang teknologi yang dapat dikenakan dan jam tangan pintar tidak meninggalkan kedamaian bagi jiwa saya. Saya melihat potensi besar dalam perangkat yang dapat dipakai dengan layar. Tidak, saya tidak berbicara tentang menghitung langkah-langkah dan hal-hal kebugaran lainnya, mereka memang keren, tetapi sangat jauh dari dangkal “Selamat! Anda berjalan 4 km, naik 20k + langkah! ” dan grafik perkembangan dan regresi yang indah, mereka tidak menghasilkan sesuatu yang istimewa.Tetapi kenyataan bahwa saya dapat menerima notifikasi langsung ke layar di pergelangan tangan saya nyaman. Jika saya juga bisa berinteraksi dengannya atau dengan sesuatu di dekatnya dengan menekan tombol 1-2-3 - ini bahkan lebih keren.Sekali lagi, membajak hamparan aliexpress, saya menemukan gelang kebugaran iWown i5. Dia segera menarik perhatian saya dengan harga yang sangat rendah (pada waktu itu sekitar 800r dengan pengiriman gratis) dan kehadiran layar OLED. Setelah membaca deskripsi penjual dan ulasan pelanggan dengan cermat, saya memutuskan untuk memesan keajaiban ini.Spesifikasi yang diumumkan (deskripsi terjemahan dari aliexpress):- Tampilan: OLED
- Baterai: Li-Polymer
- Pengisian: pengisian USB standar
- Waktu siaga: lebih dari 72 jam
- Dimensi: 69.1 * 15.8 * 11.2mm
- Berat: 18g
- Bahan: tali ABS, gesper baja
- Tahan Air: IP55
- Suhu Operasional: -20 ° C ~ + 45 ° C
- Suhu operasi media flash: -40 ° C ~ + 45 ° C
Kemampuan:- Monitor olahraga: semua waktu mencatat langkah dan gerakan, jarak yang ditempuh, dan kalori yang terbakar, semua angka dihitung dengan mempertimbangkan berat dan tinggi badan Anda.
- Memantau kualitas tidur: Saat Anda tidur, pelacak mencatat fase tidur, menentukan tidur nyenyak dan cepat, 8 kelompok alarm diam memungkinkan Anda membangunkan Anda tanpa mengganggu anggota keluarga lainnya.
- Sinkronisasi nirkabel Bluetooth 4.0 daya rendah
- Mendukung sinkronisasi PC melalui USB
- Perlindungan IP55: melindungi perangkat dari hujan lebat, tetapi tidak lebih
dan keuntungan "terlalu jauh" dalam gaya pemasaran Cina.Saya sangat tertarik pada kesempatan untuk melacak mimpi dan bangun pada fase yang tepat. Banyak teman saya membeli pelacak kebugaran murah justru karena fungsi ini dan senang dengan mi band dan sejenisnya. Saya selalu kekurangan layar di dalamnya, tapi ini all-in-one.Dalam pekerjaan saya, saya sering harus mengembangkan aplikasi sederhana untuk Android, saya memutuskan bahwa jika saya tidak memiliki fungsionalitas aplikasi asli saya, saya akan menulis sendiri.Paket itu tiba dengan cepat dan saya segera bergegas mempelajari gelang yang bagus. Setelah satu jam bermain dengan aplikasi Zeroner, yang menurut instruksi harus diinstal pada perangkat Android saya, saya menyadari bahwa fungsinya agak buruk dan sedih. Zeroner, seperti semua produsen lain, berfokus pada penghitungan langkah dan kalori, menampilkan grafik yang indah, memiliki fungsi pencarian telepon (saya akan membicarakan ini nanti), dapat memberi tahu Anda tentang panggilan masuk, kedatangan pesan di facebook dan whatsapp, dan mengirim pemberitahuan dari SATU aplikasi apa pun yang dipilih , yang akan dianggap sebagai aplikasi untuk SMS.Getaran gelang itu sangat kontroversial, mereka menulis di forum bahwa itu agak lemah, ada yang mengatakan itu normal. Bagi saya, itu bisa lebih kuat. Gelang memiliki reaksi terhadap gerakan "Lihat arloji", jika Anda melihat gelang seperti arloji, mengangkat tangan dan menekuk siku, layar akan menyala secara otomatis dan menunjukkan waktu atau pemberitahuan yang terlewat.
Secara umum, tanpa ragu-ragu, saya memutuskan untuk menulis aplikasi saya, dengan notifikasi, getaran, dan sinkronisasi. Saya akan maju, butuh 4 hari libur dan beberapa malam yang panjang ...Untuk bisnis
Mengingat bahwa dengan Bluetooth saya bukan gigi biru, saya memutuskan untuk mencoba mencegat data yang dipertukarkan antara telepon dan gelang dengan orang bodoh. Untuk melakukan ini, saya naik ke tab untuk pengembang, dan menyalakan kotak centang "Aktifkan HCI Bluetooth Broadcast Log" . Setelah mengaktifkan opsi ini, seluruh dump komunikasi android dengan perangkat Bluetooth apa pun ditambahkan ke file /sdcard/Android/data/btsnoop_hci.log (jalur dapat berubah untuk perangkat yang berbeda, nama file sepertinya selalu sama).Setelah mengunduh WireShark, saya mulai mempelajari log komunikasi dengan gelang dan melihat sesuatu yang serupa dengan ini:
Setelah menghabiskan hampir dua jam, mempelajari log, membuat kecanduan, protokol google di Internet, saya menyadari bahwa jalur seperti itu bukan untuk saya.Karena ponsel saya menafsirkan gelang itu sebagai perangkat BLE biasa dan menunjukkannya di bagian perangkat yang terhubung, saya memutuskan untuk menggunakan contoh bekerja dengan BLE dari Android SDK.Setelah mengkloning repositori https://github.com/googlesamples/android-BluetoothLeGatt , atur Android Studio di pusar dengan sumber, buat dan luncurkan aplikasi. ( Tautan ke deskripsi Android SDK dengan Bluetooth LE )Ternyata seperti pada gambar dari github:
Setelah menjalankan pemindaian, aplikasi tidak melihat perangkat. Ternyata aplikasi asli dengan menghubungkan ke gelang tidak memungkinkan BLE untuk menemukan perangkat. Semuanya diputuskan oleh penghapusan sederhana Zeroner, Anda bisa mematikannya, tetapi lebih dapat diandalkan untuk menghancurkannya sepenuhnya.Maka, Bluetooth LE adalah teknologi yang dibangun di atas perangkat dengan konsumsi daya yang rendah, digunakan dalam sensor, tag baru, dan banyak perangkat lainnya. Dasar dari teknologi ini adalah Generic Attribute Profile (GATT) , ini adalah profil Bluetooth yang memungkinkan Anda untuk bertukar potongan kecil data, "atribut" . Saya tidak akan menulis tentang bagaimana semuanya bekerja untuk waktu yang lama. Di Internet dan di Internet ada banyak informasi yang saya juga harus mencari solusi.Saya berharap bahwa semua data yang saya butuhkan disimpan dalam karakteristik dan deskripsi gelang, dan saya dapat menerima dan mencatat data tanpa masalah. Saya salah ... Aplikasites BLE hanya menunjukkan 4 layanan kepada saya:0000180f-0000-1000-8000-00805f9b34fb00001800-0000-1000-8000-00805f9b34fb0000ff20-0000-1000-8000-00805f9b34fb00001801-0000-1000-8000-00805f9b34fbmereka memiliki beberapa karakteristik yang sangat sedikit, karakteristik yang berbunyi batal atau nol, dan tulisan tidak berguna. Tetapi saya merasa terdorong untuk dapat terhubung dan mendapatkan setidaknya beberapa data.Lebih lanjut, saya memutuskan bahwa tidak mungkin untuk bertindak secara membabi buta dan memutuskan untuk membedah aplikasi Zeroner. Setelah mengumpulkan beberapa dekompiler APK online di Internet, saya memberi mereka makan zeroner.apk dan mendapatkan 2 arsip zip pada hasilnya.Yang pertama adalah versi JADX, dan yang kedua berisi hasil apktool.Mengaduk-aduk kode sumber saya ngeri dengan kode Cina(walaupun dalam pekerjaan saya, saya sering menjumpai dia dalam bentuk backend untuk situs dan layanan, tetapi dia tidak pernah berhenti membuat saya takjub dengan tortuosity dan kecerdikannya, tetapi bagaimanapun, itu sangat sulit untuk dibaca)Setelah banyak penelitian, saya akhirnya menemukan file WristBandDevice.java , yang berada di jalur com.kunekt / bluetooth.Di kelas ini, semua pekerjaan dengan perangkat itu hanya bersembunyi, tapi sekali lagi, penyergapan menungguku.Ternyata kemudian, dalam firmware gelang sebelumnya, lebih banyak layanan digunakan dalam karakteristik (seperti yang saya harapkan sebelumnya), tetapi kemudian, pengembang hanya menyisakan 2, satu untuk membaca, yang kedua untuk menulis. Semua perintah dikirimkan dalam satu paket.Itu tidak begitu mudah untuk memahami seperti apa bentuk paket itu, saya memutuskan untuk dengan jelas menentukan apa yang saya inginkan dari gelang di tempat pertama, sehingga saya bisa mulai melacak panggilan fungsi. Dan saya ingin menampilkan pesan khusus pada gelang.Tanpa ragu-ragu, saya naik ke com.kunekt / receiver / CallReceiver.java , karena panggilan masuk ditampilkan dengan sangat stabil dan bahkan dengan karakter Rusia, saya memutuskan bahwa ini adalah awal yang baik, mengingat bahwa saya telah menjumpai acara panggilan masuk di Android, gagasan untuk cara kerjanya mungkin sudah.Membuka file, saya melihat ini:Sepotong besar kode Cinapublic 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:
}
}
Di sini kita melihat dengan jelas bahwa ada 2 opsi untuk API dan nama-nama yang mereka miliki adalah newAPI yang sangat logis, dan yang kedua, oldAPI. Dalam semua kondisi yang berlimpah ini, saya hanya tertarik pada satu, mengulangi baris:WristBandDevice.getInstance (konteks) .writeWristBandPhoneAlertNew (konteks, contact.getDisplayName .....)Ini yang saya cari. Ke depan, saya akan mengatakan bahwa iWown juga memiliki model i5 + dan i6, mereka memiliki layar yang lebih besar dan karenanya lebih banyak karakter ditempatkan, untuk ini semua pemeriksaan ini diperlukan. tidak jelas mengapa mereka tidak menulis kelas atau sesuatu seperti itu, mungkin ini adalah lelucon dekompiler, tetapi kode ini diulangi di banyak tempat.Beralih ke definisi fungsi ini, saya melihat ini: public void writeWristBandPhoneAlertNew(Context context, String displayName) {
writeAlertNew(context, displayName, 1);
}
public void writeWristBandSmsAlertNew(Context context, String displayName) {
writeAlertNew(context, displayName, 2);
}
Hebat, ia menggunakan fungsi yang sama untuk mengirim teks, hanya dengan parameter yang berbeda. Semua fungsi dengan kata Baru hanyalah pilihan kami, karena seperti yang ditunjukkan di atas, saya memiliki API baru.Dengan senang hati pergi ke definisi fungsi writeAlertNew , saya melihat yang berikut: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));
}
}
Sudah jelas bahwa beberapa fungsi yang digunakan di sini memisahkan saya dari keuntungan.writeWristBandDataByte - membentuk paket dengan pesan untuk gelang, menarik bahwa ada fungsi khusus form_Header (3, 1) , yang membentuk header paket, dimana gelang memahami apa yang mereka inginkan darinya. 3 adalah jumlah kelompok tim, dan 1 adalah tim itu sendiripublic static byte form_Header(int grp, int cmd) {
return (byte) (((((byte) grp) & 15) << 4) | (((byte) cmd) & 15));
}
Fungsinya sederhana, disalin ke proyek saya tanpa perubahan. Berikutnya adalahNewAgreementBackgroundThreadManager.getInstance (). AddTask (WriteOneDataTask baru (konteks, writeData));Ternyata, tidak ada yang aneh, aplikasi menciptakan aliran di mana antrian paket untuk pengiriman terus-menerus diperiksa, jika suatu paket muncul dalam antrian, aliran itu menulis ke karakteristik perangkat yang diberikan, jika ada lebih dari satu paket, ia mengirimkannya dengan penundaan 240 milidetik.Berikutnya datang yang paling tidak bisa dipahami:PebbleBitmap.fromString (konteks, String.valueOf (e), 8, 1) .data)Mengapa kelas disebut seperti itu tidak jelas, karena perangkat ini tidak ada hubungannya dengan Pebble. Membuka sumber kelas, saya melihat yang berikut:Sumber kelas PebbleBitmappublic 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));
}
}
Setelah refleksi yang panjang, saya sampai pada kesimpulan bahwa fromString membuat gambar dengan huruf menggunakan font tertentu (yang tertanam dalam aplikasi), dan kemudian mengubah piksel menjadi 0 atau 1 tergantung pada isi, sehingga huruf O akan terlihat seperti ini:0001110001100011011000110110001100011100Tanpa benar-benar masuk ke detail, saya menyalin semuanya ke dalam proyek saya menggunakan contoh BLE GATT Google.Dan ... Oh, keajaiban !!! Gelang itu bergetar! Namun pesan itu tidak muncul, baris kosong dan ikon panggilan masuk.Ternyata sekelompok cek ukuran tidak biasa, gelang itu dengan bodohnya mengabaikan pesan yang terlalu panjang dan pesan yang panjangnya 11 karakter, meskipun 12 menampilkan secara normal. Beberapa jam menari di sekitar fungsi-fungsi ini akhirnya membuahkan hasil, saya belajar untuk menampilkan teks Rusia dan Inggris, dan pada saat yang sama saya belajar bahwa ada beberapa mode operasi dalam grup pesan:- Panggilan masuk. Handset ditampilkan, nama penelepon dan gelang bergetar
- Pesan Ikon teks dan amplop ditampilkan. Saat bergetar 2 kali
- Berawan. Sama seperti 2, tetapi bukannya amplop, ikon cloud
- Kesalahannya. Sama seperti 2, itu hanya ikon dengan tanda seru.
Setelah mengajarkan aplikasi saya untuk mengirimi saya pemberitahuan dari aplikasi yang berbeda, whatsapp, vk, viber, telegram dan lain-lain, saya memutuskan bahwa sudah waktunya untuk mengajar gelang menanggapi panggilan masuk dan, akhirnya, menggunakan satu tombol untuk mengatur ulang yang masuk.Saya tidak akan menjelaskan proses ini, posnya ternyata membengkak, saya hanya akan mengatakan bahwa tidak sulit untuk menanggapi pesan yang masuk, tetapi menggunakan tombol tidak.Semua pesan masuk dari gelangnya, Zeroner dicegat di kelas khusus. paket yang masuk memiliki judul grup perintah dan nomor perintah, setelah debug panjang dan tes saya mencari-cari kelompok yang digunakan, dan kemudian menemukan deskripsi dalam kode Zeroner.Kelompok dan tim gelang// 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
Berkat ini, saya bisa mewujudkan pekerjaan penuh dengan gelang. Saya dapat menerima data tentang langkah-langkah, tentang tidur. Saya dapat mengatur pengaturan, mengatur alarm. Saya berhasil mendapatkan sebutan byte dari paket itu sendiri dari kelas-kelas yang menyimpan data dalam database, saya mengimplementasikan semuanya di rumah.Pada akhirnya
Setelah berpikir sebentar, saya memutuskan bahwa semua ini dapat bermanfaat tidak hanya bagi saya dan menulis aplikasi baru yang berisi semua data dan fungsi yang diperlukan untuk bekerja dengan gelang, serta mengimplementasikan antarmuka sederhana untuk mengirim pemberitahuan dari aplikasi apa pun ke gelang.WiliX iWown untuk GeekSejak itu, banyak waktu telah berlalu, dan banyak setelah memperbarui ke Android 6, aplikasi berhenti bekerja. Ini juga tidak bekerja secara stabil dengan firmware gelang versi 2. Tetapi saya berharap menemukan waktu untuk revisi.Kode sumber diposting di GitHub . Anda dapat melakukan fork dan bersenang-senang sesuka Anda. Semua permintaan tarik setelah peninjauan akan diterima, dan setelah pengujian akan segera diunggah ke Google Play.Saat ini, aplikasi dapat:- Tampilkan pemberitahuan dari aplikasi apa pun
- BT
Koneksi ke Google Fit diimplementasikan untuk menyimpan data pelatihan, tetapi, karena saya tidak memilih SDK untuk Fit, saya mencari-cari melalui banyak tautan dan forum, tetapi masih tidak mengerti bagaimana membuat data tampilan fit dari perangkat khusus. Tidak jelas mengapa fungsi ini ada di sana.Jika seseorang bekerja dengan Google Fit, dan tahu bagaimana membuatnya menggunakan data dari sensor khusus untuk menampilkan grafik, beri tahu saya dalam komentar atau tulis saya, pengguna dan saya akan sangat berterima kasih!Itu juga merupakan ide untuk menghubungkan gelang ke Sleep sebagai Adnroid. Sebenarnya, untuk memantau tidur, gelang dibeli. Tapi, ternyata, iWown hanya bisa mengembalikan durasi fase tidur. Artinya, sudah dihitung data dari accelerometer.Dan Sleep as Android membutuhkan data telanjang dari accelerometer, dan dengan frekuensi yang diinginkan 10 detik.Secara umum, hasilnya. Saya mengundang pengembang dan pemilik untuk mendukung proyek dengan kode mereka, tips dan apa pun. Tinggalkan pull-requist, terbitkan di Github.Aplikasi ini ternyata sangat populer di luar negeri, orang asing sering menulis kepada saya, meminta saya untuk menambah / memperbaiki / menerjemahkan sesuatu.Omong-omong, iWown i5 memiliki beberapa klon, dengan firmware serupa:Vidonn X5Harper BFB-301Excelvan i5Referensi
Google Play - iWown untuk GeekRepository on GitHubDiskusi di w3bsit3-dns.comPS Dimulai dengan versi ke-5, kategori tambahan muncul di android di tirai, yang tidak muncul di layar kunci.Dapatkah seseorang memberi tahu saya cara mentransfer notifikasi ke kategori ini? Terima kasih