added ability to connect to the current DeviceSupport
By binding the DeviceCommunicationService a binder object can now be acquired, which then can be used to get a reference to the currently responsible DeviceSupport.
In my example this is done from a random activity to interact with the QHybridSupport class and get the device vibration strength, which is handled here.
I tried to come up with a way of communicating with the DeviceSupport from basically any point in the app, and this is the best i could come up with. Please enlighten me if there is another method of archieving the same, in my case to call that getVibrationStrength() method.
Thanks for the PR, but this is most probably not the way to go forward with this. The DeviceSupport classes are the lowlevel work horses with individual abilities and should not be accessed directly (only through the service).
The normal information flow from a DeviceSupport instance to the UI is via an Intent. So we should add a new method to EventHandler and the implementations for requesting the vibration strength (in your example). Since we shouldn't add a new method for every single flag to query, should make that a generic method, like onGenericDeviceReq(String which, Bundle args). The implementation would then find out which information is requested (vibration strength -- use device specific constants), get the information via (typically via BtleQueue) and return the result asynchronously via an Intent when received. The intent should get the which name as extra, in addition to the device and the result.
How does this sound?
sounds good. But when you say "via Intent", do you mean something like a local Broadcast?
Or maybe some sort of a binder, which is implemented and returned by the DeviceSupport?
Yes, a broadcast intent. See GBDevice#sendDeviceUpdateIntent() and its usage, for example.
wouldn't it be possible to add a Binder-like system for the DeviceSupports? So that every DeviceSupport would have a callback which returns a Specially crafted Class giving some control over that DeviceSupport, yet not giving direct access to it? Basically an onBind, but in terms of DeviceSupport.
Unless you have some very compelling arguments against the other solution, no. Those instances belong to the service, and should be called though the service.
I may need some stream-like interaction with my gadget from different activities, and to manage bi-directional communication with different types of messaging, even more when one of those types involves sending continuous Broadcasts seems like a waste of ressources to me.
Yet, when your proposed solution is your way to go, i am going to adapt to that whenever it gets implemented.
Care to elaborate on that? I have no idea what use case(s) that might be.
For instance, i would want to make the real clock hands make the hand settings on the screen. This involves sending such a mesage ohn every hand move on the screen.
Also, relying on the delivery of such a message makes it pretty hard to distinguish whether a device is connected or if is the real device.
Throughout my whole argumentation i might be a bit one-sided, since i am using the Androids Service-Binder-implementation. Thus, although i understand your wish of isolating those parts of the application, i see sense in giving developers a chance of communicating with the connected device more of less directly.
A second case i might see that feature handy for is file synchronization. Activity files, such as sleep and motion activity are stored on the watch and have to be downloaded. And those may get quite big, and once again, sending those files by value through a broadcast just seems like a waste of Ressources to me.
-
A hand move would be at most once per second (for the seconds hand), right? We have the same for live activity, for example.
-
You get the correct
GBDeviceinto your activity. You can queryisConnected(), or ratherisInitialized(). And your activity would only be started with a Fossil Q device, not anything else. -
For larger data like files, your
DeviceSupportclass would probably store the file either in the db, like activity data, or in the filesystem, and just broadcast a URI.
Alright, i'll try to adapt my code to that concept.
so...how do i query that GBDevice from an activity?
You would get the device right from the intent that started the activity. In onCreate(), use
device = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE);
Callers have to ensure that they actually pass the device like that, of course.
What class does my activity have to extend in order to receive that parcelable?
Because if my Activity extends the AbstractGBActivity class getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE) somehow always returns null, no matter if the device is connected.
EDIT
as far as i understant, all the settings activities get started in nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity.
So, how should the EXTRA_DEVICE get into the Intent?
AFAICS, we have only one SettingsActivity, and indeed it doesn't receive the device. Most of the activities are started from GBDeviceAdapterv2 (where the get the device) and from ControlCenterv2 (where they don't get the device.
This should be fixed so that they always get the device.
so, how to hotfix that problem in the case of ControlCenterv2? how to get the device there for now?
As a hotfix, you can use this:
DeviceManager deviceManager = ((GBApplication) getApplication()).getDeviceManager();
GBDevice device = deviceManager.getSelectedDevice();
Before adding the EXTRA_DEVICE parameter to all activities, we need to determine how this relates to multi-device support (multiple devices connected at the same time). Also devices getting disconnected, etc.
@cpfeiffer how does your hotfix handle the scenario of multiple devices?
It should only return the currently connected device (atm there can only be one).
alright... maybe override startActivity in ControlCenterv2, so the device is added? concerning multiple devices...the only option i see is to add an array of all connected devices, but i can imagine that would break a lot of code already written...
and concerning devices disconnecting, i really think it is on the developers side to register for a corresponding DEVICE_DISCONNECTED broadcast or something...
@dakhnod Multiple connected device support definitely breaks quite a lot (including phones' bluetooth stacks D:) but I wouldn't concern myself with that in this PR. You can see my WIP here - https://github.com/Freeyourgadget/Gadgetbridge/pull/1039 Though IMHO the UI changes are much harder to get right.
well, i'll just go with a hotfix for now...
so, what is the current state?
How can i get access to the device support from the Settings UI?