Hello, fellow XDA-ers.
Today I want to tell you about new RemoteController class introduced in Android 4.4.
What does this class do?
The RemoteController class is used to control media playback, display and update media metadata and playback status, published by applications using the RemoteControlClient class.
Click to expand...
Click to collapse
However, the documentation is rather empty. Sure, there are methods etc., but it's not really helpful if you have zero knowledge about this class and you want to implement it right away.
So, here I am to help you.
Sit down and get your IDE and a cup of coffee/tea ready.
WARNING: This guide is oriented at experienced Android developers. So, I'll cover the main points, but don't expect me to go into details of something which is not directly related to RemoteController.
1. Creating a service to control media playback.
To avoid illegal access to metadata and media playback, user have to activate a specific NotificationListenerService in Security settings.
As a developer, you have to implement one.
Requirements for this service:
1. Has to extend NotificationListenerService[/B
2. Has to implement RemoteController.OnClientUpdateListener.
You can look at my implementation on GitHub.
Let's now talk about details.
It's better to leave onNotificationPosted and onNotificationRemoved empty if you don't plan to actually process notifications in your app; otherwise you know what to do.
Now we need to register this service in AndroidManifest.xml.
Add the following to the manifest(replacing <service-package> with actual package where your service lies, and <service-name> with your Service class name):
Code:
<service
android:name="<service-package>.<service-name>"
android:label="@string/service_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
Please note: do not override onBind() method, as it will break the functionality of the service.
"service_name" is a name for your service which will be shown in Security->Notification access.
2. Handling client update events.
Now on to implementation of RemoteController.OnClientUpdateListener. .
You may process everything inside this service, or (which I consider a better alternative, as it gives more flexibility, and you can re-use your service for different apps) re-call methods of external callback to process the client update events.
Here, however, we will only talk about the methods and which parameters are passed to them.
The official description is good enough and I recommend reading it before processing further.
Code:
[B]onClientChange(boolean clearing)[/B]
Pretty self-explanatory. "true" will be passed if metadata has to be cleared as there is no valid RemoteControlClient, "false" otherwise.
Code:
[B]onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor)[/B]
[I]metadataEditor[/I] is a container which has all the available metadata.
How to access it? Very simple.
For text data, you use RemoteController.MetadataEditor#getString(int key, String defaultValue);
"R.string.unknown" is a reference to String resource with name "unknown", which will be used to replace missing metadata.
To get artist name as a String, use:
[B]metadataEditor.getString(MediaMetadataRetriever.METADATA_KEY_TITLE, getString(R.string.unknown))[/B]
To get title of the song as a String, use:
[B]metadataEditor.getString(MediaMetadataRetriever.METADATA_KEY_ALBUM, getString(R.string.unknown))[/B]
To get the duration of the song as a long, use:
[B]metadataEditor.getLong(MediaMetadataRetriever.METADATA_KEY_DURATION, 1)[/B]
1 is the default duration of the song to be used in case the duration is unknown.
To get the artwork as a Bitmap, use:
[B]metadataEditor.getBitmap(RemoteController.MetadataEditor.BITMAP_KEY_ARTWORK, null)[/B]
"null" is the default value for the artwork. You may use some placeholder image, however.
And here is one pitfall.
Naturally, you would expect artist name to be saved with the key MediaMetadataRetriever.METADATA_KEY_ARTIST.
However, some players, like PowerAmp, save it with key MediaMetadataRetriever.METADATA_KEY_ALBUMARTIS.
So, to avoid unnecessary checks, you may use the following(returns String):
[B]mArtistText.setText(editor.getString(MediaMetadataRetriever.METADATA_KEY_ARTIST, editor.getString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, getString(R.string.unknown))));[/B]
What does it do - it tries to get the artist name by the key METADATA_KEY_ARTIST, and if there is no such String with this key, it will fall back to default value, which, in turn, will try to get the artist name by the key METADATA_KEY_ALBUMARTIST, and if it fails again, it falls back to "unknown" String resource.
So, you may fetch the metadata using these methods and then process it as you like.
Code:
[B]onClientPlaybackStateUpdate(int state, long stateChangeTimeMs, long currentPosMs, float speed)[/B]
Called when the state of the player has changed.
Right now this method is not called, probably due to bug.
[I]state[/I] - playstate of player. Read the [URL="http://developer.android.com/reference/android/media/RemoteControlClient.html"]RemoteControllerClient class description[/URL] to get the list of available playstates.
For example, RemoteControlClient.PLAYSTATE_PLAYING means that music is currently playing.
[I]stateChangeTimeMs[/I] - the system time at which the change happened.
[I]currentPosMs[/I] - current playback position in milliseconds.
[I]speed[/I] - a speed at which playback occurs. 1.0f is normal playback, 2.0f is 2x-speeded playback, 0.5f is 0.5x-speeded playback etc.
Code:
[B]onClientPlaybackStateUpdate (int state)
[I]state[/I] - playstate of player. Read the [URL="http://developer.android.com/reference/android/media/RemoteControlClient.html"]RemoteControllerClient class description[/URL] to get the list of available playstates.[/B]
Code:
[B]onClientTransportControlUpdate (int transportControlFlags)[/B]
[I]transportControlFlags[/I] - player capabilities in form of bitmask.
This is one interesting method. It reports the capabilities of current player in form of bitmask.
Let's say, for example, you want to know if current player supports "fast forward" media key.
Here is how to do it:
[B]if(transportControlFlags & RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD != 0) doSomethingIfSupport(); else doSomethingIfDoesNotSupport(); [/B]
All of the flags are listed in [URL="http://developer.android.com/reference/android/media/RemoteControlClient.html"]RemoteControlClient class description.[/URL]
3. Creating RemoteController object.
The preparations are finished.
Now we need to construct RemoteController object.
The constructor of RemoteController takes two arguments. First is Context, and second is RemoteController.OnClientUpdateListener.
You should know how to fetch Context already.
Now let's talk about the second parameter. You have to pass YOUR SERVICE implementing RemoteController.OnClientUpdateListener and extending NotificationListenerService. This is a must, otherwise you won't be able to register your RemoteController to the system.
So, in your service, use something like this:
Code:
public class RemoteControlService extends NotificationListenerService implements RemoteController.OnClientUpdateListener {
private RemoteController mRemoteController;
private Context mContext;
...
@Override
public void onCreate() {
mContext = getApplicationContext();
mRemoteController = new RemoteController(mContext, this);
}
...
Now to activate our RemoteController we have to register it using AudioManager.
Please note that AudioManager#registerRemoteController returns "true" in case the registration was successful, and "false" otherwise.
When can it return "false"? I know only two cases:
1. You have not activated your NotificationListenerService in Security -> Notification Access.
2. Your RemoteController.OnClientUpdateListener implementation is not a class extending NotificationListenerService.
Code:
if(!((AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE)).registerRemoteController(mRemoteController)) {
//handle registration failure
} else {
mRemoteController.setArtworkConfiguration(BITMAP_WIDTH, BITMAP_HEIGHT);
setSynchronizationMode(mRemoteController, RemoteController.POSITION_SYNCHRONIZATION_CHECK);
}
Of course, we will have to deactivate RemoteController at some point with this code.
Code:
((AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE)).unregisterRemoteController(mRemoteController);
By default you will NOT receive artwork updates.
To receive artwork, call setArtworkConfiguration (int, int). First argument is width of the artwork, and second is the height of the artwork.
Please note that this method can fail, so check if it returns true or false.
To stop receiving artwork, call clearArtworkConfiguration().
4. Controlling media playback.
We can send media key events to RemoteControlClient.
Also, we can change position of playback for players which support it(currently only Google Play Music supports it).
You can send key events using this helper method:
Code:
private boolean sendKeyEvent(int keyCode) {
//send "down" and "up" keyevents.
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
boolean first = mRemoteController.sendMediaKeyEvent(keyEvent);
keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
boolean second = mRemoteController.sendMediaKeyEvent(keyEvent);
return first && second; //if both clicks were delivered successfully
}
"keyCode" is the code of the pressed media button. For example, sending KeyEvent.KEYCODE_MEDIA_NEXT will cause the player to change track to next. Note that we send both "down" event and "up" method - without that it will get stuck after first command.
To seek to some position in current song, use RemoteController#seekTo(long). The parameter is the position in the song in milliseconds.
Please note that it will have no effect if the player does not support remote position control.
5. Getting current position.
RIght now the onClientPlaybackStateUpdate(int state, long stateChangeTimeMs, long currentPosMs, float speed) method is broken, as it's not called when the position is updated. So, you have to manually fetch current position. To do this, use the RemoteController#getEstimatedMediaPosition() method - it returns current position in milliseconds(or other values, like 0, if player does not support position update).
To update it periodically, you may use Handler and Runnable. Look at the implementation on GitHub as the reference.
Hi. Good tutorial! How can i use RemoteController without MediaPlayer class? I'm using custom engine for playback.
XDA is usually pretty shi tty so I never come on here, and hence I had to reset my password to say thank you! This was really useful.
Including this code in NotificationListener Service on 4.3
Thank you for taking the time to describe the implementation in such detail. My only problem now is including implements RemoteController.OnClientUpdateListener in my NotificationListener class for an app that supports 4.0+. As soon as this service is started up by a 4.3 device the app crashes (reason is obvious, 4.3 doesn't support remote controller). The only solution I've found is to create 2 seperate notification listener classes, one for 4.3 and one for 4.4 (which has the RemoteController code in it). This also creates 2 entries in Notification Access list in the security settings.
Any ideas on how to make a hybrid service for 4.3/4.4 that implements the necessary RemoteController code?
corrytrevor said:
Thank you for taking the time to describe the implementation in such detail. My only problem now is including implements RemoteController.OnClientUpdateListener in my NotificationListener class for an app that supports 4.0+. As soon as this service is started up by a 4.3 device the app crashes (reason is obvious, 4.3 doesn't support remote controller). The only solution I've found is to create 2 seperate notification listener classes, one for 4.3 and one for 4.4 (which has the RemoteController code in it). This also creates 2 entries in Notification Access list in the security settings.
Any ideas on how to make a hybrid service for 4.3/4.4 that implements the necessary RemoteController code?
Click to expand...
Click to collapse
I have the exact same problem. Been searching for hours now, but I just couldn't come up with a solution for that issue.
Does anybody know how to solve this? Any kind of hint would be highly appreciated!
corrytrevor said:
Thank you for taking the time to describe the implementation in such detail. My only problem now is including implements RemoteController.OnClientUpdateListener in my NotificationListener class for an app that supports 4.0+. As soon as this service is started up by a 4.3 device the app crashes (reason is obvious, 4.3 doesn't support remote controller). The only solution I've found is to create 2 seperate notification listener classes, one for 4.3 and one for 4.4 (which has the RemoteController code in it). This also creates 2 entries in Notification Access list in the security settings.
Any ideas on how to make a hybrid service for 4.3/4.4 that implements the necessary RemoteController code?
Click to expand...
Click to collapse
I found a solution to this problem (or rather WisdomWolf did). http://stackoverflow.com/questions/...motecontroller-onclientupdatelistener-crashes
Problem solved
Finding music to play
Hi Thanks for the fantastic tutorial! Is there away to find a receiver if there is no music playing. I have noticed the line
Code:
I/RemoteController﹕ No-op when sending key click, no receiver right now
is logged. Thanks
Thanks for the great tutorial, very helpful for my current project. RemoteController is also used in KitKat built-in Keyguard KeyguardTransportControlView to replace RDC in older version.
ATI-ERP expeditious Business Solutions
Great article on building Remotecontroller in an Android application.
For More Android Apps visit ati-erp.com
ATI-ERP
i can't bind the service, i debug and seemd android start the service well , however trying bind the service onStart seems does not work in 4.4.4 someone has this issue? i tried reboot and other options
Nevermind i forgot to put the intent filter on manifest (shame on me)
Sorry to drag up an old thread. Does anyone know how to get the package of the client that is currently connected to / updating the RemoteController? I can't find it anywhere...
So the end goal in this project is to view an RTMP stream and interact with the server at the same time.
This is a little hard, because obviously VLC or Mx Player or whatever I'm viewing the RTMP stream with doesn't know how to communicate with the custom server. So I'm trying to make an overlay that will sit on top of the player which has buttons, the buttons can then communicate with the server which will alter the stream and you'll see the result streamed to the player. This is sort of like an interactive HUD if you will.
Problem is that it's difficult to make an overlay which will take actions if they're clicked, but can also pass those actions to the background app (in this case the player) if it opts not to process them. Right now my app creates a service and the service catches the input and displays whatever. This WORKS, but the problem is no matter what I return from "onTouchEvent(MotionEvent)" in the view of the service (true or false) the home screen is frozen. It catches the press but it won't pass it on, even if the function returns "false" - to say it's not handled.
I'm not sure if I'm not passing the touch event on correctly, or is this not even possible? I read somewhere that it's not possible for app A to provide input to app B, but I'm not sure if that is correct (frankly I don't believe it). Basically I want to handle some presses in the overlay and allow some others to go to the active app beneath it.
Does anybody have any input for making this work as expected? I'm creating a view to pass to the window manager with the following flags:
Code:
LayoutParams params = new LayoutParams(LayoutParams.TYPE_SYSTEM_ALERT,
LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
I've tried playing with the flags but to no avail, I cannot get the touches to go through, even if all the onTouchEvent(MotionEvent) function does is return false.
Anybody have any ideas?
I'd be open to alternative implementation ideas too, the point is I need to basically have two communication channels open, one is a player (ie. VLC) for viewing the RTMP stream, which likely would not change, the other would be the command stream, which will control said server, which I am open to change. I considered trying to use the accelerometer in the service instead of an overlay, but I think that would create a bad proof of concept UI (because there's some latency in the video stream), any alternative ways to communicate with the server would be up for discussion! Maybe I can plug an IO device into the USB port or something, like a keyboard? Extra buttons could be of use. It's only a POC, so some clunkyness IS okay.
EDIT:
As you can see above, I used an alert type instead of an overlay type, I guess this is because overlays won't accept focus after a certain Android version number. I'm using 4.0.4 ICS.
Hello all, this is my first post here!
In this article I will explain my method of hacking the Square G-Shocks that make use of a Bluetooth module (I have a GW-B5600, but it should theoretically work on the GMW-B5000 too) with the goal to create our own Android app that will allow to get info and set the watch via BLE (Bluetooth Low Energy) commands/requests.
The tools I am using are: (sorry no link I am too new)
nRF Connect for Android by Nordic Semiconductor from the Play Store
Wireshark desktop (Windows/Mac) from the official website
The official "G-Shock Connected" Android app from the Play Store
And adb that can be found in the Android platform tools (by default in "C:\Users\usrname\AppData\Local\Android\Sdk\platform-tools")
Your phone does not need to be rooted but needs the Developer options enabled.
1 Discover the services offered by the G-Shock
I am using nRF Connect installed from the Play Store to scan for BT devices.
Long-press the (C) (bottom left) button on the B5600 to enable BT on the watch.
Hit Scan in nRF and search for "CASIO GW-B5600" and tap it to show the following details:
Code:
Device BT Name: CASIO GW-B5600
Device BT Address: [B]EB:1C:FF:90:C2:34[/B]
Offered services: 0x1801 Generic Attribute
0x1800 Generic Access
0x2A00 (R) Device Name
0x2A01 (R) Appearance
0x1804 Tx Power
0x2A07 (R) Tx Power Level
0x26EB00 0D Unknown Service
(UUID 0x2902 for all)
[B]0x26EB002C (W*) Custom Service #2C[/B]
[B]0x26EB002D (NW) Custom Service #2D[/B]
0x26EB0023 (NW) Custom Service #23
0x26EB0024 (NW*)Custom Service #24
(R) is read only (W) write (W*) write no response (N) notify.
The important information has been set in bold: the BT address that we will use to analyze the packets, and the 2 services that I called #2C and #2D that are used by the official G-Shock app to get and set info from/to the watch.
2 Enable Bluetooth traces on the phone
After that, open the phone Developer options > Enable Bluetooth HCI snoop log.
Or use the USB debugging mode, plug the phone to the computer and type the following command in a prompt:
Code:
adb shell settings put secure bluetooth_hci_log 1
To know where the BT traces will be stored, type the following command:
Code:
adb shell cat /etc/bluetooth/bt_stack.conf
and look at the line starting with 'BtSnoopFileName=' to locate the BT log files.
3 Capture BT activity and save the logs on computer
Install and run the "G-Shock Connected" app on your phone from the Play Store.
Do manipulations between the watch and the app, take note of the time you make them.
Then plug the phone and type:
Code:
adb pull /data/log/bt/btsnoop_hci*.log
Note: the place and name of the logs are for my Huawei Mate 10. You will need to adapt the path with the one you got at step 2.
4 Analyze the BT traces in Wireshark
Open Wireshark and drag and drop one of the "btsnoop_hci*.log" files pulled to the computer onto the program.
Add a filter on the G-Shock BT address we got from nRF Connect at step 1:
Code:
bluetooth.addr==EB:1C:FF:90:C2:34
And hit enter to see the BLE activity on the watch.
Now the fun (or the boring part, it depends ) begins... Understanding the BT requests/answers (get info) and BT commands (set info)!
In Wireshark, the important information for each BT frame are contained in the fields
Bluetooth Attribute Protocol > Handle > UUID
and in Bluetooth Attribute Protocol > Value
The very first -easiest- command I was able to identify is the one to Get and Set the Home City and the 5 World Time (WT) Cities.
When you analyse the BT packets, you can see the name of the cities written in all letters in the Value field:
Code:
0000 1f 01 48 4f ..HO
0010 4e 47 20 4b 4f 4e 47 00 00 00 00 00 00 00 00 00 NG KONG.........
We can observe that to GET the Home City, we send a Write command with the value 1F00 to the service 0x26EB002C (aka Custom Service #2C). In return, we will receive a notification through the service 0x26EB002D (aka Custom Service #2D) containing an echo of the Command ID (1F00) followed by the name of the Home City in upper-case (e.g. "PARIS").
To SET the Home City is just as easy: we send a Write request to the service 0x26EB002D (Custom Service #2D) with the value 1F00 followed by the name of the new Home City on 18 Bytes (e.g. "PARIS"), tailed with 0x00.
GETting and SETting the 5 World Time Cities is very similar: you only need to use the Command IDs 1F01 to 1F05...
The next command I reverse engineered is the one to set the date and time.
I started to search for the hexadecimal value "07 E4" in the traces (2020 in decimal = the current year). The search returned zero result... If finding a WORD (value encoded on 2 bytes) in big endian* fails, you gotta try searching it in little endian* so I did another search for "E4 07" this time, and bingo! It appears in a SET command starting with the ID 0x09.
* search Wikipedia for "Endianness"
The full structure of the binary value is:
Code:
([B]09[/B]) YYYY MM DD HH mm ss ?? ?? 01 ?? ?? is the milliseconds in big endian(?)
[B]Mon.13-JAN (15:54:10) traces[/B]
([B]09[/B]) E4 07 01 0D 0F 36 0B 01 F2 01 --> 2020-01-13 15:54:11 (,498?)
[B]Wed.15-JAN (15:29:27) traces[/B]
([B]09[/B]) E4 07 01 0F 0F 1D 1E 03 44 01 --> 2020-01-15 15:29:30 (,836?)
You can notice there's a difference in the trace timestamp and the time sent, respectively 1 second and 3 seconds. That is quite normal: I disabled the time synchronization in the watch settings, so the watch time can deviate from the atomic time by a few seconds (the user guide states a tolerance of +/- 15s per month average).
Hey, did you ever manage to get any further with this @mougino ? I've also got one of these watches, and have been playing around with the BLE connection to it. I've managed to successfully set the alarm times and on/off state – but so far haven't had any luck with setting the actual time. I tried writing with the op-code you suggested of 0x09, but it doesn't seem to actually do anything for me.
Up its interesting.
Hope somebody can help me. I'm having trouble getting/setting time on my Casio GW-B5600BC-2BJF. I can get and Set most other things like alarms, home city, etc using the #2D command (Characteristic: 26eb002d-b012-49a8-b1f8-394fb2032b0f), but when I try to set the time, it has no effect. The command does not complain, but does not change the time. Should I be using a different characteristic? Here are supported BLE services on my watch:
[CD:85:24:01:62:17][LE]> connect
Attempting to connect to CD:85:24:01:62:17
Connection successful
[CD:85:24:01:62:17][LE]> characteristics
handle: 0x0003, char properties: 0x02, char value handle: 0x0004, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0005, char properties: 0x02, char value handle: 0x0006, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0008, char properties: 0x02, char value handle: 0x0009, uuid: 00002a07-0000-1000-8000-00805f9b34fb
handle: 0x000b, char properties: 0x04, char value handle: 0x000c, uuid: 26eb002c-b012-49a8-b1f8-394fb2032b0f
handle: 0x000d, char properties: 0x18, char value handle: 0x000e, uuid: 26eb002d-b012-49a8-b1f8-394fb2032b0f
handle: 0x0010, char properties: 0x18, char value handle: 0x0011, uuid: 26eb0023-b012-49a8-b1f8-394fb2032b0f
handle: 0x0013, char properties: 0x14, char value handle: 0x0014, uuid: 26eb0024-b012-49a8-b1f8-394fb2032b0f
[CD:85:24:01:62:17][LE]>
Here is the command I'm sending:
Wrote to characteristic 26eb002d-b012-49a8-b1f8-394fb2032b0f | value: 0x09 E6 07 03 19 0B 29 07 05 4F 01
Thanks in advance.
seanlano said:
Hey, did you ever manage to get any further with this @mougino ? I've also got one of these watches, and have been playing around with the BLE connection to it. I've managed to successfully set the alarm times and on/off state – but so far haven't had any luck with setting the actual time. I tried writing with the op-code you suggested of 0x09, but it doesn't seem to actually do anything for me.
Click to expand...
Click to collapse
Same here. Did you resolve this? See my message above. Thanks.
izivkov said:
Same here. Did you resolve this? See my message above. Thanks.
Click to expand...
Click to collapse
Nah I kind of dropped it, and haven't picked it up again for quite a while. I'd love to get it working though!
seanlano said:
Nah I kind of dropped it, and haven't picked it up again for quite a while. I'd love to get it working though!
Click to expand...
Click to collapse
OK, I will let you know if I figure it out.
Just curious, are you wring an Android app for the watch?
izivkov said:
OK, I will let you know if I figure it out.
Just curious, are you wring an Android app for the watch?
Click to expand...
Click to collapse
I was planning on having something running on a Raspberry Pi Zero W – I can program, but I've never made an Android app. My plan was to do something in Python, ideally having the Pi Zero running somewhere in my bedroom so that the Casio watch can do the time synchronisation at night. If I can get that working I'd also thought about setting some alarms and reminders for the day ahead, like maybe connect it to a calendar and put any important events into the reminders function of the watch, things that the existing Casio app can't do. An Android app would be a better way of doing this, but I figured I'd get it working in Python first since it's faster for me.
Ok, thanks for the info.
I more or less figured out how to set the time. It involves setting the DST for all world locations first. I guess makes sense, since the casio will update the time for all locations. I still don't understand some things so I will need to figure it out first, and I can share if you are interested.
I am working on an open source Android app to integrate the Casio watch with Google services on android, such as calendar and Alarm ckock. It will not replace the official app. I have been working on this app for about a month now, and got the alarms and now the time setting working. I think the callender integration will be the most challenging, since I don't know what the data means to Casio.
Currently the github is private, because it is WIP, but I will make it public when it is ready.
That would be very cool! I'll be happy to do some beta testing if you end up getting to that stage. Good luck!
@seanlano I have the basic app running, except for the reminders. If you like to try it, here is the github:
GitHub - izivkov/CasioGShockSmartSync
Contribute to izivkov/CasioGShockSmartSync development by creating an account on GitHub.
github.com
It is private, so not sure if you can access it, so let me know.
If you don't want to bother building the APK, I have put it on on my Google drive:
Google Drive: Sign-in
Access Google Drive with a Google account (for personal use) or Google Workspace account (for business use).
drive.google.com
I'm curious to see if for you the local time works properly, and the battery level is correct. Where are you located?
Of course, use at your own risk. It might screw up some settings on your watch. In that case, you may have to reset it like this:
Google Drive: Sign-in
Access Google Drive with a Google account (for personal use) or Google Workspace account (for business use).
drive.google.com
Ivo
izivkov said:
I'm curious to see if for you the local time works properly, and the battery level is correct. Where are you located?
Click to expand...
Click to collapse
Hey @izivkov, I tried it out and it seems to mostly work!
The time setting worked correctly (I made sure by manually setting the time to be very wrong, and your app brought it back to the correct time). The home time zone (Sydney) was correct too.
However, the battery level didn't work – the Casio app shows my watch at 100% but your app shows only maybe 20%.
The alarms worked well too, although I found that any time I set the alarms it turns off the hourly signal, and the app doesn't have a way to turn it back on (this isn't a big deal though, since it's only a couple of buttons to press on the watch).
Keep up the good work!
seanlano said:
Hey @izivkov, I tried it out and it seems to mostly work!
The time setting worked correctly (I made sure by manually setting the time to be very wrong, and your app brought it back to the correct time). The home time zone (Sydney) was correct too.
However, the battery level didn't work – the Casio app shows my watch at 100% but your app shows only maybe 20%.
The alarms worked well too, although I found that any time I set the alarms it turns off the hourly signal, and the app doesn't have a way to turn it back on (this isn't a big deal though, since it's only a couple of buttons to press on the watch).
Keep up the good work!
Click to expand...
Click to collapse
Hey, thanks for the feedback.
- I did not notice the hourly signal setting and will fix it. Possibly add a setting to the app to turn it on/off.
- For the battery level, I was not sure I was getting the right value, but for me seemed to be about right. Obviously, should look at other ways to set it.
- I'm working on Calendar events integration with Watch's reminders, and when I finish this and fix these issues you mentioned I will have another version and will let you know.
Cheers
izivkov said:
Hey, thanks for the feedback.
- I did not notice the hourly signal setting and will fix it. Possibly add a setting to the app to turn it on/off.
- For the battery level, I was not sure I was getting the right value, but for me seemed to be about right. Obviously, should look at other ways to set it.
- I'm working on Calendar events integration with Watch's reminders, and when I finish this and fix these issues you mentioned I will have another version and will let you know.
Cheers
Click to expand...
Click to collapse
Hay, thanks for starring my github. I moved the code to another repository: https://github.com/izivkov/CasioGShockPhoneSync, which is now public. Feel free to star the new one. ;-)
Basically, I added Google calendar event support, and fixed the issue with hourly chime getting reset. Still cannot figure out how the battery level is read. I get a value using command 0x28, but the value does not make sense. I get back something like 0x28 0x0f 0x17 0x00 for about 25% charged battery, and 0x28 0x13 0x19 0x00 for almost fully charged one. I think I will disable the battery icon until I can figure what is going on.
Anyway, adding some documentation now. Hope other people can contribute to this project and possibly support more watch models.
I'm a bit stuck. I'm trying to detect the difference between GW-B5600 long-press lower left button and short-press lower-right button as far at connection to the Android device is concerned. The app on the phone should be able to tell the difference, becase the official app acts differntly when the right button is pressed, i.e. sets the current location. This does not happen for left-button connection. But the data sent to the phone from the watch is identical. If somebody has figured this out, please let me know.
For those who are interested in how to communicate with the Casio G-Shock 5600 BT watches, here is the latest github I created:
GitHub - izivkov/CasioGShockSmartSync
Contribute to izivkov/CasioGShockSmartSync development by creating an account on GitHub.
github.com
And you can get the android app on PlayStore:
Casio G-Shock Smart Sync - Apps on Google Play
Add Smart functions to your Casio G-Shock Bluetooth (B5600, B5000, B2100) watch.
play.google.com
Enjoy
I've been working on a very similar app but for a slightly different Casio model. I'm not very familiar with the BLE and getting to a point where I'd happily pay someone for investigating the communication.
Would anyone be willing to figure it out?
drunkenHiker said:
I've been working on a very similar app but for a slightly different Casio model. I'm not very familiar with the BLE and getting to a point where I'd happily pay someone for investigating the communication.
Would anyone be willing to figure it out?
Click to expand...
Click to collapse
Sure, I can take a look. You can contact me by email directly at [email protected], or better still you can post to the github repository:
izivkov/CasioGShockSmartSync · Discussions
Explore the GitHub Discussions forum for izivkov CasioGShockSmartSync. Discuss code, ask questions & collaborate with the developer community.
github.com