安卓系统中的可点击小部件

2022-08-31 15:08:49

开发人员文档似乎让我失望了。我可以不假思索地创建一个静态小部件,我甚至可以创建一个像模拟时钟小部件这样的小部件,它将自我更新,但是,我无法为我的生活弄清楚如何创建一个小部件,以便在用户单击它时做出反应。以下是开发人员文档给出的有关小部件活动应包含的内容的最佳代码示例(唯一的其他提示是 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);
        }
    }
}

来自: Android 开发人员文档的 Widget 页面

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

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

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

那么,我能做些什么来让应用程序小伙伴响应点击?由于该方法是我找到的最接近某一种方法的方法。onClickPendingIntent()onClick


答案 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
}

这应该可以做到!


答案 2

onUpdate 方法保留原样,并复制粘贴逻辑以更新 AppWidget

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);
    }
}

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