Android 12 BroadcastReceiver onReceive Intent.getExtras 始终为 null
我正在尝试构建一个 stackview 小部件,它在滑动时应该显示不同的数据。 到目前为止,一切正常,但是当我想接收小部件中单击的卡的索引时,我总是得到一个额外的或“null”的操作。 我已经尝试了几种解决方法,但没有一个在我的应用程序中起作用。 我还设置了一个全新的应用程序,只是为了使这项工作完全隔离。但在这里我得到了完全相同的行为。
我尝试传递索引的几个解决方法:
- 滥用意图操作(就像这里 Android 7 BroadcastReceiver onReceive Intent.getExtras 缺少数据)
- 创建捆绑包(putInt,putString)(同时使用 getBundleExtra 接收)(如下所示待处理的 getbroadcast 丢失了可分包数据)
- putExtra(clickedCategory, test)(使用 getIntExtra( 接收时) clickedCategory, 0))
我观察到, getViewAt 函数被多次调用,位置(p0)为在被生成的 exampleData 列表中的正确位置调用之前为“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 Factory
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
}
}
我真的很感谢各种帮助! 已经预先感谢您了!
I'm trying to build a stackview widget, which should display differnt data when swiping through it.
So far everything is working, but when I want to receive the index of the clicked card in the widget, I always get an extra or action of 'null'.
I already have tried several workarounds, but none of them is working in my application.
I also set up a complete new application for only making this work completely isolated. But here I get the exact same behaviour.
Several workarounds I tried to pass the index:
- misusing the intent action (like here Android 7 BroadcastReceiver onReceive intent.getExtras missing data)
- creating a bundle (putInt, putString) (while receiving using getBundleExtra) (like here Pendingintent getbroadcast lost parcelable data)
- putExtra(clickedCategory, test) (while receiving using getIntExtra(clickedCategory, 0))
What I observed is, that the getViewAt funtion is called several times with a position(p0) of "0" before it gets called by the right positions from the generated exampleData List...
But I don't know if this causes the Nulls in the onReceive function, when an card is clicked.
Here is my coding:
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 Factory
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
}
}
I really appreciate everykind of help!!!
Thank you already in advance!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我也有同样的问题
终于我解决了这个问题!
只需将
setPendingIntentTemplate
的挂起意图标志更改为PendingIntent.FLAG_UPDATE_CURRENT 或 PendingIntent.FLAG_MUTABLE
即可。I've the same issue,
finally I resolve this issue!
Just change
setPendingIntentTemplate
's pending intent flags toPendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
.