對不起,我完全忘了,很忙..那麼,我希望你有你想要的東西,片段正在追隨,希望我沒有忘記一些東西。
對小部件提供者類。
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 {
// stop alarm
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();
}
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
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);
}
}
RepeatingJob類
@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);
// needs RTC_WAKEUP to wake the device
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" />
你真的解決了這個問題嗎? 我面臨幾乎相同的問題。我不在乎精確到秒,我關心的是不停止,在Android 6+設備上發生的事情。 我跳過了'setRepeating()'並去了'setExactAndAllowWhileIdle'來解決這個問題,但仍然 – Nikiforos
不,我管理的最好的是AlarmManager,它每分鐘更新一次,有時更慢(最多五六分鐘)。時鐘小工具如何工作對我來說是個謎。 – tendays
@Nikiforos:你解決了這個問題嗎?我被困在同樣的問題上這麼多天。 – user1090751