AppWidgetProvider public void onEnabled(Context context)不会影响窗口小部件

时间:2013-12-27 00:07:43

标签: android android-asynctask android-widget textview

我正在使用AppWidgetProvider并试图覆盖onEnabled,我假设是当应用程序从用户添加到主屏幕时调用的内容。我的AppWidgetProvider类看起来像这样,并调用异步任务,该任务应该更新我的文本视图:

package com.example.beerportfoliopro;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;

/**
 * Created by Mike on 12/26/13.
 */
public class HelloWidget extends AppWidgetProvider {

    @Override
    public void onEnabled(Context context){

        //build url for async task
        String url = "hiddenURL";

        //call async task
        new GetRandomBeer(context).execute(url);



    }

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

        //todo: call update code, which should be the same as onEnabled


    }


}

显示小部件外观的我的小部件xml文件是:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/widget_bg_normal"
    >


    <TextView
        android:id="@+id/widget_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="testing 123"
        android:layout_gravity="center_horizontal|center"
        android:layout_marginTop="5dip"
        android:padding="10dip"
        android:textColor="@android:color/black"
        >
    </TextView>

</LinearLayout>

我的异步任务最终将解析一些JSON以添加到我的小部件,如下所示:

public class GetRandomBeer extends AsyncTask
        <String, Void, String> {

    Context c;

    public GetRandomBeer(Context context)
    {
        c = context;

    }

    @Override
    protected String doInBackground(String... arg0) {
        // TODO Auto-generated method stub
        return readJSONFeed(arg0[0]);
    }



    protected void onPostExecute(String result){
        Log.d("taste","Inside get taste");
        //decode json here
        try{

            //todo: get all beer data



            //todo: set text views with data
            TextView breweryTitle = (TextView) ((Activity) c).findViewById(R.id.widget_tv);
            breweryTitle.setText("changed in the async task!");




        }
        catch(Exception e){

        }


    }

    public String readJSONFeed(String URL) {
        StringBuilder stringBuilder = new StringBuilder();
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(URL);
        try {
            HttpResponse response = httpClient.execute(httpGet);
            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            if (statusCode == 200) {
                HttpEntity entity = response.getEntity();
                InputStream inputStream = entity.getContent();
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(inputStream));
                String line;
                while ((line = reader.readLine()) != null) {
                    stringBuilder.append(line);
                }
                inputStream.close();
            } else {
                Log.d("JSON", "Failed to download file");
            }
        } catch (Exception e) {
            Log.d("readJSONFeed", e.getLocalizedMessage());
        }
        return stringBuilder.toString();
    }

}

根据我上面的代码,当用户将小部件添加到他们的主屏幕时,它应该运行onEnabled(),它应该调用我的异步任务并将textview从“测试123”更改为“更改异步任务!”

现在一切都没有改变,我无法弄清楚原因。

更新

以下是我的清单中与我的小部件相关的代码:

   <receiver android:name="com.example.beerportfoliopro.HelloWidget" android:label="@string/app_name">
        <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
        </intent-filter>

我也知道我的异步任务正在被调用,因为我只是将一些Log.d放入其中并且它正在运行异步任务,它只是没有在小部件中设置textview值。

更新2

我也尝试使用下面建议的答案使用远程视图,现在我在异步任务中有这个:

 @Override
    protected String doInBackground(String... arg0) {
        // TODO Auto-generated method stub

        String beerText =  "try number 3";

        AppWidgetManager mgr = AppWidgetManager.getInstance(c);
        int[] appWidgetIds = mgr.getAppWidgetIds(new ComponentName(c, HelloWidget.class));

        //You need a static method somewhere (I usually put in widget provider class)
        //that builds the RemoteView and sets everything up.
        RemoteViews rv = HelloWidget.buildRemoteViews(c, mgr, appWidgetIds);

        rv.setTextViewText(R.id.widget_tv, beerText);

        mgr.updateAppWidget(appWidgetIds, rv);


        return readJSONFeed(arg0[0]);
    }

但我得到一个无法解决方法错误

 RemoteViews rv = HelloWidget.buildRemoteViews(c, mgr, appWidgetIds);
<{1>}

下的

2 个答案:

答案 0 :(得分:3)

在清单中注册广播:

<receiver android:name="MyWidget" android:label="Widget">
<intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    <action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
</intent-filter>
....
</receiver>

还要注意onEnabled():

“当第一次创建App Widget的实例时调用此方法。例如,如果用户添加了App Widget的两个实例,则只会在第一次调用它。”

你还有一个事实是,当添加一个实例时,无论如何都会调用onUpdate(),所以在onEnabled()中做同样的事情可能是多余的。

此外,一旦你执行了AsyncTask,你就会遇到很多问题,首先是Context对象不是Activity。

编辑:既然正在调用您的方法,您将需要使用RemoteViews设置文本。您不需要在onPostExecute()中执行此操作,因为这是跨进程更新。

protected Void doInBackground(String... arg0) {

    String beerText =  readJSONFeed(arg0[0]);

    AppWidgetManager mgr = AppWidgetManager.getInstance(c);
    int[] appWidgetIds = mgr.getAppWidgetIds(new ComponentName(c, HelloWidget.class));

    //You need a static method somewhere (I usually put in widget provider class) 
    //that builds the RemoteView and sets everything up.
    RemoteViews rv = HelloWidget.buildRemoteViews(c, mgr, appWidgetIds);

    rv.setTextViewText(R.id.text_view_in_layout, beerText);

    mgr.updateAppWidget(appWidgetIds, rv);
}

这会更新你的所有AppWidget,如果你只想更新一个,你需要传递它的id。

答案 1 :(得分:0)

buildRemoteViews()方法不是如何在窗口小部件中获取RemoteViews对象;改为使用构造函数。

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);

没有冒犯,但API guide for App Widgets

中的例子清楚地说明了这一点