小部件不更新视图并且也不显示错误

时间:2013-06-28 14:50:14

标签: android android-widget broadcastreceiver android-view android-appwidget

我正在开发一个没有任何错误的小部件,但我的小部件的ImageView没有更新,也没有给出任何错误。因此让我对我正在做的错误感到困惑。这是代码: -

BroadcastReceiver _broadcastReceiver;
GetDrawableResources getDrawableResources = new GetDrawableResources();
private final SimpleDateFormat _sdfWatchTime = new SimpleDateFormat("HH:mm");

@Override
public void onEnabled(final Context context) {
    super.onEnabled(context);
    // TODO Auto-generated method stub
    System.out.println("Entering onstart");
    _broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context ctx, Intent intent) {
            System.out.println("Registering BroadCast");
            if (intent.getAction().compareTo(Intent.ACTION_TIME_TICK) == 0) {

                System.out.println(_sdfWatchTime.format(new Date()));
                Bundle extras = intent.getExtras();
                if (extras != null) {
                    AppWidgetManager awm = AppWidgetManager
                            .getInstance(context);
                    ComponentName thisWidget = new ComponentName(
                            context.getPackageName(),
                            MainActivity.class.getName());
                    int[] appWidgetIds = awm.getAppWidgetIds(thisWidget);
                    onUpdate(context, awm, appWidgetIds);
                }

            }
        }
    };
    context.getApplicationContext().registerReceiver(_broadcastReceiver,
            new IntentFilter(Intent.ACTION_TIME_TICK));

}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {
    // TODO Auto-generated method stub
    super.onUpdate(context, appWidgetManager, appWidgetIds);
    for (int awID : appWidgetIds) {
        updateAppWidget(context, appWidgetManager, awID);
    }

}

private void updateAppWidget(Context context,
        AppWidgetManager appWidgetManager, int awID2) {
    // TODO Auto-generated method stub
    // class to get drawable images that will be used to denote hours and
    // minutes

    int time[] = new int[new GetTime().getTime(context
            .getApplicationContext()).length];
    // class to get each digit of time separately eg 10:10, separating 1 0 1
    // 0 working correctly
    time = new GetTime().getTime(context.getApplicationContext());
    // changing views

    System.out.println("awID for " + awID2);
    RemoteViews views = new RemoteViews(context
            .getPackageName(), R.layout.activity_main);

    views.setImageViewResource(R.id.ivHour0,
            getDrawableResources.setTimeDrawable(time[0]));
    views.setImageViewResource(R.id.ivHour1,
            getDrawableResources.setTimeDrawable(time[1]));
    views.setImageViewResource(R.id.ivMinute0,
            getDrawableResources.setTimeDrawable(time[2]));
    views.setImageViewResource(R.id.ivMinute1,
            getDrawableResources.setTimeDrawable(time[3]));


    System.out.println("updating the views");

    appWidgetManager.updateAppWidget(awID2, views);

}

我的LogCat中的输出

06-28 19:46:00.076: I/System.out(680): Registering BroadCast
06-28 19:46:00.086: I/System.out(680): 19:46
06-28 19:46:00.096: I/System.out(680): awID for 14
06-28 19:46:00.096: I/System.out(680): updating the views
06-28 19:47:00.086: I/System.out(680): Registering BroadCast
06-28 19:47:00.086: I/System.out(680): 19:47
06-28 19:47:00.096: I/System.out(680): awID for 14
06-28 19:47:00.096: I/System.out(680): updating the views

因此appWidgetID是正确的,函数正在执行,但是视图没有更新。它们和以前一样。

1 个答案:

答案 0 :(得分:1)

您的方法有一个有效的基础,但是您正在onEnabled方法中创建并注册broadcastReceiver,而onEnabled方法又属于WidgetProvider类。

当WidgetProvider(onEnabled,onUpdate)的方法完成执行时,系统会破坏WidgetProvider类,因此你的broadcastReceiver也是如此。正如你在这里看到没有错误但没有收到错误。

为了做你想做的事情,你需要一个更“稳定”的应用程序组件来保存你的broadcastReceiver,像这样的组件是一种服务。即使您的应用程序已停止运行,服务也会继续运行,因此它是这类作业的一个很好的组件。

因此,为了回答您的问题,我建议您创建一个服务,创建并注册您的broadcastReceiver,然后从您的widgetprovider类的onEnabled方法启动服务,并且当用户从您的widget移除您的小部件时,您可以停止该服务主屏幕。

从我的建议开始的一个好地方是here...

修改 Here是来自谷歌的App Widgets的文档(约中间):

  

注意:由于AppWidgetProvider是BroadcastReceiver的扩展,因此在回调方法返回后,您的进程无法保证继续运行(有关广播生命周期的信息,请参阅BroadcastReceiver)。如果您的App Widget设置过程可能需要几秒钟(可能在执行Web请求时),并且您需要继续进程,请考虑在onUpdate()方法中启动Service。在服务中,您可以对App Widget执行自己的更新,而无需担心由于应用程序无响应(ANR)错误导致AppWidgetProvider关闭。有关运行服务的App Widget的示例,请参阅Wiktionary示例的AppWidgetProvider。

我在我的appwidget中遇到了类似的问题,原来这是由我的appwidgetprovider的生命周期引起的,所以我基于此回答了你。但是在你的观察中你是对的,你的小部件应该至少更新自己第一次更新的当前时间,所以看看它更多我看到你正在使用自定义的getDrawableResources类来获取你的资源(你能用它编辑你的问题吗?代码?),你正在使用getDrawableResources.setTimeDrawable(time [0]));为了得到drawable,也许你应该把它改成getDrawableResources.getTimeDrawable(time [0]))?

编辑2

以下是说明我的建议的代码。首先是我们注册BatteryReceiver的服务。

class FullWidgetBatteryChangedReceiver extends BroadcastReceiver {
//----- BroadcastReceiver Overrides -----
@Override
public void onReceive(Context cx, Intent intent) {
    Log.d("BatteryChangedReceiver", "onReceive");

    Commands.FullWidgetUpdate(cx, -1, 0); //<-- Update all widgets
}
//----- BroadcastReceiver Overrides END -----
}

public class myWidgetService extends Service {

//----- Private Members -----
private FullWidgetBatteryChangedReceiver    bcRCV;
//----- Private Members END -----



//----- Private Code -----    
private void RegisterBatteryChangedReceiver() {
    Log.d(TAG, "RegisterBatteryChangedReceiver");

    if (bcRCV == null) {
        Log.d(TAG, "BatteryChangedReceiver needs Registration and I am doing it...");

        bcRCV = new FullWidgetBatteryChangedReceiver();
        IntentFilter actions = new IntentFilter();
        actions.addAction(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(bcRCV, actions);
    } else {
        Log.d(TAG, "BatteryChangedReceiver does not needs Registration");
    }
}

private void UnRegisterBatteryChangedReceiver() {
    Log.d(TAG, "UnRegisterBatteryChangedReceiver");

    if (bcRCV != null) {
        Log.d(TAG, "Assuming that BatteryChangedReceiver is registered and I am unregister it...");

        unregisterReceiver(bcRCV);
        bcRCV = null;
    } else {
        Log.d(TAG, "Assuming that BatteryChangedReceiver is NOT registered");
    }
}    
//----- Private Code END -----



//----- Service Overrides -----
@Override
public void onCreate() {
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    RegisterBatteryChangedReceiver();

    return Service.START_STICKY; //<-- This is important!!!
}   

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

@Override
public void onDestroy() {       
    UnRegisterBatteryChangedReceiver();

    super.onDestroy();
}   
//----- Service Overrides END -----

}

然后是myWidgetProvider,其中完成了服务操作:

public class myWidgetProvider extends AppWidgetProvider {


//----- AppWidgetProvider Overrides -----
@Override
public void onEnabled(Context context) {
    super.onEnabled(context);
}

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

    // If no specific widgets requested, collect list of all
    if (appWidgetIds == null) {
        appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, FullWidgetProvider.class));
    }

    // Εδώ κάνουμε update to Widget για κάθε id ξεχωριστά
    for (int widgetId : appWidgetIds) {
        Commands.FullWidgetUpdate(context, widgetId, 0); //<-- Update το widgetId
    }

    context.startService(new Intent(context, myWidgetService.class));
}

@Override
public void onDeleted(Context context, int[] appWidgetIds) {        
    super.onDeleted(context, appWidgetIds);
}

@Override
public void onDisabled(Context context) {
    super.onDisabled(context);

    context.stopService(new Intent(context, FullWidgetService.class));

    int[] appWidgetIds = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, FullWidgetProvider.class));

    if (appWidgetIds.length != 0) {
        AppWidgetHost host = new AppWidgetHost(context, 0);

        for (int widgetId : appWidgetIds) {
            host.deleteAppWidgetId(widgetId);
        }   
    }
}
//----- AppWidgetProvider Overrides END -----       
}

希望这会有所帮助......