0

我正在开发一个小部件,它运行时没有任何错误,但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 是正确的,并且函数正在执行,但视图没有更新。它们和以前一样。

4

1 回答 1

1

您的方法有一个有效的基础,但是您正在 onEnabled 方法中创建和注册您的广播接收器,该方法又属于 WidgetProvider 类。

当 WidgetProvider 的方法(onEnabled,onUpdate)执行完毕后,WidgetProvider 类将被系统销毁,您的 broadcastReceiver 也将被销毁。如您所见,这里没有错误,但也没有收到。

为了做你想做的事,你需要一个更“稳定”的应用程序组件来保存你的广播接收器,这样的组件就是一个服务。即使您的应用程序停止,服务也会继续运行,因此它是此类作业的良好组件。

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

从我的建议开始的好地方就在这里......

编辑 是来自谷歌的 App Widgets 的文档(大约在中间):

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

希望这可以帮助...

于 2013-06-28T15:16:16.520 回答