簡単にウィジェットを表示したり、アプリから更新する方法を知りたい人向け。

 ウィジェットを表示するためには、レイアウトファイルとかを作成したり、マニフェストファイルを修正する必要があるが、Android Studioだと基本的なことはすべてやってくれるので、ほぼ何もしなくてもいい。具体的にはプロジェクトのツリービューの右クリック→NewからWidgetを選択するとウィザードが開くので入力していくだけ。
 まずはレイアウトファイルで表示する部品などを登録しておく。使用できるレイアウトや部品については制限があるので注意。
 基本的な仕組みはこんな感じ。ウィジェットを新規に表示させたり、更新時間になるとonUpdateが実行される。その後、updateAppWidgetが呼ばれる。こうなっているのは、複数のウィジェットを表示させることができるからで、複数のウィジェットに同時に何か変更を加える場合にはonUpdateで、個別のウィジェットで表示を変えたい場合にはupdateAppWidgetのほうでいろいろやる。

override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
    // There may be multiple widgets active, so update all of them
    for (appWidgetId in appWidgetIds) {
        updateAppWidget(context, appWidgetManager, appWidgetId)
    }
}
companion object {
    internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
//ビューを取得して文字を設定する val views = RemoteViews(context.packageName, R.layout.test_widget) views.setTextViewText(R.id.tvHeight, "height") views.setTextViewText(R.id.tvWeight, "weight")
//ウィジェットIDとviewを渡して設定する appWidgetManager.updateAppWidget(appWidgetId, views) } }

 アプリからウィジェットをいじる場合には、下記のようなコードを実行することで変更することができる


//AppWidgetManagerから、このウィジェットが登録されているウィジェットIDをすべて取得する
//それぞれについてウィジェットの中身を更新する
val manager: AppWidgetManager = AppWidgetManager.getInstance(this)
for (appWidgetID: Int in manager.getAppWidgetIds(ComponentName(this, BMILogWidget::class.java)))
 {
    val views = RemoteViews(this.packageName, R.layout.bmilog_widget)
    views.setTextViewText(R.id.tvHeight, "ぬぬぬ")

    manager.updateAppWidget(appWidgetID, views)
}
 他のクラス以外からも上記でウィジェットの中身を触れるが、自動的に作成されるAppWidgetProviderの継承クラス(onUpdate、updateAppWidgetのメソッドのあるクラス)に実装したほうがいいと思う。
 こんな感じで実装すればデータの更新はすべてproviderクラスのほうで行われるので見通しがよくなる。

companion object {
    internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
                                     appWidgetId: Int) {
    }
    internal fun setText(context: Context, text: String) {
        val manager: AppWidgetManager = AppWidgetManager.getInstance(context)
        for (appWidgetID: Int in manager.getAppWidgetIds(ComponentName(context, BMILogWidget::class.java))) {
            val views = RemoteViews(context.packageName, R.layout.test_widget)
            views.setTextViewText(R.id.tvHeight, text)

            manager.updateAppWidget(appWidgetID, views)
        }
    }
}