Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 小部件没有更新视图,也没有显示错误_Android_Android Widget_Broadcastreceiver_Android View_Android Appwidget - Fatal编程技术网

Android 小部件没有更新视图,也没有显示错误

Android 小部件没有更新视图,也没有显示错误,android,android-widget,broadcastreceiver,android-view,android-appwidget,Android,Android Widget,Broadcastreceiver,Android View,Android Appwidget,我正在开发一个运行中没有任何错误的小部件,但是我的小部件的ImageView没有更新,也没有给出任何错误。这让我对自己做错了什么感到困惑。代码如下:- BroadcastReceiver _broadcastReceiver; GetDrawableResources getDrawableResources = new GetDrawableResources(); private final SimpleDateFormat _sdfWatchTime = new SimpleDateFor

我正在开发一个运行中没有任何错误的小部件,但是我的小部件的
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是正确的,函数正在按其应该的方式执行,但视图没有更新。它们与以前相同。

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

当WidgetProvider(oneEnabled,onUpdate)的方法完成执行时,系统将销毁WidgetProvider类,您的broadcastReceiver也是如此。正如你所看到的,这里没有错误,也没有接收错误

为了实现您想要的功能,您需要一个更“稳定”的应用程序组件来容纳您的broadcastReceiver,这样的组件就是服务。即使应用程序停止运行,服务也会继续运行,因此它是此类作业的良好组件

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

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

编辑 是来自谷歌的应用程序小部件文档(大约在中间)说明:

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

在我的appwidget中,我和你有过类似的问题,结果是由我的appwidgetprovider的生命周期造成的,所以我基于此回答了你。然而,根据您的观察,您是对的,您的小部件应该至少在第一次更新时使用当前时间进行自我更新,因此仔细查看它,我发现您正在使用一个自定义的getDrawableResources类来获取资源(您能用它的代码编辑您的问题吗?),并且您正在使用getDrawableResources.setTimeDrawable(时间[0]);为了获得可绘制的,也许您应该将其更改为getDrawableResources.getTimeDrawable(时间[0])

编辑2

下面是说明我的建议的代码。首先是我们注册电池接收器的服务

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 -----

}
类FullWidgetBatteryChangedReceiver扩展了BroadcastReceiver{
//-----广播接收机覆盖-----
@凌驾
公共void onReceive(上下文cx、意图){
Log.d(“电池更换接收器”、“接收”);

命令。FullWidgetUpdate(cx,-1,0);//我不知道这些WidgetProvider类和broadcastReceiver在执行后被销毁。我正在阅读有关该服务的信息,如果它解决了我的问题,请将答案标记为正确。谢谢。我想澄清一些事情。您说过,在执行后,onEnabled、onUpdate和broadcastReceiver被销毁,但每分钟我的broadcastReceiver都会被销毁nUpdate,然后最后调用updateAppWidget。因此,如果updateAppWidget每分钟都被调用,那么视图必须更新,因为更新是在这个方法中完成的。我说的有什么不对吗?
getDrawableResources
是我创建的一个自定义类,它没有扩展或实现任何内容。它是一个简单的类。它返回t基于发送时间[0]的图像id。例如-if time[0]是8那么运行在
getDrawableResources
中的代码是案例8:time=R.drawable.time_8;break;@RohanKandwal是这样的,但是看看我的第二次编辑,我在其中添加了一些说明这种方法的代码。谢谢。@RohanKandwal命令是一个自定义的静态类,我创建它是为了保持事情的有序性。哟你可以用你的updatewidget函数替换这一行。对于给你带来的不便,我深表歉意,但我的代码只是为了说明,不是一个完整的工作代码。顺便说一句,我很高兴你解决了你的问题。谢谢。
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 -----       
}