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

Notification handling and work manager tweaks #177

Merged
merged 8 commits into from
Dec 12, 2023
Merged

Notification handling and work manager tweaks #177

merged 8 commits into from
Dec 12, 2023

Conversation

bjester
Copy link
Member

@bjester bjester commented Nov 30, 2023

Summary

  • Reverts Notification tweaks #175
  • Adds a new notification channel, separating the foreground service notification and the task notifications
  • Updates the foreground service notification to be completely separate with static int ID
  • Updates task notifications to use a static int ID and a tag matching the work request ID to maintain notifications for each
  • Creates an App class to define configuration for WorkManager, including a fixed thread pool executor, and moves notification channel creation to it
  • Disables automatic initialization of WorkManager so we only initialize it in our foreground service process
  • Ensures we use RemoteWorkManager when queuing / checking work requests (ref)
  • Updates worker to use tags for noting long-running tasks
  • Creates Notifier interface, NotificationRef and NotificationBuilder classes for utility in handling notifications
  • Updates our Worker implementation to function more like the standard Worker which opens a background thread for processing automatically (ref)
  • Adds button to foreground service notification that takes user to settings so they can minimize it
  • Adds ticker text to notifications used by accessibility services

@bjester bjester requested a review from rtibbles December 1, 2023 15:18
Copy link
Member Author

@bjester bjester left a comment

Choose a reason for hiding this comment

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

@rtibbles some comments. I think I want to clean up a few things but could be done in followup. Fine with either!

@@ -24,7 +24,7 @@
<application android:label="@string/app_name"
android:icon="@mipmap/icon"
android:allowBackup="true"

android:name=".App"
Copy link
Member Author

@bjester bjester Dec 6, 2023

Choose a reason for hiding this comment

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

@rtibbles This is for defining the main Application class. I wasn't sure if this would cause any problems with python4android, but it doesn't seem like it.


boolean longRunning = getInputData().getBoolean(ARGUMENT_LONG_RUNNING, false);
public boolean isLongRunning() {
return getTags().contains(TAG_LONG_RUNNING);
Copy link
Member Author

@bjester bjester Dec 6, 2023

Choose a reason for hiding this comment

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

@rtibbles I made this a tag instead because I think there might be a way to listen on the bind/unbind of these task workers to the service process, perhaps to handle notifications or some other service process behavior, and tags seem a little more straightforward to check against.

@Override
public void run() {
Log.d(TAG, "Running with python worker argument: " + serviceArg);
Log.d(TAG, id + " Running with python worker argument: " + arg);
Copy link
Member Author

Choose a reason for hiding this comment

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

I think I want to better format these log messages using the request ID. I was reading on Java's String interpolation

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, the logging in general leaves a lot to be desired, but you've made it no worse!

} else {
completer.set(Result.failure());
Log.w(TAG, id + " Exception in remote python work, scheduling retry", e);
future.set(Result.retry());
Copy link
Member Author

Choose a reason for hiding this comment

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

@rtibbles should I just get rid of this retry behavior since we're not even sure it works?

Copy link
Member

Choose a reason for hiding this comment

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

Might make things simpler - and I had kind of assumed that WorkManager should be handling this with its retry behaviour also?


public static boolean isWorkerContext() {
return PythonWorker.mWorker != null;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I was at one point going to use these externally but didn't

R.drawable.baseline_notifications_paused_24,
context.getString(R.string.notification_service_channel_action),
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
).build());
Copy link
Member Author

Choose a reason for hiding this comment

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

This adds that Manage action button to the sticky service notification

return;
}
ID_CHANNEL_DEFAULT = context.getString(R.string.notification_default_channel_id);
ID_CHANNEL_SERVICE = context.getString(R.string.notification_service_channel_id);
Copy link
Member Author

Choose a reason for hiding this comment

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

@rtibbles I saw some code examples where these were just static variables. Maybe we don't need them in that string configs and these references can be simplified?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I was also a little confused why the examples I was seeing drew from the resource manifest - I guess the main thing is to have them be referenceable in other files.

RemoteWorkManager workManager = RemoteWorkManager.getInstance(context);
WorkQuery workQuery = WorkQuery.Builder
.fromTags(tags)
.build();
Copy link
Member Author

Choose a reason for hiding this comment

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

The RemoteWorkManager only has getWorkInfos so I had to use the WorkQuery here

android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.93 6,11v5l-2,2v1h16v-1l-2,-2zM14.5,9.8l-2.8,3.4h2.8L14.5,15h-5v-1.8l2.8,-3.4L9.5,9.8L9.5,8h5v1.8z"/>
</vector>
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a bell icon with snooze 'z'. It doesn't seem to show anywhere 🤷‍♂️

Copy link
Member

Choose a reason for hiding this comment

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

Hrm, it's meant to show up in the notification intent launch though, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, and the API requires it but I never saw it show

src/android_app_plugin/kolibri_plugin.py Show resolved Hide resolved
Copy link
Member

@rtibbles rtibbles left a comment

Choose a reason for hiding this comment

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

No real concerns, thanks for the walk through!

@Override
public void run() {
Log.d(TAG, "Running with python worker argument: " + serviceArg);
Log.d(TAG, id + " Running with python worker argument: " + arg);
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, the logging in general leaves a lot to be desired, but you've made it no worse!

} else {
completer.set(Result.failure());
Log.w(TAG, id + " Exception in remote python work, scheduling retry", e);
future.set(Result.retry());
Copy link
Member

Choose a reason for hiding this comment

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

Might make things simpler - and I had kind of assumed that WorkManager should be handling this with its retry behaviour also?

if (mWorker != null) {
// We could also update progress on the worker here, if we need info about it on
// the Android side
// @see setProgressAsync
Copy link
Member

Choose a reason for hiding this comment

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

Yeah - I guess the only thing would be if we wanted to handle the progress updating of the notification via Java rather than doing send notification here.

PythonUtil.loadLibraries(
new File(context.getApplicationInfo().nativeLibraryDir)
);
// Initialize the work manager
WorkManager.getInstance(getApplicationContext());
super.onCreate();
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, to be honest, I really have no idea - if it works, it works!


// defaults for service notification channel
if (channelId.equals(NotificationRef.ID_CHANNEL_SERVICE)) {
setOngoing(true);
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, looking at the docs for it, it does seem like it makes the notification more rather than less prominent: https://developer.android.com/reference/android/app/Notification.Builder#setOngoing(boolean)

return;
}
ID_CHANNEL_DEFAULT = context.getString(R.string.notification_default_channel_id);
ID_CHANNEL_SERVICE = context.getString(R.string.notification_service_channel_id);
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I was also a little confused why the examples I was seeing drew from the resource manifest - I guess the main thing is to have them be referenceable in other files.

android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.93 6,11v5l-2,2v1h16v-1l-2,-2zM14.5,9.8l-2.8,3.4h2.8L14.5,15h-5v-1.8l2.8,-3.4L9.5,9.8L9.5,8h5v1.8z"/>
</vector>
Copy link
Member

Choose a reason for hiding this comment

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

Hrm, it's meant to show up in the notification intent launch though, right?

src/android_app_plugin/kolibri_plugin.py Show resolved Hide resolved
@bjester bjester merged commit 017faa3 into develop Dec 12, 2023
4 checks passed
@rtibbles rtibbles deleted the revert-175 branch January 16, 2024 20:13
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