Android widget update via service, that is doing h

2019-04-01 23:28发布

问题:

what is the best strategy for the following scenario:

my app will periodically send and receive http requests to a server run PHP script. I tried a service fired by AlarmManager or clicking directly on its widget. Direct operations on the device are working fine (like random numbers, see http://www.vogella.com/tutorials/AndroidWidgets/article.html ) when it comes to the request, these should be done in async tasks. I tried to update the widget (remoteView) from the postexecute section of the async task, but it is not working.

Somebody could give me some hints or maybe snippets?

thank you in advance

Update:

widget provider class with async task:

public class MyWidgetProvider extends AppWidgetProvider {

private static final String ACTION_CLICK = "ACTION_CLICK";
long ddd;
String dddd;
RemoteViews remoteViews;
TextView tvUpdate;


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

the service class with async task making pings to website (only for test purpose, later requests will be done there) the aim is to show the ping in the widget:

public class UpdateWidgetService extends Service {
private static final String LOG = "de.vogella.android.widget.example";
long ddd;
String dddd;
RemoteViews remoteViews;
TextView tvUpdate;

@Override
public void onStart(Intent intent, int startId) {
    Log.i(LOG, "Called");
    // create some random data

    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 = new RemoteViews(this
                .getApplicationContext().getPackageName(),
                R.layout.widget_layout);
        Log.w("WidgetExample", String.valueOf(number));
        if (dddd!=null)Log.w("dddd -", dddd);
        new LongOperation().execute("");
        if (dddd!=null)Log.w("dddd +", dddd);
        // Set the text
        remoteViews.setTextViewText(R.id.update,
                "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.update, pendingIntent);
        appWidgetManager.updateAppWidget(widgetId, remoteViews);
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.add(Calendar.SECOND, 5);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                cal.getTimeInMillis(), 5 * 1000, pendingIntent);

    }
    stopSelf();

    super.onStart(intent, startId);
}

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

private class LongOperation extends AsyncTask<String, Void, String> {
    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
    }

    @Override
    protected String doInBackground(String... params) {
        // TODO Auto-generated method stub
        ddd = MainActivity.isURLReachable();

        Log.e("ddd", ddd + "");
        dddd = ddd + " ms";
        Log.e("dddd", dddd);

        return null;
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        Log.e("POST dddd", dddd);
        remoteViews.setTextViewText(R.id.update, dddd);
    }

}

}

problem is that widget is not reachable from the post execute async task.

UPDATE 2:

How can I get the WidgetIDs from the postexecute method?

@Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(UpdateWidgetService.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 = new RemoteViews(UpdateWidgetService.this
                    .getApplicationContext().getPackageName(),
                    R.layout.widget_layout);
            Log.w("WidgetExample", String.valueOf(number));
            if (dddd!=null)Log.w("dddd -", dddd);
            new LongOperation().execute("");
            if (dddd!=null)Log.w("dddd +", dddd);
            // Set the text
            remoteViews.setTextViewText(R.id.update,
                    "Random: " + dddd);

            // Register an onClickListener
            Intent clickIntent = new     Intent(UpdateWidgetService.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.update, pendingIntent);
            appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }


    }

回答1:

problem is that widget is not reachable from the post execute async task.

It does not need to be. onPostExecute() can get an instance of AppWidgetManager via getInstance() and call updateAppWidget() on it.