Android Widget 更新服务,多个 onclick 监听器

Posted

技术标签:

【中文标题】Android Widget 更新服务,多个 onclick 监听器【英文标题】:Android Widget Update service, multiple onclick listeners 【发布时间】:2014-06-07 22:33:26 【问题描述】:

我有以下小部件服务,当我单击一个按钮时,它会更新文本视图。

更新小部件服务:

ipublic class UpdateWidgetService extends Service 

private static final String LOG = "widgetService";
private static final String MyOnClick1 = "myOnClickTag1";
private static final String MyOnClick2 = "myOnClickTag2";
private static final String MyOnClick3 = "myOnClickTag3";

static LocationClient mLocationClient;

@Override
public void onStart(Intent intent, int startId) 

    Log.i(LOG, "Called and started");

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext());
    int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);

    ComponentName thisWidget = new ComponentName(getApplicationContext(), MyWidgetProvider.class);
    int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
    Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
    Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));

    for (int widgetId : allWidgetIds) 
        // create some random data
        int number = (new Random().nextInt(100));

        RemoteViews remoteViews = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.widget_layout);
        Log.w("WidgetExample", String.valueOf(number));
        // Set the text
        remoteViews.setTextViewText(R.id.widget_textview_gpscoords, "Random: " + String.valueOf(number));

        // Register an onClickListener
        Intent clickIntent = new Intent(this.getApplicationContext(), MyWidgetProvider.class);

        clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);

        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.widget_button_dissarm, pendingIntent);
        appWidgetManager.updateAppWidget(widgetId, remoteViews);
    
    stopSelf();
    super.onStart(intent, startId);


@Override
public IBinder onBind(Intent intent) 
    return null;

MyWidget 提供者:

public class MyWidgetProvider extends AppWidgetProvider 

private static final String LOG = "de.vogella.android.widget.example";

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

    Log.w(LOG, "onUpdate method called");
    // Get all ids
    ComponentName thisWidget = new ComponentName(context, MyWidgetProvider.class);
    int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

    // Build the intent to call the service
    Intent intent = new Intent(context.getApplicationContext(), UpdateWidgetService.class);
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);

    // Update the widgets via the service
    context.startService(intent);
        

android 清单:

<!-- Widget -->
    <receiver
        android:name="widget.MyWidgetProvider"
        android:icon="@drawable/icon"
        android:label="My Widget" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />                
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/example_appwidget_info" />
    </receiver>
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    <!-- Services -->
    <service android:name="widget.UpdateWidgetService" >
    </service>

现在我的问题是,如何确定点击了哪个按钮?我的小部件上有 4 个按钮,我想区分单击了哪些按钮?在我的示例中,按钮 onclick 的意图是 ACTION_APPWIDGET_UPDATE 我想我需要如何更改它?

这样做的正确方法是什么?

最终我的每个按钮都会进行网络通话,这就是我使用该服务的原因,因为网络通话可能需要一些时间。

【问题讨论】:

【参考方案1】:

我没有足够的声誉来评论您的帖子,所以我的回答只是为了从您那里获取更多信息并向您展示如何为 AppWidget 按钮添加操作的简单示例。如果您接受我的回答,我会为您提供更多帮助。顺便说一句,您没有在此处提供 UpdateWidgetService.java,而是两次提供 AppWidgetProvider。

更新:

我会将您的 UpdateWidgetService.java 更改为以下代码。

public class UpdateWidgetService extends Service 

private static final String LOG = "widgetService";

// my changes - part 1 - beginning
private static final String BUTTON_ONE_CLICKED = "com.yourpackage.BUTTON_ONE_CLICKED";
private static final String BUTTON_TWO_CLICKED = "com.yourpackage.BUTTON_TWO_CLICKED";
private static final String BUTTON_THREE_CLICKED = "com.yourpackage.BUTTON_THREE_CLICKED";
private static final String BUTTON_FOUR_CLICKED = "com.yourpackage.BUTTON_FOUR_CLICKED";
// my changes - part 1 - end


@Override
public void onStart(Intent intent, int startId) 

    Log.i(LOG, "Called and started");

    // my changes - part 2 - beginning
    if(BUTTON_ONE_CLICKED.equals(intent.getAction())) 
        // do what should be done if button One has been clicked
    
    if(BUTTON_TWO_CLICKED.equals(intent.getAction())) 
        // do what should be done if button Two has been clicked
    
    if(BUTTON_THREE_CLICKED.equals(intent.getAction())) 
        // do what should be done if button Three has been clicked
    
    if(BUTTON_FOUR_CLICKED.equals(intent.getAction())) 
        // do what should be done if button Four has been clicked
    
    // my changes - part 2 - end

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext());
    int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);

    ComponentName thisWidget = new ComponentName(getApplicationContext(), MyWidgetProvider.class);
    int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
    Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
    Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));

    for (int widgetId : allWidgetIds) 
        // create some random data
        int number = (new Random().nextInt(100));

        RemoteViews remoteViews = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.widget_layout);
        Log.w("WidgetExample", String.valueOf(number));
        // Set the text
        remoteViews.setTextViewText(R.id.widget_textview_gpscoords, "Random: " + String.valueOf(number));

        // my changes - part 3 - beginning
        Context context = getApplicationContext();

        Intent buttonOneIntent = new Intent(context, UpdateWidgetService.class);
        Intent buttonTwoIntent = new Intent(context, UpdateWidgetService.class);
        Intent buttonThreeIntent = new Intent(context, UpdateWidgetService.class);
        Intent buttonFourIntent = new Intent(context, UpdateWidgetService.class);

        // set action
        buttonOneIntent.setAction(BUTTON_ONE_CLICKED);
        buttonTwoIntent.setAction(BUTTON_TWO_CLICKED);
        buttonThreeIntent.setAction(BUTTON_THREE_CLICKED);
        buttonFourIntent.setAction(BUTTON_FOUR_CLICKED);

        // put widgetId
        buttonOneIntent.putExtra("widgetId", widgetId);
        buttonTwoIntent.putExtra("widgetId", widgetId);
        buttonThreeIntent.putExtra("widgetId", widgetId);
        buttonFourIntent.putExtra("widgetId", widgetId);

        // make these intents unique to avoid collisions
        buttonOneIntent.setData(Uri.withAppendedPath(Uri.parse("webcall_widget://buttonone/widgetid"), String.valueOf(widgetId)));
        buttonTwoIntent.setData(Uri.withAppendedPath(Uri.parse("webcall_widget://buttontwo/widgetid"), String.valueOf(widgetId)));
        buttonThreeIntent.setData(Uri.withAppendedPath(Uri.parse("webcall_widget://buttonthree/widgetid"), String.valueOf(widgetId)));
        buttonFourIntent.setData(Uri.withAppendedPath(Uri.parse("webcall_widget://buttonfour/widgetid"), String.valueOf(widgetId)));

        // pending intents
        PendingIntent buttonOnePendingIntent = PendingIntent.getService(context, 0, buttonOneIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        PendingIntent buttonTwoPendingIntent = PendingIntent.getService(context, 0, buttonTwoIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        PendingIntent buttonThreePendingIntent = PendingIntent.getService(context, 0, buttonThreeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        PendingIntent buttonFourPendingIntent = PendingIntent.getService(context, 0, buttonFourIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        // register onClickListeners to your buttons
        remoteViews.setOnClickPendingIntent(R.id.button_one, buttonOnePendingIntent);
        remoteViews.setOnClickPendingIntent(R.id.button_two, buttonTwoPendingIntent);
        remoteViews.setOnClickPendingIntent(R.id.button_three, buttonThreePendingIntent);
        remoteViews.setOnClickPendingIntent(R.id.button_four, buttonFourPendingIntent);
        // my changes - part 3 - end

        appWidgetManager.updateAppWidget(widgetId, remoteViews);
    
    stopSelf();
    super.onStart(intent, startId);


@Override
public IBinder onBind(Intent intent) 
    return null;


如果有不清楚的地方,请不要犹豫,问我。

【讨论】:

好的,我已经修复了我的帖子,希望它现在更有意义。 好吧,这是有道理的,但现在我的小部件提供者不是只接收带有动作 &lt;action android:name="android.appwidget.action.APPWIDGET_UPDATE" /&gt; 的广播意图吗?现在我将更改操作,因此不会调用该服务。 哦,等等,我想我知道你在做什么了。您的意图是直接访问服务,而不是通过 widgetprovider 接收的更新广播。小部件服务直接接收意图。如果我理解正确的话。 @Zapnologica 是的,您是对的并且理解正确。希望我的回答对你有足够的帮助。

以上是关于Android Widget 更新服务,多个 onclick 监听器的主要内容,如果未能解决你的问题,请参考以下文章

method ‘void android.widget.Spinner.setAdapter(android.widget.SpinnerAdapter)‘ on a null object refe

int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' on a null.....

Android Widget onClick 不起作用 - 服务无法启动

Android Studio Widget 更新更快

Android开发之创建App Wiget和更新Widget内容

更新您的 widget 以适配 Android 12