定期更新小部件无法正常工作

时间:2015-09-09 16:45:27

标签: android service widget

我创建了一个小部件,我想每5秒定期更新一次(用于测试目的)。但是,从不调用该服务。

public class WidgetProvider extends AppWidgetProvider {


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Log.i("STATUS", "APPWIDGET onUpdate");
        final int count = appWidgetIds.length;

        for (int i = 0; i < count; i++) {
            int widgetId = appWidgetIds[i];
            String number = String.format("%03d", (new Random().nextInt(900) + 100));
            Log.i("NUMBER", number);

            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_large);
            remoteViews.setTextViewText(R.id.tv_inmonths, number);

             Intent intentt = new Intent(context, UpdateService.class);
             PendingIntent pendingIntent = PendingIntent.getService(context, 0, intentt, PendingIntent.FLAG_UPDATE_CURRENT);
             AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
             alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (5 * 1000), pendingIntent);

            appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }
    }

  @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        Log.i("STATUS", "APPWIDGET onReceive");
            Bundle extras = intent.getExtras();
            if(extras!=null) {
                AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                ComponentName thisAppWidget = new ComponentName(context.getPackageName(), WidgetProvider.class.getName());
                int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
                if (appWidgetIds.length > 0) {

                    new WidgetProvider().onUpdate(context, appWidgetManager, appWidgetIds);
                }

            }

    }
}

public final class UpdateService extends Service {


    PendingIntent pendingIntent;

    @Override
    public void onCreate(){
        Log.i("STATUS", "Service onCreate");

        String number = String.format("%03d", (new Random().nextInt(900) + 100));
        Log.i("NUMBER2", number);

        RemoteViews updateViews = new RemoteViews(this.getPackageName(), R.layout.widget_large);
        updateViews.setTextViewText(R.id.tv_inmonths, number);  //ha ez AAAA akkor is eltűnik


        ComponentName thisWidget = new ComponentName(this, WidgetProvider.class);
        AppWidgetManager manager = AppWidgetManager.getInstance(this);
        manager.updateAppWidget(thisWidget, updateViews);


    } 

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
}

清单:

<receiver android:name=".WidgetProvider" >
   <intent-filter>
      <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
   </intent-filter>
   <meta-data android:name="android.appwidget.provider"
              android:resource="@xml/widget_provider_large" />
</receiver>
<service android:enabled="true" android:name=".UpdateService" />

一旦我将小部件放在我的主屏幕上,这就是logcat:

09-09 18:36:48.330  10551-10551/myapp.myapp I/STATUS﹕ APPWIDGET onReceive
09-09 18:36:48.340  10551-10551/myapp.myapp I/STATUS﹕ APPWIDGET onUpdate
09-09 18:36:48.340  10551-10551/myapp.myapp I/NUMBER﹕ 809

有时它会调用服务,但这就是全部。

更新: 我也尝试使用Handler,尽管它每3秒运行一次,但服务只被调用一次

m_Handler = new Handler();
        mRunnable = new Runnable(){
            @Override
            public void run() {
                Log.i("STATUS", "run");
                Intent myIntent = new Intent(context, UpdateService.class);
                context.startService(myIntent);

                m_Handler.postDelayed(mRunnable, 3000);
            }
        };
        mRunnable.run();

1 个答案:

答案 0 :(得分:0)

两件事:

频繁警报

根据AlarmManager.set()的文档:

  

注意:从API 19开始,传递给此方法的触发时间被视为不精确:警报将不会在此时间之前传递,但可能会延迟并在稍后传递。操作系统将使用此策略以便批量处理&#34;在整个系统中一起报警,最大限度地减少设备需要“唤醒”的次数。并尽量减少电池使用。一般而言,只要将来安排的警报很长,就不会推迟在不久的将来安排的警报。

您可以使用adb shell dumpsys alarm确认何时安排警报,这会提供may be hard to understand

的非常详细的输出

但请注意,即使使用setExact()也可能not trigger with small intervals。相反,正如AlarmManager文档顶部所述:

  

注意:警报管理器适用于您希望在特定时间运行应用程序代码的情况,即使您的应用程序当前未运行也是如此。对于正常的计时操作(刻度,超时等),使用Handler更容易,效率更高。

<强>服务

您正在使用Service。根据{{​​3}},Service开始的startService()将继续有效,直到您在stopSelf()或其他组件调用Service内调用stopService()。由于onCreate()仅在首次创建Service时发生,因此您对startService()的后续调用不会重新触发您的代码。

相反,考虑使用Services guide - 对startService()的每次调用,您都会收到onHandleIntent()的回调,Service会立即停止完成对onHandleIntent()的所有待处理呼叫,甚至更好,只需使用IntentService - 在这种情况下没有理由拥有Service您没有执行任何长时间的处理任务(当然,您要更新startService()而不是使用BroadcastReceiver