Android 12 广播接收器 onReceive intent.getExtras 始终为 null

Android 12 BroadcastReceiver onReceive intent.getExtras allways null

我正在尝试构建一个 stackview 小部件,它应该在滑动时显示不同的数据。 到目前为止一切正常,但是当我想在小部件中接收被点击的卡片的索引时,我总是得到一个额外的或 'null' 的动作。 我已经尝试了几种变通方法,但其中 none 个在我的应用程序中有效。 我还设置了一个全新的应用程序,只是为了让这项工作完全独立。但在这里我得到了完全相同的行为。

我尝试通过索引的几种解决方法:

我观察到,getViewAt 函数在被生成的 exampleData 列表中的正确位置调用之前被多次调用,位置 (p0) 为“0”... 但我不知道这是否会导致单击卡片时 onReceive 函数中出现空值。

这是我的编码:

Manifest.xml

<service android:name=".ExampleWidgetService"
        android:permission="android.permission.BIND_REMOTEVIEWS">
</service>

WidgetLayout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <StackView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/stackview">
    </StackView>

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/empty_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:text="empty"
        android:textSize="20sp" />
</FrameLayout>

WidgetItemEntry

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:text="Icon"
        android:id="@+id/newwidgetentry">

    </TextView>
</LinearLayout>

AppWidgetProvider

package com.example.widgettest
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.RemoteViews
import android.widget.Toast

/**
 * Implementation of App Widget functionality.
 */
public const val clickedCategory: String = "com.example.myapplication.buttonpress.id"
public const val stackviewButton = "stackviewbutton"

class newwidget : AppWidgetProvider() {
    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray,
    ) {
        // There may be multiple widgets active, so update all of them
        for (appWidgetId in appWidgetIds) {

        /*    val widgetText = context.getString(R.string.appwidget_text)
            // Construct the RemoteViews object
            val views = RemoteViews(context.packageName, R.layout.newwidget)
            views.setTextViewText(R.id.newwidgetentry, widgetText)*/

            val serviceIntent: Intent = Intent(context, ExampleWidgetService::class.java).apply{
                putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
                data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
            }
            val views = RemoteViews(
                context.packageName,
                R.layout.newwidget
            ).apply{
                setRemoteAdapter(R.id.stackview, serviceIntent)
                setEmptyView(R.id.stackview, R.id.empty_view)
            }

            val toastIntent = Intent(context, newwidget::class.java).run {
                action= stackviewButton
                putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
                data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
                PendingIntent.getBroadcast(context,
                    0,
                    this,
                    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
            }
            views.setPendingIntentTemplate(R.id.stackview, toastIntent)


            // Instruct the widget manager to update the widget
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
        super.onUpdate(context, appWidgetManager, appWidgetIds)
    }

    override fun onEnabled(context: Context) {
        // Enter relevant functionality for when the first widget is created
    }

    override fun onDisabled(context: Context) {
        // Enter relevant functionality for when the last widget is disabled
    }

    override fun onReceive(context: Context?, intent: Intent?) {


   var clickedCat2 = intent?.getBundleExtra("test")?.getInt(clickedCategory,-1)
             /*val clickedCat2: Int? = intent?.getIntExtra(clickedCategory, -1)*/

        Toast.makeText(context, "onreceive +$clickedCat2" , Toast.LENGTH_SHORT).show();
        if (stackviewButton.equals(intent?.getAction())){
            val clickedCat: Int? = intent?.getIntExtra(clickedCategory, 0)
            Toast.makeText(context, "widgetbuttonpressed id + $clickedCat", Toast.LENGTH_SHORT).show();
        }
        super.onReceive(context, intent)
    }
}

RemoteView 工厂

package com.example.widgettest

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.widget.RemoteViews
import android.widget.RemoteViewsService
import com.google.gson.Gson

private const val REMOTE_VIEW_COUNT: Int = 2

data class WidgetItem(
    val id: String,
)

class ExampleWidgetService : RemoteViewsService() {

    override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
        return ExampleWidgetService1(this.applicationContext, intent)
    }
}

class ExampleWidgetService1(private val context: Context, intent: Intent) :
    RemoteViewsService.RemoteViewsFactory {

    private lateinit var exampleData: List<WidgetItem>

    override fun onCreate() {
        exampleData = List(REMOTE_VIEW_COUNT) { index -> WidgetItem("$index!") }
        val test = 123
    }

    override fun onDataSetChanged() {
    }

    override fun onDestroy() {
    }

    override fun getCount(): Int {
        return exampleData.size
    }

    override fun getItemId(p0: Int): Long {
        return p0.toLong()
    }

    override fun getViewAt(p0: Int): RemoteViews {

        return RemoteViews(context!!.packageName, R.layout.newwidgetentry).apply {

            setTextViewText(R.id.newwidgetentry, exampleData[p0].id)

       

     val fillIntent = Intent().apply {
                    Bundle().also { extras ->
                        extras.putInt(clickedCategory, p0)
                        putExtra("test",extras)
                    }
                }

  /*val fillIntent = Intent().apply {
                putExtra(clickedCategory, p0)
            }*/
            setOnClickFillInIntent(R.id.newwidgetentry, fillIntent)
        }
    }

    override fun getLoadingView(): RemoteViews? {
        return null
    }

    override fun getViewTypeCount(): Int {
        return 1
    }


    override fun hasStableIds(): Boolean {
        return true
    }

}

非常感谢大家的帮助!!! 提前谢谢你!!

我遇到了同样的问题, 我终于解决了这个问题!

只需将 setPendingIntentTemplate 的待处理意图标志更改为 PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE