feat(android): implement Phase 2.2 Android exact alarm fallback completion
- Add DailyNotificationExactAlarmManager with SCHEDULE_EXACT_ALARM permission handling - Add DailyNotificationRebootRecoveryManager for system reboot and time-change recovery - Update DailyNotificationScheduler with exact alarm manager integration - Add exact alarm status checking and permission request methods - Add windowed alarm fallback (±10m) when exact alarms are denied - Add deep-link to exact alarm settings for user guidance - Add reboot recovery with broadcast receiver registration - Update TypeScript interface with new exact alarm and recovery methods - Update web implementations with placeholder methods - Add phase2-2-android-fallback.ts usage examples This completes Phase 2.2 Android fallback implementation: - Exact alarm permission handling with graceful fallback - Windowed alarm support (±10m) for battery optimization - Reboot and time-change recovery with broadcast receivers - Deep-link to exact alarm settings for user enablement - Integration with existing TTL enforcement and rolling window - Comprehensive fallback scenarios and error handling Files: 7 changed, 1200+ insertions(+)
This commit is contained in:
321
examples/phase2-2-android-fallback.ts
Normal file
321
examples/phase2-2-android-fallback.ts
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* Phase 2.2 Android Fallback Completion Usage Example
|
||||
*
|
||||
* Demonstrates Android exact alarm fallback functionality
|
||||
* Shows permission handling, windowed alarms, and reboot recovery
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
import { DailyNotification } from '@timesafari/daily-notification-plugin';
|
||||
|
||||
/**
|
||||
* Example: Configure Android exact alarm fallback
|
||||
*/
|
||||
async function configureAndroidExactAlarmFallback() {
|
||||
try {
|
||||
console.log('Configuring Android exact alarm fallback...');
|
||||
|
||||
// Configure with fallback settings
|
||||
await DailyNotification.configure({
|
||||
storage: 'shared',
|
||||
ttlSeconds: 1800, // 30 minutes TTL
|
||||
prefetchLeadMinutes: 15,
|
||||
maxNotificationsPerDay: 50 // Android limit
|
||||
});
|
||||
|
||||
console.log('✅ Android exact alarm fallback configured');
|
||||
|
||||
// The plugin will now:
|
||||
// - Request SCHEDULE_EXACT_ALARM permission
|
||||
// - Fall back to windowed alarms (±10m) if denied
|
||||
// - Handle reboot and time-change recovery
|
||||
// - Provide deep-link to enable exact alarms
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Android exact alarm fallback configuration failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Check exact alarm status
|
||||
*/
|
||||
async function checkExactAlarmStatus() {
|
||||
try {
|
||||
console.log('Checking exact alarm status...');
|
||||
|
||||
// Get exact alarm status
|
||||
const status = await DailyNotification.getExactAlarmStatus();
|
||||
|
||||
console.log('📱 Exact Alarm Status:');
|
||||
console.log(` Supported: ${status.supported}`);
|
||||
console.log(` Enabled: ${status.enabled}`);
|
||||
console.log(` Can Schedule: ${status.canSchedule}`);
|
||||
console.log(` Fallback Window: ${status.fallbackWindow}`);
|
||||
|
||||
// Example output:
|
||||
// Supported: true
|
||||
// Enabled: false
|
||||
// Can Schedule: false
|
||||
// Fallback Window: ±10 minutes
|
||||
|
||||
if (!status.enabled && status.supported) {
|
||||
console.log('⚠️ Exact alarms are supported but not enabled');
|
||||
console.log('💡 Consider requesting permission or opening settings');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Exact alarm status check failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Request exact alarm permission
|
||||
*/
|
||||
async function requestExactAlarmPermission() {
|
||||
try {
|
||||
console.log('Requesting exact alarm permission...');
|
||||
|
||||
// Request exact alarm permission
|
||||
await DailyNotification.requestExactAlarmPermission();
|
||||
|
||||
console.log('✅ Exact alarm permission request initiated');
|
||||
|
||||
// This will:
|
||||
// - Open the exact alarm settings screen
|
||||
// - Allow user to enable exact alarms
|
||||
// - Fall back to windowed alarms if denied
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Exact alarm permission request failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Open exact alarm settings
|
||||
*/
|
||||
async function openExactAlarmSettings() {
|
||||
try {
|
||||
console.log('Opening exact alarm settings...');
|
||||
|
||||
// Open exact alarm settings
|
||||
await DailyNotification.openExactAlarmSettings();
|
||||
|
||||
console.log('✅ Exact alarm settings opened');
|
||||
|
||||
// This will:
|
||||
// - Navigate to exact alarm settings
|
||||
// - Allow user to enable exact alarms
|
||||
// - Provide fallback information if needed
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Opening exact alarm settings failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Schedule notification with fallback handling
|
||||
*/
|
||||
async function scheduleWithFallbackHandling() {
|
||||
try {
|
||||
console.log('Scheduling notification with fallback handling...');
|
||||
|
||||
// Configure fallback
|
||||
await configureAndroidExactAlarmFallback();
|
||||
|
||||
// Check status first
|
||||
const status = await DailyNotification.getExactAlarmStatus();
|
||||
|
||||
if (!status.canSchedule) {
|
||||
console.log('⚠️ Exact alarms not available, will use windowed fallback');
|
||||
}
|
||||
|
||||
// Schedule notification
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: 'https://api.example.com/daily-content',
|
||||
time: '09:00',
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready',
|
||||
sound: true
|
||||
});
|
||||
|
||||
console.log('✅ Notification scheduled with fallback handling');
|
||||
|
||||
// The plugin will:
|
||||
// - Use exact alarms if available
|
||||
// - Fall back to windowed alarms (±10m) if not
|
||||
// - Handle permission changes gracefully
|
||||
// - Provide appropriate user feedback
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Scheduling with fallback handling failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Check reboot recovery status
|
||||
*/
|
||||
async function checkRebootRecoveryStatus() {
|
||||
try {
|
||||
console.log('Checking reboot recovery status...');
|
||||
|
||||
// Get reboot recovery status
|
||||
const status = await DailyNotification.getRebootRecoveryStatus();
|
||||
|
||||
console.log('🔄 Reboot Recovery Status:');
|
||||
console.log(` In Progress: ${status.inProgress}`);
|
||||
console.log(` Last Recovery Time: ${new Date(status.lastRecoveryTime)}`);
|
||||
console.log(` Time Since Last Recovery: ${status.timeSinceLastRecovery}ms`);
|
||||
console.log(` Recovery Needed: ${status.recoveryNeeded}`);
|
||||
|
||||
// Example output:
|
||||
// In Progress: false
|
||||
// Last Recovery Time: Mon Sep 08 2025 10:30:00 GMT+0000
|
||||
// Time Since Last Recovery: 120000ms
|
||||
// Recovery Needed: false
|
||||
|
||||
if (status.recoveryNeeded) {
|
||||
console.log('⚠️ Recovery is needed - system may have rebooted');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Reboot recovery status check failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Demonstrate fallback scenarios
|
||||
*/
|
||||
async function demonstrateFallbackScenarios() {
|
||||
try {
|
||||
console.log('Demonstrating fallback scenarios...');
|
||||
|
||||
// Configure fallback
|
||||
await configureAndroidExactAlarmFallback();
|
||||
|
||||
// Check initial status
|
||||
const initialStatus = await DailyNotification.getExactAlarmStatus();
|
||||
console.log('📱 Initial Status:', initialStatus);
|
||||
|
||||
// Schedule notification
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: 'https://api.example.com/daily-content',
|
||||
time: '09:00',
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready'
|
||||
});
|
||||
|
||||
console.log('✅ Notification scheduled');
|
||||
|
||||
// Check status after scheduling
|
||||
const afterStatus = await DailyNotification.getExactAlarmStatus();
|
||||
console.log('📱 Status After Scheduling:', afterStatus);
|
||||
|
||||
// The plugin will handle:
|
||||
// - Exact alarms if permission granted
|
||||
// - Windowed alarms (±10m) if permission denied
|
||||
// - Graceful degradation based on Android version
|
||||
// - Appropriate user feedback and guidance
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Fallback scenarios demonstration failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Monitor exact alarm changes
|
||||
*/
|
||||
async function monitorExactAlarmChanges() {
|
||||
try {
|
||||
console.log('Monitoring exact alarm changes...');
|
||||
|
||||
// Configure fallback
|
||||
await configureAndroidExactAlarmFallback();
|
||||
|
||||
// Monitor changes over time
|
||||
const monitorInterval = setInterval(async () => {
|
||||
try {
|
||||
const status = await DailyNotification.getExactAlarmStatus();
|
||||
console.log('📱 Exact Alarm Status:', status);
|
||||
|
||||
if (status.enabled && !status.canSchedule) {
|
||||
console.log('⚠️ Exact alarms enabled but cannot schedule - may need app restart');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Monitoring error:', error);
|
||||
}
|
||||
}, 30000); // Check every 30 seconds
|
||||
|
||||
// Stop monitoring after 5 minutes
|
||||
setTimeout(() => {
|
||||
clearInterval(monitorInterval);
|
||||
console.log('✅ Exact alarm monitoring completed');
|
||||
}, 300000);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Exact alarm monitoring failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Handle permission denial gracefully
|
||||
*/
|
||||
async function handlePermissionDenialGracefully() {
|
||||
try {
|
||||
console.log('Handling permission denial gracefully...');
|
||||
|
||||
// Configure fallback
|
||||
await configureAndroidExactAlarmFallback();
|
||||
|
||||
// Check status
|
||||
const status = await DailyNotification.getExactAlarmStatus();
|
||||
|
||||
if (!status.enabled) {
|
||||
console.log('⚠️ Exact alarms not enabled, using windowed fallback');
|
||||
|
||||
// Schedule with fallback
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: 'https://api.example.com/daily-content',
|
||||
time: '09:00',
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready (windowed fallback)'
|
||||
});
|
||||
|
||||
console.log('✅ Notification scheduled with windowed fallback');
|
||||
|
||||
// Provide user guidance
|
||||
console.log('💡 To enable exact alarms:');
|
||||
console.log(' 1. Call requestExactAlarmPermission()');
|
||||
console.log(' 2. Or call openExactAlarmSettings()');
|
||||
console.log(' 3. Enable exact alarms in settings');
|
||||
|
||||
} else {
|
||||
console.log('✅ Exact alarms enabled, scheduling normally');
|
||||
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: 'https://api.example.com/daily-content',
|
||||
time: '09:00',
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready (exact timing)'
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Permission denial handling failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Export examples for use
|
||||
export {
|
||||
configureAndroidExactAlarmFallback,
|
||||
checkExactAlarmStatus,
|
||||
requestExactAlarmPermission,
|
||||
openExactAlarmSettings,
|
||||
scheduleWithFallbackHandling,
|
||||
checkRebootRecoveryStatus,
|
||||
demonstrateFallbackScenarios,
|
||||
monitorExactAlarmChanges,
|
||||
handlePermissionDenialGracefully
|
||||
};
|
||||
Reference in New Issue
Block a user