Skip to content
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

Add Unifiedpush support #3

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open

Add Unifiedpush support #3

wants to merge 25 commits into from

Conversation

p1gp1g
Copy link

@p1gp1g p1gp1g commented Oct 25, 2024

SDK

The SDK exposes the UnifiedPush dependency directly with a 'api' dependency so it can be used to un/register, select the default distributor etc.

The library exposes the UnifiedPush broadcast receiver by itself and forward events to a (non-exported) service the application must implement. That way, we reduce risk of any breaking change.
For that reason, I've hesitated to rewrite PushMessage, PushEndpoint, and FailedReason, to avoid passing classes defined in connector's library.

Any message that haven't been correctly decrypted is ignored. For information, the connector library doesn't do that by itself for backward compatibility, if the application doesn't use web push correctly.

Client sample

There is a MockApplicationServer that emulate a remote application server. Client<->Server calls are emulated with functions of MockApplicationServer.MockApi.

I have added some horizontal dividers to add some clarity on the UI.

I've added a new section for push messages:
if unregistered: a button to register
if registered: a button to unregister and a button to send a test notification

The application register to the distributor with VAPID enabled, the MockApplicationServer sends the push message with VAPID.

When receiving a push notification, a notification is displayed with the content of the test message.

@khvMX
Copy link
Collaborator

khvMX commented Oct 28, 2024

Hi @p1gp1g. I have questions which I hope you can shed some light on. I'm sorry if I'm asking things which have been clarified already.

  1. This PR would embed UnifiedPush directly in "COVESA SDK", without clear separation of its implementation and dependencies from other future "libraries". Have you considered some modularization approach to avoid mixing this with previous and future changes? I'm also thinking about versioning separate libraries within COVESA SDK separately.
  2. Should we have different sample apps for different libraries?
  3. Is "EventBus" dependency really necessary with current Kotlin and Jetpack state of the art capabilities?

@p1gp1g
Copy link
Author

p1gp1g commented Oct 29, 2024

Hi @khvMX,

  1. This PR would embed UnifiedPush directly in "COVESA SDK", without clear separation of its implementation and dependencies from other future "libraries". Have you considered some modularization approach to avoid mixing this with previous and future changes? I'm also thinking about versioning separate libraries within COVESA SDK separately.

Indeed, I think there are 2 ways to expose the feature: directly as an api dependency, and the service uses intent with the library classes (https://github.com/COVESA/covesa-aosp-sdk/pull/3/files#diff-dbdd43b7bfea8a29b76c088d80d8d17974ee18ddb299a354f0084cea5f853a49R9-R11) or write new classes that call the library ones. The first solution takes advantage of new features (if any) more easily, the second improves control on the updates.

I asked Maximilian, and he said that one or the other is fine to open the PR, then we can discuss about it.

Let me know if you prefer the 2nd option, it is very fast to do

  1. Should we have different sample apps for different libraries?

Both solution make sense. Having a different sample per feature would probably make it clearer. Let me know if you want to split the sample

  1. Is "EventBus" dependency really necessary with current Kotlin and Jetpack state of the art capabilities?

I've removed it, also it wasn't very clean how the PushUiState was updated, I've fixed that

@khvMX
Copy link
Collaborator

khvMX commented Oct 29, 2024

Indeed, I think there are 2 ways to expose the feature: directly as an api dependency, and the service uses intent with the library classes (https://github.com/COVESA/covesa-aosp-sdk/pull/3/files#diff-dbdd43b7bfea8a29b76c088d80d8d17974ee18ddb299a354f0084cea5f853a49R9-R11) or write new classes that call the library ones. The first solution takes advantage of new features (if any) more easily, the second improves control on the updates.

I asked Maximilian, and he said that one or the other is fine to open the PR, then we can discuss about it.

Let me know if you prefer the 2nd option, it is very fast to do

Good point, let's create an issue for that here? It would be great if others would join the discussion. On some of the meetings someone said that "COVESA SDK clients' efforts must be reduced to the absolute minimum", which I support too. Also, reducing API surface would allow for easier under-the-hood changes, albeit for the cost of client flexibility.

@khvMX
Copy link
Collaborator

khvMX commented Oct 29, 2024

3. Should we have different sample apps for different libraries?

Both solution make sense. Having a different sample per feature would probably make it clearer. Let me know if you want to split the sample

Similar to the above, we probably should create another issue for that, simply to come back to this question once we have at least 3 different SDK features to see any commonalities between them.

@p1gp1g
Copy link
Author

p1gp1g commented Oct 31, 2024

Do you prefer issues or github discussions ? and would you like me to open them?

@khvMX
Copy link
Collaborator

khvMX commented Nov 4, 2024

Do you prefer issues or github discussions ? and would you like me to open them?

Let's move these to (potentially separate) discussions. Could you please create them stating how you have done it for UnifiedPush for now?

As for this PR, it LGTM.

@p1gp1g
Copy link
Author

p1gp1g commented Nov 4, 2024

Discussions for the 2 subjects:
#4
#5

@p1gp1g p1gp1g force-pushed the unifiedpush branch 2 times, most recently from 718026a to f6c02d2 Compare December 11, 2024 18:00
Copy link
Collaborator

@khvMX khvMX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I did not take time before to properly review.
I have left some comments, which are mostly my concerns.
What is also missing is updating the READMEs to reflect the fact that we now have 2 different kinds of services and 2 quite different examples of APIs for apps to use. I will upload some README changes to this branch, so that we can get it reviewed together.

class PushReceiver: MessagingReceiver() {

override fun onUnregistered(context: Context, instance: String) {
CoroutineScope(Dispatchers.IO).launch {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory leak? Is this scope ever destroyed? Concerns all methods in this file.

*
* ```
* class MyActivity: Activity() {
* /* ... */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://kotlinlang.org/docs/kotlin-doc.html#kdoc-syntax
*/ is the end of comment started on line 8. Some parsers may break. Maybe remove this line?

* // An error occurred, consider no distributor found for the moment
* }
* }
* /* ... */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

* }
* ```
*/
class LinkActivityHelper(activity: Activity) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not have a sample which uses this class. I have found this comment here:

 * Be aware that [tryUseDefaultDistributor][org.unifiedpush.android.connector.UnifiedPush.tryUseDefaultDistributor]
 * starts a new translucent activity in order to get the result of the distributor activity. You may prefer to use
 * [LinkActivityHelper][org.unifiedpush.android.connector.LinkActivityHelper] directly in your own activity instead.

So which API is recommended? Maybe at least mention this in documentation to this class?

/**
* Object containing functions to interact with the distributor
*
* <!-- Note: This must be mirrored in Module.md -->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which Module.md?

* Update the UI
*/
private fun updateRegistrationState(registered: Boolean) {
CoroutineScope(Dispatchers.IO).launch {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, memory leak?
you probably need scope injected here

if (lightsUiState.installedServiceVersion is LightServiceVersion.Installed) {
LightStates(lightsUiState.lights)
}

HorizontalDivider(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a smaller screen, this content does not fit, maybe make the whole screen scrollable with Scaffold?

data class PushUiState (
val registered: Boolean = false
) {
constructor(context: Context) : this(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably can be injected with a boolean instead, see above

@@ -18,6 +23,7 @@ class MainActivity : ComponentActivity() {
setContent {
val viewModel: MainViewModel = viewModel {
MainViewModel(
context = this@MainActivity,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be avoided (see other comments)

private fun subscribeActions() {
CoroutineScope(Dispatchers.IO).launch {
ActionEvent.events.collect {
it.handleAction(this@MainActivity)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are giving a reference to an object (MainActivity) which may be destroyed to a global event queue, which may try to use it when it's already destroyed. We need some common scope for these.

@p1gp1g
Copy link
Author

p1gp1g commented Dec 13, 2024

Thank you @khvMX , most of the comments have been resolved

@khvMX
Copy link
Collaborator

khvMX commented Dec 16, 2024

On my emulator the client sample is now crashing with this:

2024-12-16 09:10:34.099 12966-12966 AndroidRuntime          global.covesa.sdk.client             E  FATAL EXCEPTION: main
                                                                                                    Process: global.covesa.sdk.client, PID: 12966
                                                                                                    java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed. One of the common reasons is nesting layouts like LazyColumn and Column(Modifier.verticalScroll()). If you want to add a header before the list of items please add a header as a separate item() before the main items() inside the LazyColumn scope. There are could be other reasons for this to happen: your ComposeView was added into a LinearLayout with some weight, you applied Modifier.wrapContentSize(unbounded = true) or wrote a custom layout. Please try to remove the source of infinite constraints in the hierarchy above the scrolling container.

I believe we're nesting LazyColumn in a Column(Modifier.verticalScroll())

@p1gp1g
Copy link
Author

p1gp1g commented Dec 16, 2024

Thanks, fixed

khvMX and others added 3 commits December 16, 2024 15:09
Update READMEs with push notification APIs
ntfy doesn't support the last version of the spec at this moment
Copy link
Collaborator

@khvMX khvMX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We can clean up or change things related to Singleton usage later on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants