-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prefer faster networks for downloads on watch #881
Conversation
@DownloadOkHttpClient | ||
fun downloadOkHttpClient(): OkHttpClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am providing this in the repository module because the wear app needs the OkHttpClient
to create a NetworkSelectingCallFactory
which serves as the Call.Factory
for downloads (@DownloadCallFactory
) in the watch app. The phone and automotive apps just return this directly with their @DownloadCallFactory
providers.
@DownloadRequestBuilder | ||
fun downloadRequestBuilder(): Request.Builder = | ||
Request.Builder() | ||
.requestType(RequestType.MediaRequest.DownloadRequest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This RequestType
comes from the horologist library and setting it on the Request.Builder
for wear requests is the only reason I need to inject it separately for the wear vs phone/automotive apps.
check(requestType != RequestType.UnknownRequest) { | ||
"Unknown request type. Failing on debug builds." | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seemed like a good way to make sure we don't use these networking rules but forget to set a request type on the request.
|
||
@Module | ||
@InstallIn(SingletonComponent::class) | ||
object AutomotiveAppModule { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a duplicate fo the AppModule
. We could create a new module shared only by the phone and wear apps to avoid this duplication, but that felt like it would be overcomplicating things. Maybe later something like that may make sense (I kind of doubt it though).
@DownloadCallFactory private val callFactory: Call.Factory, | ||
@DownloadRequestBuilder private val requestBuilderProvider: Provider<Request.Builder> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depending on which app is running (phone/automotive/wear), these dependencies will be provided by the @DownloadCallFactory
and @DownloadRequestBuilder
provide methods from the relevant app (i.e., from AppModule
, AutomotiveAppModule
or WearNetworkModule
).
Request.Builder() | ||
.requestType(RequestType.MediaRequest.DownloadRequest) | ||
|
||
// FIXME update the provide methods below this point |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I put this cleanup in a follow-up PR.
cbfb0df
to
d7ff7c6
Compare
Hey @mchowning! 👋 Hats off for putting out this PR, it must have been tricky to figure out dependency injection like this and also support it with tests. 🕵️ While everything that you described makes sense, I still see |
Interesting. I assume you're using a physical watch device paired to a physical phone in your testing. I just retested this, and I'm still seeing the expected behavior on my watch. 🤔 Perhaps you could try dropping a breakpoint or log message on the changed line and see (1) that the code is actually getting to that point and, if it is (2) what networks are actually available (i.e., maybe the watch is reporting that Bluetooth isn't available for some reason). |
Yes, I was using a physical watch, Bluetooth paired with a physical mobile device, and connected to wifi.
Also added a breakpoint, the code actually hit that point I'm not sure what was wrong, I factory reset my watch and tried it all over again, 😅 this time it worked 🥳 Great job! I'm approving the PR now. |
Description
This PR uses the horologist network-awareness library to prefer faster networks when we download media. Without this, the watch defaults to using slower network connections (i.e., Bluetooth). More info here.
There was some trickiness integrating this because this wraps the
Call.Factory
which we create in the repository module. I initially tried using the library directly there, but the problem is that the network-awareness library (1) uses watch features (or at least claims it does in its manifest file) and (2) has min SDK of 26. Since the phone app uses our repository module, both of these requirements created issues.To work around this, I have created an annotation in the repository module to provide the relevant
Call.Factory
, but the@Provides
methods for those annotations are in the application modules (phone, automotive, and wear). I'm keeping the actual construction of the non-wear dependencies in the repository module—the application module is really only responsible for identifying which dependency to inject.I had to do something similar with the
Request.Builder
because this library creates an extension method (.requestType(...)
that needs to be set with an object from the library.I'm only doing this for downloads currently, but I imagine I'll be doing something similar for some of our other okhttp requests in the future, so let me know any issues you see with this pattern.
This is a bit confusing from the DI perspective, but it completely avoids having any horologist dependency in our repository module, which feels like a nice win. With that said, let me know if you think this is too messy and not worth it.
Testing Instructions
HTTPS request media-download Wifi
reflecting that Wifi was used for the downloadHTTPS request media-download BT
reflecting that Bluetooth was used for the downloadChecklist
modules/services/localization/src/main/res/values/strings.xml