Open Domi04151309 opened 4 years ago
I am currently working on that feature.
I am running into an issue with the communication between the watch and the phone. The watch only receives messages when it feels like it. This is absolutely random.
Sorry to hear that. Unfortunately I cannot help you as I don't own a smartwatch.
I have kind of figured it out now. Can you describe or show me code that gets the timetable data from Untis? That would speed up development a lot.
TimetableLoader
val timetableLoader = TimetableLoader(WeakReference(context), timetableDisplay, profileUser, timetableDatabaseInterface)
context
is just the Context
of an activity (not sure how it works in your case)timetableDisplay
is any object extending TimetableDisplay
, this contains the callback functions addTimetableItems
and onTimetableLoadingError
profileUser
and timetableDatabaseInterface
: load a profile from the user database like this:
val userDatabase = UserDatabase.createInstance(context)
userDatabase.getUser(profileId)?.let {
profileUser = it
timetableDatabaseInterface = TimetableDatabaseInterface(userDatabase, it.id ?: -1)
}
You need to specify a profileId
or load the currently selected profile id like this:
preferenceManager.currentProfileId()
preferenceManager
is just a PreferenceManager(context)
object.
val target = TimetableLoader.TimetableLoaderTarget(...)
timetableLoader.load(target, flags, proxyHost)
For proxyHost
, use the preferenceManager
from above:
val proxyHost = preferenceManager.defaultPrefs.getString("preference_connectivity_proxy_host", null)
flags
can be an OR-combination of TimetableLoader.FLAG_LOAD_CACHE
TimetableLoader.FLAG_LOAD_SERVER
.
I recommend you use only FLAG_LOAD_CACHE
and check for error codes like this:
override fun onTimetableLoadingError(requestId: Int, code: Int?, message: String?) {
when (code) {
TimetableLoader.CODE_CACHE_MISSING -> timetableLoader.repeat(requestId, TimetableLoader.FLAG_LOAD_SERVER, proxyHost)
else -> {
// show error message
}
}
}
That way cache is used if available and only loads from the server if necessary.
Let's hope I didn't forget anything :)
Thanks @SapuSeven that's already a lot of information. What do you think is the best method for copying a profile to the watch? I'd suggest to only copy the currently selected profile to the watch. It would be nice to copy as less as possible like only the username, school and password.
I really don't know how smartwatch development works.
Fact is that the app uses more than just authentication details to display the timetable, as the API provides IDs for every element instead of plain text names.
So to view the timetable, you'd need at least data from every table in the userdata.db
database with the _user_id
field corresponding to the current profile.
It basically works the same way as with phone development. I am currently trying to copy over the logic from the LoginDataInputActivity so that I can create a user on the watch.
Some stuff will likely be duplicated so it is worth considering to export the basic logic to a module and only leave the data adaption in the app modules.
I am having issues with getting the timetable. Can you help me print the lessons for the current day to the logs?
Most of the classes are just copied over but i have to use a modified TimetableLoader and TimetableGridItem because i don't use the weekview.
Alright, first of all we should definitely avoid these duplicate files in the project later on.
Anyways, here's what I would do in the mentioned code section to quickly test it:
val today = UntisDate.fromLocalDate(LocalDate.now())
timetableLoader.load(TimetableLoader.TimetableLoaderTarget(today, today, profileUser.userData.elemId, profileUser.userData.elemType ?: ""), TimetableLoader.FLAG_LOAD_SERVER)
and set a breakpoint inside the addTimetableItems
function to inspect the items
parameter of said function.
With the code above the app crashes with the following error
2020-03-18 15:55:36.344 25526-25526/com.sapuseven.untis.debug E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sapuseven.untis.debug, PID: 25526
kotlinx.serialization.json.JsonUnknownKeyException: Strict JSON encountered unknown key: jsonrpc
You can disable strict mode to skip unknown keys
at kotlinx.serialization.json.internal.StreamingJsonInput.decodeElementIndex(StreamingJsonInput.kt:96)
at com.sapuseven.untis.models.untis.response.TimetableResponse$$serializer.deserialize(Unknown Source:18)
at com.sapuseven.untis.models.untis.response.TimetableResponse$$serializer.deserialize(TimetableResponse.kt:8)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:33)
at kotlinx.serialization.json.internal.StreamingJsonInput.decodeSerializableValue(StreamingJsonInput.kt:29)
at kotlinx.serialization.CoreKt.decode(Core.kt:79)
at kotlinx.serialization.json.Json.parse(Json.kt:148)
at com.sapuseven.untis.wear.helpers.TimetableLoader.loadFromServer(TimetableLoader.kt:102)
at com.sapuseven.untis.wear.helpers.TimetableLoader$loadFromServer$1.invokeSuspend(Unknown Source:13)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
This is really strange because as far as I understand the code strict mode is already disabled and the key jsonrpc
is known.
Look at #14 , it's a weird bug, just clean the project before you build it.
Setup | Connecting | Timetable | Timetable 2 |
---|---|---|---|
That already looks really nice! As I mentioned, there's still some work to do to avoid duplicate code between the main and the smartwatch code.
I would recommend merging the wear-support
branch when I have implemented everything and then creating a new branch and copying over the logic to a new module which can be included in the app
and the wear
module.
That sounds like a great idea.
I think you don't need to worry about merging multihour lessons as this will be implemented in that shared module.
I'll start working on it after your PR.
I think i have found quite an effective method for merging multihour lessons. I first sort the array by the time the lesson starts and then cycle through the array and check if there is an item with the same name and a start time that matches the end time.
Only problem with that is if you have something like a 5 minute break between the lessons. Start and end time won't match in that case.
That's why I went with sorting the items into a timegrid.
I think we can have two methods for that. One optimized for a list and one optimized for the weekview.
Some planning
app
All things related directly to the app, e.g.:
wear
All things related to the wear app, e.g.:
weekview
No changes there
untis
All things related to the "deeper workings" of the app, e.g.:
That looks great to me. How do you plan on integrating these changes? You can submit pull requests for a new branch if you like.
I plan to wait until you finished the teacher specific features to not cause unnecessary extra work.
Will the Galaxy store for the Samsung Watches supported too?
I'm sorry but currently there are no plans to support any other platform than Wear OS. Even then it will probably be a while until smart watches are supported, as this PR is quite out of date by now and I'm not actively working on it myself.
Describe the solution you'd like It would be nice if there was an option to see the current day on your watch.