抱歉,我完全忘记了,非常忙碌。我希望你已经明白了你需要的东西,代码片段如下,希望我没有漏掉什么。
关于小部件提供者类。
public static final String ACTION_TICK = "CLOCK_TICK";
public static final String SETTINGS_CHANGED = "SETTINGS_CHANGED";
public static final String JOB_TICK = "JOB_CLOCK_TICK";
@Override
public void onReceive(Context context, Intent intent){
super.onReceive(context, intent);
preferences = PreferenceManager.getDefaultSharedPreferences(context);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), WidgetProvider.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
if (intent.getAction().equals(SETTINGS_CHANGED)) {
onUpdate(context, appWidgetManager, appWidgetIds);
if (appWidgetIds.length > 0) {
restartAll(context);
}
}
if (intent.getAction().equals(JOB_TICK) || intent.getAction().equals(ACTION_TICK) ||
intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
|| intent.getAction().equals(Intent.ACTION_DATE_CHANGED)
|| intent.getAction().equals(Intent.ACTION_TIME_CHANGED)
|| intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
restartAll(context);
onUpdate(context, appWidgetManager, appWidgetIds);
}
}
private void restartAll(Context context){
Intent serviceBG = new Intent(context.getApplicationContext(), WidgetBackgroundService.class);
context.getApplicationContext().startService(serviceBG);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
scheduleJob(context);
} else {
AppWidgetAlarm appWidgetAlarm = new AppWidgetAlarm(context.getApplicationContext());
appWidgetAlarm.startAlarm();
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void scheduleJob(Context context) {
ComponentName serviceComponent = new ComponentName(context.getPackageName(), RepeatingJob.class.getName());
JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
builder.setPersisted(true);
builder.setPeriodic(600000);
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
int jobResult = jobScheduler.schedule(builder.build());
if (jobResult == JobScheduler.RESULT_SUCCESS){
}
}
@Override
public void onEnabled(Context context){
restartAll(context);
}
@Override
public void onDisabled(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.cancelAll();
} else {
AppWidgetAlarm appWidgetAlarm = new AppWidgetAlarm(context.getApplicationContext());
appWidgetAlarm.stopAlarm();
}
Intent serviceBG = new Intent(context.getApplicationContext(), WidgetBackgroundService.class);
serviceBG.putExtra("SHUTDOWN", true);
context.getApplicationContext().startService(serviceBG);
context.getApplicationContext().stopService(serviceBG);
}
WidgetBackgroundService
public class WidgetBackgroundService extends Service {
private static final String TAG = "WidgetBackground";
private static BroadcastReceiver mMinuteTickReceiver;
@Override
public IBinder onBind(Intent arg0){
return null;
}
@Override
public void onCreate(){
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null) {
if (intent.hasExtra("SHUTDOWN")) {
if (intent.getBooleanExtra("SHUTDOWN", false)) {
if(mMinuteTickReceiver!=null) {
unregisterReceiver(mMinuteTickReceiver);
mMinuteTickReceiver = null;
}
stopSelf();
return START_NOT_STICKY;
}
}
}
if(mMinuteTickReceiver==null) {
registerOnTickReceiver();
}
return START_STICKY;
}
@Override
public void onDestroy(){
if(mMinuteTickReceiver!=null) {
unregisterReceiver(mMinuteTickReceiver);
mMinuteTickReceiver = null;
}
super.onDestroy();
}
private void registerOnTickReceiver() {
mMinuteTickReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent){
Intent timeTick=new Intent(WidgetProvider.ACTION_TICK);
sendBroadcast(timeTick);
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mMinuteTickReceiver, filter);
}
}
重复作业类
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class RepeatingJob extends JobService {
private final static String TAG = "RepeatingJob";
@Override
public boolean onStartJob(JobParameters params) {
Log.d(TAG, "onStartJob");
Intent intent=new Intent(WidgetProvider.JOB_TICK);
sendBroadcast(intent);
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
AppWidgetAlarm类
public class AppWidgetAlarm {
private static final String TAG = "AppWidgetAlarm";
private final int ALARM_ID = 0;
private static final int INTERVAL_MILLIS = 240000;
private Context mContext;
public AppWidgetAlarm(Context context){
mContext = context;
}
public void startAlarm() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MILLISECOND, INTERVAL_MILLIS);
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(WidgetProvider.ACTION_TICK);
PendingIntent removedIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Log.d(TAG, "StartAlarm");
alarmManager.cancel(removedIntent);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), INTERVAL_MILLIS, pendingIntent);
}
public void stopAlarm()
{
Log.d(TAG, "StopAlarm");
Intent alarmIntent = new Intent(WidgetProvider.ACTION_TICK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
}
清单文件
<receiver android:name=".services.SlowWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="CLOCK_TICK" />
</intent-filter>
<intent-filter>
<action android:name="JOB_CLOCK_TICK" />
</intent-filter>
<intent-filter>
<action android:name="SETTINGS_CHANGED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.TIME_SET" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DATE_CHANGED" />
</intent-filter>
<intent-filter>
<action android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.ACTION_DREAMING_STOPPED" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/slow_widget_info" />
</receiver>
<service
android:name=".services.RepeatingJob"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"/>
<service android:name=".services.WidgetBackgroundService" />
setRepeating()
,选择了setExactAndAllowWhileIdle
来解决这个问题,但仍然存在 - NikiforosAlarmManager
,它有时每分钟更新一次,有时更新较慢(长达五到六分钟)。闹钟小部件如何工作对我来说仍然是个谜。 - tendays