简体   繁体   English

Android 小部件 - 单击按钮时更新

[英]Android Widget - update when a button is clicked

Good day.再会。 I'm trying to create a widget that will show the balance on the screen.我正在尝试创建一个将在屏幕上显示余额的小部件。 Created 2 buttons and set up the listener to determine which button was pressed.创建 2 个按钮并设置侦听器以确定按下了哪个按钮。

Difficulty: How to update data by clicking on the button or reload the widget so that the data is updated?难点:如何通过点击按钮更新数据或重新加载widget从而更新数据?

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.DateFormat;
import java.util.Date;

public class EthWidgetProvider extends AppWidgetProvider {
    private static final String SYNC_CLICKED    = "automaticWidgetSyncButtonClick";
    private static final String SYNC_CLICKED2    = "automaticWidgetSyncButtonClick2";


    static void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager, final int appWidgetId) {
        RequestSingleton.getInstance(context).fetchData(new VolleyCallback() {
            @Override
            public void onSuccessRequest(JSONArray result) {
                Log.i("Response", result.toString());
                String price = "";
                try {
                    JSONObject etherObject = result.getJSONObject(0);
                    price = etherObject.getString("price_usd");
                } catch (JSONException e) {
                    Log.e("JSONException", e.toString());
                }
                Log.i("Price", price);
                RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_widget);
                views.setTextViewText(R.id.gprs, "$" + price);

                String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
                views.setTextViewText(R.id.timeofday, currentDateTimeString);

                appWidgetManager.updateAppWidget(appWidgetId, views);
            }
        });
    }
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {


        RemoteViews remoteViews;
        ComponentName watchWidget;

        remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_widget);
        watchWidget = new ComponentName(context, EthWidgetProvider.class);

        remoteViews.setOnClickPendingIntent(R.id.refresh, getPendingSelfIntent(context, SYNC_CLICKED));
        remoteViews.setOnClickPendingIntent(R.id.example_widget_button, getPendingSelfIntent(context, SYNC_CLICKED2));
        appWidgetManager.updateAppWidget(watchWidget, remoteViews);

        for(int appId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appId);
        }
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        super.onReceive(context, intent);

        if (SYNC_CLICKED.equals(intent.getAction())) {

            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

            RemoteViews remoteViews;
            ComponentName watchWidget;

            remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_widget);
            watchWidget = new ComponentName(context, EthWidgetProvider.class);

            remoteViews.setTextViewText(R.id.timeofday, "TESTING");

            appWidgetManager.updateAppWidget(watchWidget, remoteViews);

        }

        if (SYNC_CLICKED2.equals(intent.getAction())) {

            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

            RemoteViews remoteViews;
            ComponentName watchWidget;

            remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_widget);
            watchWidget = new ComponentName(context, EthWidgetProvider.class);

            remoteViews.setTextViewText(R.id.timeofday, "TESTING2");

            appWidgetManager.updateAppWidget(watchWidget, remoteViews);

        }
    }

protected PendingIntent getPendingSelfIntent(Context context, String action) {
        Intent intent = new Intent(context, getClass());
        intent.setAction(action);
        return PendingIntent.getBroadcast(context, 0, intent, 0);
    }
}

By pressing button 1, I need to show the activity.通过按下按钮 1,我需要显示活动。 By pressing the second button, you need to update the widget so that the data is updated, that is, so that the request to the server goes again and the data is updated.通过按下第二个按钮,您需要更新小部件,以便更新数据,即再次向服务器发出请求并更新数据。

Any help would be appreciated.任何帮助,将不胜感激。

I don't get you idea with the Broadcast.我不明白你对广播的看法。

  1. The broadcast should not be inner class广播不应该是内部 class
  2. Broadcast should extend BroadcastReceiver class广播应该扩展 BroadcastReceiver class
  3. Broadcast should be defined in manifest广播应该在清单中定义

So when you do this, your receiver should be called after buttons are clicked.因此,当您这样做时,应在单击按钮后调用您的接收器。

But, you want something to wake up your Widget.但是,你想要一些东西来唤醒你的小部件。 And then Widget#onUpdate will fetch the updated data (that you download on widget click) and show them.然后 Widget#onUpdate 将获取更新的数据(您在小部件单击时下载的数据)并显示它们。 To request update of your widget, you can use something like this:要请求更新您的小部件,您可以使用以下内容:

public static void updateAppWidget(@NonNull Context applicationContext,
        @NonNull Class<? extends AppWidgetProvider> widgetProviderClass) {
    final ComponentName component = new ComponentName(applicationContext, widgetProviderClass);
    final int[] widgetIds;
    try {
        widgetIds = AppWidgetManager.getInstance(applicationContext).getAppWidgetIds(component);
    } catch (RuntimeException re) {
        Log.d(re, "Unable to obtain widget IDs.");
        return;
    }

    if (widgetIds.length == 0) {
        Log.d("There is no widget to be updated.");
        return;
    }

    final Intent intent = new Intent(applicationContext, widgetProviderClass);
    intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds);

    applicationContext.sendBroadcast(intent);
}

So to sum it up:所以总结一下:

  • In widget setup views, listeners, and populate with last known data.在小部件设置视图中,侦听器和填充最后一个已知数据。
  • In listener broadcast either open Activity, or run some download在侦听器广播中打开 Activity,或运行一些下载
  • Don't forget BroadcastReceivers are running on UI thread;不要忘记 BroadcastReceivers 在 UI 线程上运行; use goAsync() approach.使用 goAsync() 方法。
  • The downloaded data should be stored to some place, where widget can obtain them下载的数据应该存储在某个地方,小部件可以获取它们
  • call mentioned function to trigger widget update.调用提到的 function 来触发小部件更新。

I believe, this is a quite specific and complex topic unlike the rest of Android, so feel free to ask anything I might missed:)我相信,与 Android 的 rest 不同,这是一个非常具体和复杂的话题,所以请随时问我可能错过的任何问题:)

To call activity:调用活动:

remoteViews.setOnClickPendingIntent( R.id.button1, PendingIntent.getActivity(context, 0, new Intent( context, Main.class), 0) );

To update widgets from another class:要从另一个 class 更新小部件:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance( context );
int ids[] = appWidgetManager.getAppWidgetIds( componentName );
for( int id : ids ){
    //update textView here
    appWidgetManager.updateAppWidget( id, views);
}

There is a very helpful must-read official guide titled "Build an App Widget": ( https://developer.android.com/guide/topics/appwidgets )有一个非常有用的必读官方指南,标题为“构建应用程序小部件”:( https://developer.android.com/guide/topics/appwidgets

Please read this page carefully so you understand the concepts and focus on the AppWidgetProvider section for your problem.请仔细阅读此页面,以便您了解概念并针对您的问题关注AppWidgetProvider部分。 Although in this section, they use: PendingIntent.getActivity() , you are supposed to use a Service as PendingIntent.getService() to have your Service called on button click, and then have the Service update your Widget.尽管在本节中,他们使用: PendingIntent.getActivity() ,但您应该使用服务作为PendingIntent.getService()以在单击按钮时调用您的服务,然后让服务更新您的小部件。

Basically you'll see that you need to:基本上你会看到你需要:

  1. Create a Service创建服务

  2. Create a PendingIntent:创建一个 PendingIntent:

     Intent intent = new Intent(context, YourService.class); PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
  3. Set the onClickPendingIntent listener on your RemoteViews object like this:在 RemoteViews object 上设置onClickPendingIntent侦听器,如下所示:

     views.setOnClickPendingIntent(R.id.button, pendingIntent);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM