简体   繁体   中英

How to update time widget every minute like KWGT(Kustom Widget)?

Update

I gave up using ACTION_TIME_TICK because when click the physical button of a locked phone, it will also sent ACTION_TIME_TICK even the phone is still locked. That may make trouble if I keep pressing the key to wake up the phone.

Edit

The original purpose of this question: Update widget text every 60s(not TextClock)? Can I use ACTION_TIME_TICK to update android time widget?

I find an app called KWGT(Kustom Widget) and seems like using background?foreground service to update every minute. Its service(shows notification, so I' m sure it is service) lives longer than mine(alarm + foreground service).

How do KWGT do this? Its help site says: Kustom was using close to 0 resources when it was allowed to ignore battery optimization (because targeting old releases) and new version acts like the same. Does it mean alarm using AlarmManager.RTC mode?

I have an Android AppWidget that shows HH:mm, update every 60 seconds, it works but still has some problem. Here is what I' ve got:

  1. I' ve tried TextClock, it seems good, but I still need to update some other text when time ticks, like “count down: 3 min”、“count down: 2 min”.

  2. I use the AlarmManager, send broadcast every minute to update my widget. I 'ma little worry about my device' s battery. Another problem is, when I change my device' s time, TextClock get the new time immediately, but my widget text not.

  3. I know how TextClock do it: intent ACTION_TIME_TICK, ACTION_TIME_CHANGED, ACTION_TIMEZONE_CHANGED sent by the system. The annotation says: “You cannot receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver()”.

  4. So, should I register that receiver in a service? I think it will not work very long because my process can not run forever. How those system time widgets do this? What' s the best way in 2021? My minSdk is API 26, if there is some better way after it, I can change to higher version.

My Alarm:

 fun startAlarm() { val calendar: Calendar = Calendar.getInstance() calendar.set(Calendar.MILLISECOND, 0) calendar.set(Calendar.SECOND, 0) calendar.add(Calendar.MINUTE, 1) val alarmIntent = Intent(context, MyWidget::class.java) alarmIntent.action = MyWidget.ACTION_AUTO_UPDATE val pendingIntent = PendingIntent.getBroadcast( context, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT ) val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager // RTC does not wake the device up alarmManager.setRepeating( AlarmManager.RTC, calendar.timeInMillis, INTERVAL_MILLIS.toLong(), // Value will be forced up to 60000 as of Android 5.1 pendingIntent ) }

fun registerReceiver says:

Note: this method cannot be called from a BroadcastReceiver component; that is, from a BroadcastReceiver that is declared in an application's manifest. It is okay, however, to call this method from another BroadcastReceiver that has itself been registered at run time with registerReceiver, since the lifetime of such a registered BroadcastReceiver is tied to the object that registered it

What does this mean? Can I regeister it in class MyWidget: AppWidgetProvider()? What is the correct context?

Here is the receiver register in TextClock:

 // OK, this is gross but needed. This class is supported by the // remote views mechanism and as a part of that the remote views // can be inflated by a context for another user without the app // having interact users permission - just for loading resources. // For example, when adding widgets from a managed profile to the // home screen. Therefore, we register the receiver as the user // the app is running as not the one the context is for. getContext().registerReceiverAsUser( mIntentReceiver, android.os.Process.myUserHandle(), filter, null, getHandler() );

And registerReceiverAsUser is a function with @UnsupportedAppUsage so I think it can not help me.

Thanks a lot.

You can override listed method in the class which extends from AppWidgetProvider like this:

@Override
public void onReceive(Context context, Intent intent)
{
    super.onReceive(context, intent);        
    Log.d("TAG", "mythou--------->onReceive Reason: " + intent.getAction());
    
}

@Override
public void onEnabled(Context context) {
    // Enter relevant functionality for when the first widget is created
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_TIME_TICK);
    filter.addAction(Intent.ACTION_TIME_CHANGED);
    context.getApplicationContext().registerReceiver(this, filter);
}

The best approach is to use TextClock or AnalogClock if you can. These update each minute (or second for AnalogClock on Android 12) without your application's process needing to run.

ACTION_TIME_TICK is only sent to registered receivers, which means you won't receive it when your application isn't running. The only plausible way to keep your app running would be to use a foreground service, requiring showing a notification to the user.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM