将数据从小部件传递到应用程序

Posted

技术标签:

【中文标题】将数据从小部件传递到应用程序【英文标题】:Passing data from widget to app 【发布时间】:2012-07-07 18:52:03 【问题描述】:

我正在为我的应用程序开发一个小部件,我想将特定数据从小部件传递到应用程序。用户可以添加多个版本的小部件,我需要检测它来自哪个小部件,以便我可以在应用中显示特定信息。

到目前为止我所做的工作,但前提是我完全退出我的应用程序(反复按下后退按钮),否则它似乎没有检测到正在传递的数据。

这是我必须的代码:

public class WidgetProvider extends AppWidgetProvider  

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 

        final int N = appWidgetIds.length;

        for (int i=0; i<N; i++) 
            UpdateWidget(context, appWidgetManager, appWidgetIds[i]);
    

    public static void UpdateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId)
    
        Intent intent = new Intent(context, Main.class);
        final Bundle bun = new Bundle();
        bun.putInt("widgetId", appWidgetId);
        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtras(bun);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
        views.setOnClickPendingIntent(R.id.widgetText, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetId, views);
    

更新

感谢 Tal Kanel。我的应用程序中有一个ActionBar,并遵循 Google 的指导方针,我在 onOptionsItemSelected 中有此代码:

if (item.getItemId() == android.R.id.home) 
          final Intent intent = new Intent(activity, Main.class);
          intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
          startActivity(intent);
          return true;
     

如果我单击ActionBar 中的“返回”按钮,然后最小化我的应用程序并单击小部件,此代码始终为空:

    if (getIntent().getExtras() != null)
    

    

更新 2

实际上,只是回到我的应用程序中的主要活动会导致getExtras() 为空。我的应用小部件中有此代码,它不会向应用传递任何额外内容:

    PendingIntent piMain = PendingIntent.getActivity(context, appWidgetId, new Intent(context, Main.class), PendingIntent.FLAG_UPDATE_CURRENT);

    rv.setOnClickPendingIntent(R.id.widgetTitle, piMain);

如果我在我的小部件中单击该部分,然后返回并单击我的小部件中应该传递额外内容的部分,getExtras() 始终为空。

【问题讨论】:

【参考方案1】:

首先 - 当您按下返回直到返回主屏幕时,您的应用程序并没有真正关闭。只是在此阶段不存在您的应用程序中的任何活动。 我认为知道这一点非常重要,以防万一你没有......

关于您的问题: 您正在尝试使用它定义的 FLAG_ACTIVITY_CLEAR_TOP 从小部件启动活动:

如果设置了,并且正在启动的 Activity 已经在当前任务中运行,那么不会启动该 Activity 的新实例,而是关闭它之上的所有其他 Activity,并且此 Intent 将被传递到(现在在顶部)作为新 Intent 的旧活动。

这意味着如果您的 Main 活动已经在前台运行,那么当您从小部件启动活动时 - 此 Main 活动之上的所有其他活动将从堆栈中删除,并且 Main 将恢复并进入 Activity.onNewIntent(intent) 回调。

这就是您看不到数据的原因 - 因为活动不会以新意图重新启动,而只会以您发送的新意图进入 onNewIntent(intent)。

我敢肯定,如果您在 onNewIntent(intent) 方法中设置一个断点 - 您会看到您发送的意图已传递到那里,以及所有额外的数据。

您的代码的另一个问题:检查 Intent.putExtras(boundle) 方法的定义:

向意图添加一组扩展数据。键必须包含包前缀,例如应用程序 com.android.contacts 将使用“com.android.contacts.ShowAll”之类的名称。

您似乎没有按照规则调用您的密钥前缀。这就是它为空的原因。

希望对你有所帮助。

【讨论】:

感谢您的回复。这是我创建的第一个应用小部件,所以我还在搞清楚一切。你是对的,onNewItent 被击中了,所以我添加了我的代码来检查那里的额外内容,它似乎可以工作,但只有在我第二次点击小部件之后。 @KrisB:这正是假设发生的事情 - 如果活动不在堆栈中(第一次),那么以“常规方式”接收的数据 - 通过 onCreate() 和 getIntent( ),而在其他时候(当 Activity 已经在堆栈中时),您将收到 Intent throw the onNewIntent() 你是对的,这正是它的工作方式。我检查了onCreateonNewIntent 中的额外内容,问题似乎是当我使用if (getIntent().getExtras() != null) 时,有时getExtras()null。从小部件单击时,我希望 getExtras() 永远不会是 null 查看我添加到 OP 的代码。我的小部件的一部分没有传递任何额外内容,而主要部分则传递。如果我单击未传递任何附加信息的部分,然后返回小部件并单击传递任何附加信息的部分,getExtras() 始终为空。 @IgorG.:如果您使用 FLAG_ACTIVITY_SINGLE_TOP 触发意图,并且您之前通过按主页按钮导航离开它(而不是后退按钮)来关闭活动,那么系统尚未销毁您的活动以保留内存,然后它将返回到 onNewIntent() 回调并返回到前台。甚至来自小部件

以上是关于将数据从小部件传递到应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何在初始化程序颤动中从小部件访问传递的值

从小部件扩展访问核心数据

在颤动中将数据从小部件发送到另一个小部件

将 PendingIntent 中小部件的附加信息传递给 Activity

如何从小部件的函数返回值,并将其传递给 Tkinter,Python 中的另一个小部件的函数

如何使用来自小部件的不同附加功能打开相同的活动