Open Anton-V-K opened 2 years ago
@tananaev , I had some free time to look into this feature implementation, and it doesn't seem to be sophisticated.
I've managed to generate new widget in Android Studio, and with minor code changes it works quite good.
The main concern is the place where I can update widget's state when the service is started/stopped.
I've added one line to onSharedPreferenceChanged
(in MainFragment
):
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
if (key == KEY_STATUS) {
if (sharedPreferences.getBoolean(KEY_STATUS, false)) {
startTrackingService(checkPermission = true, initialPermission = false)
} else {
stopTrackingService()
}
(requireActivity().application as MainApplication).handleRatingFlow(requireActivity())
StatusWidget.updateWidgets(requireContext()) // <<<
} else if (key == KEY_DEVICE) {
findPreference<Preference>(KEY_DEVICE)?.summary = sharedPreferences.getString(KEY_DEVICE, null)
}
}
Is this the right place?
I'll test my build on the device where the system kills the application to check whether the new status widget solves the problem.
Probably makes sense to update it somewhere inside startTrackingService
.
OK. Same update should also be performed from stopTrackingService
.
I'm ready to commit my changes.
I'll create a new branch statius_widget
, so my changes will be isolated until they are ready for merging into master
.
The widget really solves the problem with keeping app alive, so the feature may be useful for others as well.
while testing my build I've noticed that the widget isn't updated if the service started/stoped via the shortcut.
Probably the update should also be performed from ShortcutActivity.executeAction
?
I was also thinking about adding service-related broadcasts to the widget's intents filter, so the widget could be decoupled from the rest:
<receiver
android:name=".StatusWidget"
android:label="@string/status_widget_label"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="org.traccar.action.SERVICE_STARTED" />
<action android:name="org.traccar.action.SERVICE_STOPPED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/status_widget_info" />
</receiver>
Unfortunately this approach doesn't seem to work on modern Androids (8.0+), probably because of Broadcast Limitations.
I've managed to register for service-related intents in the code of StatusWidget
:
override fun onEnabled(context: Context) {
// Enter relevant functionality for when the first widget is created
val filter = IntentFilter()
filter.addAction(TrackingService.ACTION_STARTED)
filter.addAction(TrackingService.ACTION_STOPPED)
// Note: we must register through the app context as a workaround
// for 'BroadcastReceiver components are not allowed to register to receive intents'
context.applicationContext.registerReceiver(Companion, filter)
}
If anyone is willing to test the functionality until it is officially available, here is the test build TraccarClient-app-regular-debug-81.apk.zip It has different package name and some icons are recolored, so the app can be installed and used side-by-side with the original one (the settings aren't shared between them as well). This build had been under test on Android 9 (Oukitel Y4800) for a month, and I can confirm the app keeps running while you have the status widget on a home screen.
I have tested the widget and it seems to work. It would be cool if this feature would be available in the main release. I would suggest two optimizations:
It would be handy to have a widget which could show the application status - whether its service running or not. When the widget is clicked, the main window may be opened.
Is your feature request related to a problem? Please describe. On some smartphones with too restrictive built-in task managers (Oukitel Y4800 with Android 9 is a typical example), the application can be closed (killed) by the system despite all optimization settings (ignoring battery optimization, white-listing, etc.).
Describe the solution you'd like A possible solution (a kind of workaround) to keep the app alive is to add an updatable widget (to the home screen), which will let system know that the app shouldn't be killed (for power optimization reasons).
Additional context Refer to the forum thread for more details.