jiichan.com

PROGRAMMING

Android Kotlin
javascript
PHP
Java

ViewMosel を利用できないクラスで Room を使う

alarmManager と通知を組み合わせたアプリを作っているときに、BroadcastReceiver を継承したクラスでデータベースを使いたいと思いました。
receiver の登録は AndroidManifest で行っていますが登録できるのはクラス名だけです。
ViewModel をコンストラクタでと思いましたができませんでした。 そこで、BroadcastReceiver を継承したクラスの中で ViewModel を経由せずに直接データベースにアクセスするようにしました。(2025.07.17)

≪開発環境≫
windows11
andriod studio Ladybug

AndroidManifest

AndroidManifest で receiver を登録しました。


            :
            :
    </activity>
        <receiver
            android:name=".utility.MyReceiver"
            android:exported="false">
        </receiver>
    </application>
</manifest>           

Application

既に Application 内でインスタンス済みの Database を使います。


class SampleApplication : Application() {
    val database by lazy { SampleDatabase.getInstance(this) }
}

クラスの中で ViewModel を使わずに直接データベースにアクセスする

BroadcastReceiver 内で直接データを得ることができました。


class MyReceiver : BroadcastReceiver() {
    private val job = Job()
    private val coroutineScope = CoroutineScope(Dispatchers.Main + job) // UIスレッドで実行

    override fun onReceive(context: Context, intent: Intent) {
        // データベースアクセスはコルーチン内で行う
        coroutineScope.launch {
            try {
                // viewModel を使用できないので application を参照し
                val application = (context.applicationContext as SampleApplication)
                // application でインスタンス済みの database を使って dao のインスタンスを生成
                val dao = application.database.sampleDao()
                // データを得る
                val countStr = dao.getTodayCount(20250717).toString()

                // 通知を作成と表示
                val myNotification = MyNotification(context)
                myNotification.showNotification(countStr)
            } finally {
                job.cancel()
                coroutineScope.cancel()
            }
        }
    }
}

まとめ

簡単には解決できませんでしたが、しつこく調べていると必ず解決すると強く感じました。