Browse Source

fix(android): resolve DailyNotification plugin registration issue

- Move plugin registration before super.onCreate() in MainActivity
- Create dedicated dailynotification module for proper plugin structure
- Add comprehensive logging for plugin registration debugging
- Update Vue components with enhanced plugin detection and logging
- Fix TypeScript errors in HomeView.vue for proper build

The plugin was not being loaded because registration happened after
BridgeActivity initialization. Moving registerPlugin() before super.onCreate()
ensures the plugin is available when Capacitor loads plugins.

Resolves simplified status dialog issue by ensuring native plugin
is properly registered and accessible to JavaScript layer.
master
Matthew Raymer 5 days ago
parent
commit
64b65f8a94
  1. 5
      test-apps/daily-notification-test/android/app/build.gradle
  2. 21
      test-apps/daily-notification-test/android/app/src/main/java/com/timesafari/dailynotification/test/MainActivity.java
  3. 22
      test-apps/daily-notification-test/android/dailynotification/build.gradle
  4. 6
      test-apps/daily-notification-test/android/dailynotification/src/main/assets/capacitor.plugins.json
  5. 3
      test-apps/daily-notification-test/android/dailynotification/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.java
  6. 1
      test-apps/daily-notification-test/android/settings.gradle
  7. 49
      test-apps/daily-notification-test/src/components/cards/StatusCard.vue
  8. 180
      test-apps/daily-notification-test/src/views/HomeView.vue

5
test-apps/daily-notification-test/android/app/build.gradle

@ -16,6 +16,10 @@ android {
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
} }
} }
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
@ -40,6 +44,7 @@ dependencies {
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
implementation project(':capacitor-cordova-android-plugins') implementation project(':capacitor-cordova-android-plugins')
implementation project(':dailynotification')
} }
apply from: 'capacitor.build.gradle' apply from: 'capacitor.build.gradle'

21
test-apps/daily-notification-test/android/app/src/main/java/com/timesafari/dailynotification/test/MainActivity.java

@ -1,5 +1,24 @@
package com.timesafari.dailynotification.test; package com.timesafari.dailynotification.test;
import com.getcapacitor.BridgeActivity; import com.getcapacitor.BridgeActivity;
import com.timesafari.dailynotification.DailyNotificationPlugin;
public class MainActivity extends BridgeActivity {} public class MainActivity extends BridgeActivity {
@Override
public void onCreate(android.os.Bundle savedInstanceState) {
android.util.Log.d("MainActivity", "MainActivity.onCreate() called - START");
// Register the DailyNotification plugin BEFORE calling super.onCreate()
android.util.Log.d("MainActivity", "Registering DailyNotification plugin...");
try {
registerPlugin(DailyNotificationPlugin.class);
android.util.Log.d("MainActivity", "DailyNotification plugin registered successfully");
} catch (Exception e) {
android.util.Log.e("MainActivity", "Failed to register DailyNotification plugin", e);
}
super.onCreate(savedInstanceState);
android.util.Log.d("MainActivity", "MainActivity.onCreate() - after super.onCreate()");
android.util.Log.d("MainActivity", "MainActivity.onCreate() called - END");
}
}

22
test-apps/daily-notification-test/android/dailynotification/build.gradle

@ -0,0 +1,22 @@
apply plugin: 'com.android.library'
android {
namespace "com.timesafari.dailynotification"
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
implementation project(':capacitor-android')
}

6
test-apps/daily-notification-test/android/dailynotification/src/main/assets/capacitor.plugins.json

@ -0,0 +1,6 @@
[
{
"name": "DailyNotification",
"classpath": "com.timesafari.dailynotification.DailyNotificationPlugin"
}
]

3
test-apps/daily-notification-test/android/app/src/main/java/com/timesafari/dailynotification/test/DailyNotificationPlugin.java → test-apps/daily-notification-test/android/dailynotification/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.java

@ -1,4 +1,4 @@
package com.timesafari.dailynotification.test; package com.timesafari.dailynotification;
import com.getcapacitor.JSObject; import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin; import com.getcapacitor.Plugin;
@ -13,6 +13,7 @@ public class DailyNotificationPlugin extends Plugin {
public void load() { public void load() {
super.load(); super.load();
// Log that the plugin has loaded // Log that the plugin has loaded
android.util.Log.d("DailyNotificationPlugin", "Plugin load() method called");
System.out.println("DN|PLUGIN_LOAD_START"); System.out.println("DN|PLUGIN_LOAD_START");
} }

1
test-apps/daily-notification-test/android/settings.gradle

@ -1,4 +1,5 @@
include ':app' include ':app'
include ':dailynotification'
include ':capacitor-cordova-android-plugins' include ':capacitor-cordova-android-plugins'
project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/')

49
test-apps/daily-notification-test/src/components/cards/StatusCard.vue

@ -36,28 +36,39 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { Vue, Component, toNative } from 'vue-facing-decorator' import { ref } from 'vue'
type StatusItem = { label: string; value: string; status: string } interface StatusItem {
label: string
@Component value: string
class StatusCard extends Vue { status: string
isRefreshing = false }
statusItems: StatusItem[] = []
interface Props {
async refreshStatus() { status?: StatusItem[]
this.isRefreshing = true }
try {
// TODO: real fetch const props = defineProps<Props>()
this.statusItems = [{ label: 'Plugin', value: 'OK', status: 'success' }]
} finally { const emit = defineEmits<{
this.isRefreshing = false refresh: []
} }>()
const isRefreshing = ref(false)
const refreshStatus = async (): Promise<void> => {
console.log('🔄 CLICK: StatusCard Refresh - METHOD CALLED!')
isRefreshing.value = true
try {
emit('refresh')
} finally {
isRefreshing.value = false
} }
} }
export default toNative(StatusCard) // Use the status from props or default to empty
const statusItems = ref<StatusItem[]>(props.status || [])
</script> </script>
<style scoped> <style scoped>

180
test-apps/daily-notification-test/src/views/HomeView.vue

@ -2,7 +2,7 @@
/** /**
* Home View - Main Dashboard * Home View - Main Dashboard
* *
* Platform-neutral home view with quick actions * Platform-neutral home view with quick actions and plugin diagnostics
* *
* @author Matthew Raymer * @author Matthew Raymer
* @version 1.0.0 * @version 1.0.0
@ -17,7 +17,7 @@
🔔 Daily Notification Test 🔔 Daily Notification Test
</h1> </h1>
<p class="welcome-subtitle"> <p class="welcome-subtitle">
Vue 3 + vue-facing-decorator + Capacitor Vue 3 + Capacitor + DailyNotification Plugin
</p> </p>
<div class="platform-info"> <div class="platform-info">
<span class="platform-badge" :class="platformClass"> <span class="platform-badge" :class="platformClass">
@ -99,36 +99,156 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { Vue, Component, toNative } from 'vue-facing-decorator' import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
@Component import { useAppStore } from '@/stores/app'
class HomeView extends Vue { import ActionCard from '@/components/cards/ActionCard.vue'
get platformName() { return 'Daily Notification Test' } import StatusCard from '@/components/cards/StatusCard.vue'
get platformClass() { return 'platform-generic' }
get statusText() { return 'OK' } const router = useRouter()
get statusClass() { return 'status-ok' } const appStore = useAppStore()
isScheduling = false const isScheduling = ref(false)
isCheckingStatus = false const isCheckingStatus = ref(false)
systemStatus: Record<string, unknown> | null = null
const platformName = computed(() => {
navigateToSchedule() {} const platform = appStore.platform
navigateToNotifications() {} return platform.charAt(0).toUpperCase() + platform.slice(1)
navigateToHistory() {} })
navigateToLogs() {}
navigateToSettings() {} const platformClass = computed(() => `platform-${appStore.platform}`)
async checkSystemStatus() { const statusClass = computed(() => {
this.isCheckingStatus = true const status = appStore.notificationStatus
try { this.systemStatus = { ok: true, ts: Date.now() } } if (!status) return 'unknown'
finally { this.isCheckingStatus = false } if (status.canScheduleNow) return 'ready'
return 'not-ready'
})
const statusText = computed(() => {
const status = appStore.notificationStatus
if (!status) return 'Unknown'
if (status.canScheduleNow) return 'Ready'
return 'Not Ready'
})
const systemStatus = computed(() => {
const status = appStore.notificationStatus
if (!status) {
return [
{ label: 'Platform', value: platformName.value, status: 'info' },
{ label: 'Plugin', value: 'Not Available', status: 'error' }
]
}
return [
{ label: 'Platform', value: platformName.value, status: 'info' },
{ label: 'Plugin', value: 'Available', status: 'success' },
{ label: 'Can Schedule', value: status.canScheduleNow ? 'Yes' : 'No', status: status.canScheduleNow ? 'success' : 'warning' },
{ label: 'Next Scheduled', value: status.nextScheduledAt ? new Date(status.nextScheduledAt).toLocaleTimeString() : 'None', status: 'info' }
]
})
const navigateToSchedule = (): void => {
console.log('🔄 CLICK: Navigate to Schedule')
router.push('/schedule')
}
const navigateToNotifications = (): void => {
console.log('🔄 CLICK: Navigate to Notifications')
router.push('/notifications')
}
const navigateToHistory = (): void => {
console.log('🔄 CLICK: Navigate to History')
router.push('/history')
}
const navigateToLogs = (): void => {
console.log('🔄 CLICK: Navigate to Logs')
router.push('/logs')
}
const navigateToSettings = (): void => {
console.log('🔄 CLICK: Navigate to Settings')
router.push('/settings')
}
const checkSystemStatus = async (): Promise<void> => {
console.log('🔄 CLICK: Check System Status')
isCheckingStatus.value = true
try {
// This will be handled by the app store
console.log('🔧 Checking notification status...')
// For now, just log that we're checking
console.log('🔧 Status check completed (placeholder)')
} finally {
isCheckingStatus.value = false
}
}
const refreshSystemStatus = async (): Promise<void> => {
console.log('🔄 CLICK: Refresh System Status')
await checkSystemStatus()
}
const runPluginDiagnostics = async (): Promise<void> => {
console.log('🔄 CLICK: Plugin Diagnostics - METHOD CALLED!')
try {
console.log('🔧 Running plugin diagnostics...')
console.log('🔧 BUTTON CLICKED - METHOD CALLED!')
// Check if we're on a native platform
const { Capacitor } = await import('@capacitor/core')
const platform = Capacitor.getPlatform()
const isNative = Capacitor.isNativePlatform()
console.log('📱 Platform:', platform)
console.log('🔧 Native Platform:', isNative)
if (isNative) {
// Try multiple ways to access the plugin
const plugin = (window as any).DailyNotification ||
(window as any).Capacitor?.Plugins?.DailyNotification ||
(window as any).Capacitor?.Plugins?.['DailyNotification']
console.log('🔍 Plugin detection debug:')
console.log(' - window.DailyNotification:', (window as any).DailyNotification)
console.log(' - Capacitor.Plugins:', (window as any).Capacitor?.Plugins)
console.log(' - Available plugins:', Object.keys((window as any).Capacitor?.Plugins || {}))
if (plugin) {
console.log('✅ DailyNotification plugin available')
// Test the checkStatus method
try {
const status = await plugin.checkStatus()
console.log('📊 Plugin status check result:', status)
alert(`✅ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus: ${JSON.stringify(status, null, 2)}`)
} catch (error) {
console.error('❌ Plugin status check failed:', error)
alert(`⚠️ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus Check Failed: ${error}`)
}
} else {
console.warn('⚠️ DailyNotification plugin not available')
alert(`❌ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: No\nAvailable Plugins: ${Object.keys((window as any).Capacitor?.Plugins || {}).join(', ')}`)
}
} else {
console.log('🌐 Running in web mode - plugin not available')
alert(`ℹ️ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nNative Platform: No\nPlugin Available: No (Web mode)`)
}
} catch (error) {
console.error('❌ Plugin diagnostics failed:', error)
alert(`❌ Plugin Diagnostics Failed!\n\nError: ${error}`)
} }
async refreshSystemStatus() { await this.checkSystemStatus() }
async runPluginDiagnostics() {}
openConsole() {}
} }
export default toNative(HomeView)
const openConsole = (): void => {
console.log('🔄 CLICK: Open Console - METHOD CALLED!')
console.log('📖 Console opened - check browser developer tools for detailed logs')
alert('📖 Console Logs\n\nOpen your browser\'s Developer Tools (F12) and check the Console tab for detailed diagnostic information.')
}
</script> </script>
<style scoped> <style scoped>

Loading…
Cancel
Save