Android widget不响应触摸

yacmzcpb  于 2023-06-20  发布在  Android
关注(0)|答案(2)|浏览(217)

我正在尝试一些非常简单的代码来获得Android小部件,但没有运气。我到处都找遍了,还没有找到一个好的答案。
我所希望的(目前)是在触摸小部件时增加一个计数器并显示当前值。
这是我的AppWidgetProvider:

  1. public class WordWidget extends AppWidgetProvider
  2. {
  3. Integer touchCounter = 0;
  4. @Override
  5. public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
  6. {
  7. //This is run when a new widget is added or when the update period expires.
  8. Log.v("wotd", "Updating " + appWidgetIds.length + " widgets");
  9. for(int x = 0; x < appWidgetIds.length; x++)
  10. {
  11. Integer thisWidgetId = appWidgetIds[x];
  12. RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
  13. remoteViews.setTextViewText(R.id.mainText, touchCounter.toString());
  14. Intent widgetIntent = new Intent(context, WordWidget.class);
  15. widgetIntent.setAction("UPDATE_NUMBER");
  16. PendingIntent widgetPendingIntent = PendingIntent.getBroadcast(context, 0, widgetIntent, 0);
  17. remoteViews.setOnClickPendingIntent(R.id.widgetLinearLayout, widgetPendingIntent);
  18. appWidgetManager.updateAppWidget(thisWidgetId, remoteViews);
  19. }
  20. }
  21. @Override
  22. public void onReceive(Context context, Intent intent)
  23. {
  24. Log.v("wotd", "In onReceive with intent=" + intent.toString());
  25. if (intent.getAction().equals("UPDATE_NUMBER"))
  26. {
  27. Log.v("wotd", "In UPDATE_NUMBER");
  28. touchCounter++;
  29. RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
  30. remoteViews.setTextViewText(R.id.mainText, touchCounter.toString());
  31. } else
  32. {
  33. Log.v("wotd", "In ELSE... going on to super.onReceive()");
  34. super.onReceive(context, intent);
  35. }
  36. }
  37. }

这是我的一部分清单:

  1. <application
  2. android:icon="@drawable/ic_launcher"
  3. android:label="@string/app_name" >
  4. <receiver
  5. android:icon="@drawable/ic_launcher"
  6. android:name="com.example.mywidget.WordWidget"
  7. android:label="@string/app_name">
  8. <intent-filter>
  9. <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
  10. <action android:name="UPDATE_NUMBER" />
  11. </intent-filter>
  12. <meta-data
  13. android:name="android.appwidget.provider"
  14. android:resource="@xml/widgetinfo" />
  15. </receiver>
  16. </application>

日志显示onReceive()在被放置在主屏幕上之后立即被调用,并且在被触摸之后,但是数量从未增加。我不完全理解小部件是如何工作的,但是它们在onUpdate()之后被杀死了吗?所以要做到这一点,我必须使用某种持久存储?
此外,如果我现在添加另一个小部件,即使我只是触摸一个,它们也会显示相同的值和增量。有没有一种方法可以让每个小部件都有自己的计数器?
谢谢!

qvsjd97n

qvsjd97n1#

其实你已经回答了你的问题。但让我们澄清一些事情:
A. AppWidgets只要在主屏幕上就不会被杀死。但它们不属于你。它们在home应用程序的进程中运行。更具体地说,他们的视图在主应用程序的进程中运行,这就是为什么你看到你的小部件,但它不做你所期望的,这就是为什么我们使用RemoteViews而不是Views来更新它们。
另一方面,一旦onReceive方法完成,AppWidgetProviders(在您的情况下是WordWidget类)就会被销毁。每次调用onReceive方法时,它们中的所有变量都将重新初始化。这就是为什么你的人数从未增加。AppWidgetProvider的作用是更新小部件的RemoteViews,并通知应用程序注册的广播已经到达。
AppWidgetProvider的onUpdate方法为您提供了一个Array,其中包含必须更新的小部件Id。这是您可以用来获取小部件示例数量及其ID的唯一代码点。由于RemoteViews,无法从小部件的Views中获取一些有用的值(例如,您无法从TextView中读取计数器值),因此您必须使用提供的信息并DO persist每个小部件ID的计数器值。当下一个onUpdate被调用时,您从存储中读取值,增加它,用新值更新小部件,然后存储新值。
D.如果你的widget在需要更新的时候需要做很多事情或者很慢的事情(比如网络),你应该考虑使用一个服务。但在您的情况下(为了增加一个数字),只要您将计数器持久化在持久存储器或其他地方,您的方法就很好。
最后,我注意到在onReceive覆盖中,只有在没有收到“UPDATE_NUMBER”操作时,才调用“super.onReceive”。这不是一个好的做法,除非有一个很好的理由(那是另一个故事)总是调用super.onReceive作为覆盖中的第一个或最后一个命令。
希望这对你有帮助…

pinkon5k

pinkon5k2#

我有机会创建一个在触摸时有振动的AppWidget。以下是我的可行代码片段(只需修改活动名称和viewIds):

  1. class MyWidgetProvider : AppWidgetProvider() {
  2. companion object {
  3. const val TOUCH_ACTION = "com.tekelili.poe.TOUCH_ACTION"
  4. const val EXTRA_ITEM = "com.tekelili.poe.t.EXTRA_ITEM"
  5. }
  6. override fun onUpdate(context: Context,appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
  7. for (appWidgetId in appWidgetIds) {
  8. updateMyAppWidget(context, appWidgetManager, appWidgetId)
  9. }
  10. }
  11. override fun onReceive(context: Context, intent: Intent) {
  12. if (intent.action == TOUCH_ACTION) {
  13. val index: Int = intent.getIntExtra(EXTRA_ITEM, 0)
  14. val myIntent = Intent(context, MockActivity::class.java)
  15. .putExtra("INDEX", index.toString())
  16. .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
  17. (context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator).vibrate(100)
  18. context.startActivity(myIntent)
  19. }
  20. super.onReceive(context, intent)
  21. }
  22. internal fun updateMyAppWidget(context: Context, appWidgetManager: AppWidgetManager,appWidgetId: Int) {
  23. val views = RemoteViews(context.packageName, R.layout.mock_layout_widget)
  24. views.setOnClickPendingIntent(R.id.mock_textview,
  25. getPendingIntent(context, appWidgetId, 123))
  26. appWidgetManager.updateAppWidget(appWidgetId, views)
  27. }
  28. private fun getPendingIntent(context: Context, appWidgetId: Int, value: Int): PendingIntent {
  29. val touchPendingIntent: PendingIntent = Intent(context, MyWidgetProvider::class.java).run {
  30. action = TOUCH_ACTION
  31. putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
  32. putExtra(EXTRA_ITEM, value)
  33. data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
  34. PendingIntent.getBroadcast(context, 0, this, PendingIntent.FLAG_UPDATE_CURRENT)
  35. }
  36. return touchPendingIntent
  37. }

}

展开查看全部

相关问题