feat(dev-app): register native fetcher SPI implementation

Add host app implementation of NativeNotificationContentFetcher for development app:
- Create PluginApplication extends Application to register fetcher on app startup
- Create DemoNativeFetcher implementing NativeNotificationContentFetcher interface
- Register PluginApplication in AndroidManifest.xml
- DemoNativeFetcher returns mock notification content for testing

This demonstrates the SPI pattern where host apps provide their own
content fetching implementation to the plugin for background workers.
This commit is contained in:
Matthew Raymer
2025-10-30 07:04:29 +00:00
parent 6d76ad39b9
commit 4d7dfcb842
3 changed files with 124 additions and 0 deletions

View File

@@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".PluginApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"

View File

@@ -0,0 +1,85 @@
/**
* DemoNativeFetcher.java
*
* Simple demo implementation of NativeNotificationContentFetcher for the plugin demo app.
* Returns mock notification content for demonstration purposes.
*
* @author Matthew Raymer
* @version 1.0.0
*/
package com.timesafari.dailynotification;
import android.util.Log;
import androidx.annotation.NonNull;
import com.timesafari.dailynotification.FetchContext;
import com.timesafari.dailynotification.NativeNotificationContentFetcher;
import com.timesafari.dailynotification.NotificationContent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Demo implementation of native content fetcher
*
* Returns mock notification content for demonstration. In production host apps,
* this would fetch from TimeSafari API or other data sources.
*/
public class DemoNativeFetcher implements NativeNotificationContentFetcher {
private static final String TAG = "DemoNativeFetcher";
@Override
@NonNull
public CompletableFuture<List<NotificationContent>> fetchContent(
@NonNull FetchContext context) {
Log.d(TAG, "DemoNativeFetcher: Fetch triggered - trigger=" + context.trigger +
", scheduledTime=" + context.scheduledTime + ", fetchTime=" + context.fetchTime);
return CompletableFuture.supplyAsync(() -> {
try {
// Simulate network delay
Thread.sleep(100);
List<NotificationContent> contents = new ArrayList<>();
// Create a demo notification
NotificationContent demoContent = new NotificationContent();
demoContent.setId("demo_notification_" + System.currentTimeMillis());
demoContent.setTitle("Demo Notification from Native Fetcher");
demoContent.setBody("This is a demo notification from the native fetcher SPI. " +
"Trigger: " + context.trigger +
(context.scheduledTime != null ?
", Scheduled: " + new java.util.Date(context.scheduledTime) : ""));
// Use scheduled time from context, or default to 1 hour from now
long scheduledTimeMs = context.scheduledTime != null ?
context.scheduledTime : (System.currentTimeMillis() + 3600000);
demoContent.setScheduledTime(scheduledTimeMs);
// fetchTime is set automatically by NotificationContent constructor (as fetchedAt)
demoContent.setPriority("default");
demoContent.setSound(true);
contents.add(demoContent);
Log.i(TAG, "DemoNativeFetcher: Returning " + contents.size() +
" notification(s)");
return contents;
} catch (InterruptedException e) {
Log.e(TAG, "DemoNativeFetcher: Interrupted during fetch", e);
Thread.currentThread().interrupt();
return Collections.emptyList();
} catch (Exception e) {
Log.e(TAG, "DemoNativeFetcher: Error during fetch", e);
return Collections.emptyList();
}
});
}
}

View File

@@ -0,0 +1,38 @@
/**
* PluginApplication.java
*
* Application class for the Daily Notification Plugin demo app.
* Registers the native content fetcher SPI implementation.
*
* @author Matthew Raymer
* @version 1.0.0
*/
package com.timesafari.dailynotification;
import android.app.Application;
import android.util.Log;
import com.timesafari.dailynotification.DailyNotificationPlugin;
import com.timesafari.dailynotification.NativeNotificationContentFetcher;
/**
* Application class that registers native fetcher for plugin demo app
*/
public class PluginApplication extends Application {
private static final String TAG = "PluginApplication";
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Initializing Daily Notification Plugin demo app");
// Register demo native fetcher
NativeNotificationContentFetcher demoFetcher = new DemoNativeFetcher();
DailyNotificationPlugin.setNativeFetcher(demoFetcher);
Log.i(TAG, "Demo native fetcher registered: " + demoFetcher.getClass().getName());
}
}