【问题标题】:Widget problems on android 4.0.3android 4.0.3 上的小部件问题
【发布时间】:2013-07-16 10:28:19
【问题描述】:

我已经尝试了大约 7,8 个教程并在这里阅读了至少 30,40 个答案,但徒劳无功...我无法让任何小部件在我的手机上运行。

每个小部件实现都不会更新我的小部件上的文本,也不会在点击时注册小部件。

例如本教程:http://blog.doityourselfandroid.com/2011/05/24/developing-android-home-screenwidgets/ 你可以下载代码,它在我朋友的手机 (android 2.3) 上运行良好,但在我的手机上我可以看到接收器在 Log Cat 中发射但没有任何更新?

这是我目前的简单代码:

1.manifest

<receiver android:name=".TestWidgetProvider">
        <meta-data android:name="android.appwidget.provider"
            android:resource="@xml/testwidgetprovider"
            />
        <intent-filter >
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
        </intent-filter>

    </receiver>
    <receiver android:name=".TestReceiver"/>
  1. TestWidgetProvider

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
    
    
    Log.d("CSV", "Called on onUpdate");
    
    AlarmManager am=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Calendar cal=Calendar.getInstance();
    cal.add(Calendar.SECOND, 30);
    
    Intent intent=new Intent(context, TestReceiver.class);
    
    
    int N=appWidgetIds.length;
    for (int i=0; i<N; i++) {
    
        RemoteViews tt=new RemoteViews(context.getPackageName(), R.layout.testwidget);
    
        tt.setTextViewText(R.id.textView1,"UPDATED" +i);
    
        appWidgetManager.updateAppWidget(appWidgetIds[i], tt);
    
        Log.d("CSV", "Update widget, i = " +i + " widgetId=" + appWidgetIds[i] );
    
    }
    
    
    
    intent.putExtra("id", appWidgetIds);
    intent.putExtra("duz", appWidgetIds.length);
    
    PendingIntent p1=PendingIntent.getBroadcast(context, 1, intent, 0);
    am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 10000, p1);
    
    super.onUpdate(context, appWidgetManager, appWidgetIds);
    

    }

  2. 测试接收器

    public class TestReceiver extends BroadcastReceiver {
    
    
    private static final String tag="TestReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    
    
    int[] ID;
    Bundle extras=intent.getExtras();
    ID=extras.getIntArray("id");
    int duz=intent.getIntExtra("duz", 0);
    
    Log.d("CSV", "update widget id=" +ID);
    
    
    double b=Math.random();
    int i=(int) ((b*10+1)%10);
    
    RemoteViews rv=new RemoteViews(context.getApplicationContext().getPackageName(), R.layout.testwidget);
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context.getApplicationContext());
    
    
    for (int a=0; a<duz; i++) {
    
        rv.setTextViewText(R.id.textView1, "update random: " + a);
        appWidgetManager.updateAppWidget(ID[a], rv);
        Log.d("CSV", "Update widget, a = " +a + " widgetId=" + ID[a] );
    
    }
    
    
    /*
    ComponentName provider = new ComponentName(context, TestWidgetProvider.class);
    appWidgetManager.updateAppWidget ( provider, rv);
    */
    

    }

  3. 小部件 xml

    <?xml version="1.0" encoding="utf-8"?>
       <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 
        android:minWidth="200dp"
    android:minHeight="120dp"
    android:updatePeriodMillis="0"
    android:initialLayout="@layout/testwidget"
    android:resizeMode="horizontal|vertical"
    >
    </appwidget-provider>
    

请帮助我已经被困了几天知道...

编辑 1。我添加了第一个答案所建议的主要活动,但没有变化。

第一次我在屏幕上设置小部件时,文本并没有实际更新,就像它找不到小部件一样,但第二次我把小部件放在屏幕上时,它会根据代码更改其文本在 onEnable 中?

编辑 2: 我已经发布了一个答案,暂时解决了我的问题,并更新了小部件

编辑 3. 我已将 Richard Le Mesurier 的答案标记为正确答案,因为他的演示代码非常详细地介绍了在进行网络操作时通过服务管理小部件。它涵盖了我的问题以及我要问的许多其他问题。如果您打算认真使用小部件,我建议您学习此演示。

【问题讨论】:

  • OnEnable 为空。我设法让小部件在我第一次放置时更新: ComponentName provider = new ComponentName(context, TestWidgetProvider.class); appWidgetManager.updateAppWidget(提供者,tt);而不是在 onUpdate 中进行更新的 for 循环
  • 我确实有 TextView1....正如我上面所说,它会在我第一次放置它时更改文本,但仍然没有在接收器类中更新,我尝试使用与 ComponentName 相同的代码但没有成功...

标签: android android-intent android-widget android-alarms android-broadcast


【解决方案1】:

答案 2(更新链接到工作演示)

正如向@JanBo 承诺的那样,我将提供更多关于我如何解决此问题的详细信息(免责声明 - 这只是我的意见,我希望有建设性的 cmets 就如何改进提出建议)。

JanBo 有一个问题,一种更新方法有效,一种失败。我建议他将它们组合成一个方法,在这两种情况下都可以调用。

我在 GitHub 上有一个名为 StackFlairWidget 的概念验证演示小部件应用程序。它显示了用户的 Stack Overflow“天赋”图像:

(此项目正在进行中 - 使用POC Complete 提交可能更容易查看与此问题相关的代码。它有一些错误,但比头部修订更容易理解。)

这是一个允许以不同方式配置多个小部件的演示。你可以例如在项目中搜索“appWidgetId”以显示我如何通过各种方法传递小部件 ID,从而使用户能够正确配置小部件。

它显示了将小部件更新代码卸载到服务内的线程中的模式,以免给您的BroadcastReceiver 带来压力 - 随着项目的发展,您可能需要做类似的事情。

由于它只是一个演示应用程序,它包含许多 cmets、一些过于复杂的代码(从生产应用程序中借用)以及一些可怕的 hack(我道歉)。

基本上,正如您所说,您的更新代码是正确的。我的,fwiw,属于FlairWidgetService 类。它使用图像更新给定的小部件:

public void updateWidget(int appWidgetId, Bitmap flair)
{
    try
    {
        // set remote views
        RemoteViews widgetUi = new RemoteViews(getPackageName(), R.layout.widget);
        widgetUi.setImageViewBitmap(R.id.ivFlair, flair);

        // open Settings on click
        Intent flairSettings = new Intent(this, SettingsActivity.class);
        flairSettings.putExtra(IntentExtra.Key.APP_WIDGET_ID, appWidgetId);
        PendingIntent pendingIntentIp =
                PendingIntent.getActivity(this, appWidgetId, flairSettings,
                        PendingIntent.FLAG_UPDATE_CURRENT);
        widgetUi.setOnClickPendingIntent(R.id.ivFlair, pendingIntentIp);

        /* UPDATE THE WIDGET INSTANCE */
        try
        {
            AppWidgetManager widgetManager = AppWidgetManager.getInstance(this);
            widgetManager.updateAppWidget(appWidgetId, widgetUi);
        }
        catch (Exception e)
        {
            Dbug.log("Failed to update widget");
        }
    }
    catch (Exception e)
    {
        Dbug.log("Failed to update widget");
    }
    finally
    {
        // clean up
        FlairWidgetService.this.stopSelf();
    }
}

这不是唯一的方法,但我保证我会提供一些东西......祝你好运。


答案 1(没有帮助发帖,根据编辑 1)

您似乎受到了我认为 HoneyComb 中发生的安全升级的影响。

基本上,在较新版本的 Android 中,如果不先启动 Activity,您的小部件将无法正常工作。

所以在项目中添加一个活动,先运行它,我认为你的小部件会更新。

一个很好的例子是使用设置风格的活动,或者也许和关于框类型的东西,告诉用户一些关于你的小部件的信息。 (我在我的小部件中使用设置)。


更多信息:

【讨论】:

  • 仍然没有工作,我添加了一个启动活动,但没有任何改变.....我可以看到所有方法都工作,因为所有日志都显示了,但没有任何更新。
  • Thnx 获取更多信息和演示,我会尽快查看并进一步更新!
  • 我已经更新了我的问题并标记了你的答案。再次感谢您的帮助。
【解决方案2】:

如果我在我的 TestReceiver 中使用此代码,它会起作用

    ComponentName thisAppWidget = new ComponentName(context.getPackageName(), TestWidgetProvider.class.getName());
     AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context.getApplicationContext());
     int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);

     appWidgetManager.updateAppWidget(ids, tt);

在 AppWidgetProvider 的 onUpdate 中:

    ComponentName provider = new ComponentName(context, TestWidgetProvider.class);
    appWidgetManager.updateAppWidget ( provider, tt); //tt is RemoteViews tt=...

我不知道为什么,但这是唯一适用于我手机的组合?

如果有人对此了解更多,请解释一下,因为我需要结合警报管理器进行更新等复杂服务......

@Richard Le Mesurier 感谢 android 4.0 需要为小部件提供活动的信息,但在任何地方都没有找到。

【讨论】:

  • 如果我今晚有机会做一些工作,我会在我的答案中添加更多细节。
  • 我已经更新了我的答案的价值 - 也许你会发现一些有用的东西,就像我为自己创建演示时所做的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-06
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
相关资源
最近更新 更多