【问题标题】:Clickable widgets in androidandroid中的可点击小部件
【发布时间】:2011-02-14 11:16:57
【问题描述】:

这里的开发者文档似乎让我失望了。我可以不假思索地创建一个静态小部件,我什至可以创建一个类似于模拟时钟小部件的小部件,它会自行更新,但是,我终其一生都无法弄清楚如何创建一个对用户点击时做出反应的小部件它。这是开发人员文档中给出的关于小部件活动应包含的最佳代码示例(唯一的其他提示是 API 演示,它只创​​建一个静态小部件):

public class ExampleAppWidgetProvider extends AppWidgetProvider {
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        final int N = appWidgetIds.length;

        // Perform this loop procedure for each App Widget that belongs to this provider
        for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];

            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

            // Get the layout for the App Widget and attach an on-click listener to the button
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current App Widget
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

来自:The Android Developer Documentation's Widget Page

因此,当小部件被点击时,它看起来像挂起的意图被调用,这是基于一个意图(我不太确定意图和挂起的意图之间的区别是什么),并且意图是ExampleActivity 类。因此,我将示例活动类设为一个简单的活动,在创建时会创建一个媒体播放器对象并启动它(它永远不会释放该对象,因此最终会崩溃,这是它的代码:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.sound);
    mp.start();
}

但是,当我将小部件添加到主屏幕并单击它时,没有播放任何内容,事实上,当我将更新计时器设置为几百毫秒(在 appwidget 提供程序 xml 文件中)时,没有播放任何内容。此外,我设置了断点,发现它不仅永远不会到达活动,而且我设置的断点也不会被触发。 (我还没有弄清楚为什么会这样)但是,logcat 似乎表明正在运行活动类文件。

那么,我可以做些什么来让 appwidget 响应点击?因为onClickPendingIntent() 方法是我发现的最接近onClick 类型的方法。

【问题讨论】:

  • Hai Leif,你用 Brain515 的 Methode 解决了这个问题吗?我有类似的问题,但是大脑的解决方案对我不起作用,你能帮帮我吗?

标签: java android onclick android-widget


【解决方案1】:

首先,添加一个带有常量的静态变量。

public static String YOUR_AWESOME_ACTION = "YourAwesomeAction";

那么你需要在将意图添加到待处理意图之前将操作添加到意图:

Intent intent = new Intent(context, widget.class);
intent.setAction(YOUR_AWESOME_ACTION);

(widget.class 是你的 AppWidgetProvider 的类,你当前的类)

然后你需要用 getBroadcast 创建一个 PendingIntent

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

为您的小部件中的可点击视图设置 onClickPendingIntent

remoteView.setOnClickPendingIntent(R.id.widgetFrameLayout, pendingIntent);

接下来,重写同一个类中的onReceive方法:

@Override
public void onReceive(Context context, Intent intent) {
 super.onReceive(context, intent);

然后通过在 onReceive 方法中查询为您的操作返回的意图来响应您的按钮按下:

if (intent.getAction().equals(YOUR_AWESOME_ACTION)) {
   //do some really cool stuff here
}

应该这样做!

【讨论】:

  • 这一行(Intent intent = new Intent(context, ExampleActivity.class);) 在哪里? widget.class 包含什么?我猜 ExampleActivity 是我们想要启动的
  • 编辑了对方法的回复,需要一些额外的步骤才能使其正常工作。 getBroadcast 对于要广播的 PendingIntent 很重要,而不是示例中的 getActivity。
  • .getActivity 用于打开活动,例如当您单击小部件中的对象时
  • 使用 LocalBroadcastManager 而不是通用广播
  • AFAIK 无法将 PendingIntent 与 LocalBroadcastManager 一起使用
【解决方案2】:

保持 onUpdate 方法不变,并将逻辑复制粘贴到 updateAppWidget

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                            int appWidgetId) {

    // Create an Intent to launch ExampleActivity when clicked
    Intent intent = new Intent(context, ExampleActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    // Construct the RemoteViews object
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
    // Widgets allow click handlers to only launch pending intents
    views.setOnClickPendingIntent(R.id.button, pendingIntent);
    // Instruct the widget manager to update the widget
    appWidgetManager.updateAppWidget(appWidgetId, views);
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    // There may be multiple widgets active, so update all of them
    for (int appWidgetId : appWidgetIds) {
        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

PS。 PendingIntent 只是一个 Intent 的“盒子”,它允许其他应用程序访问并在您的应用程序中运行该 Intent。

【讨论】:

  • 为什么每次小部件更新都这样做?确定只需要执行一次吗?
猜你喜欢
  • 2011-08-10
  • 2015-11-24
  • 2011-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-17
  • 2015-06-02
相关资源
最近更新 更多