1

I have a widget. Finishing the SettingsActivity loads data from the Internet and displays it inside a ListView. This works on pre-Oreo and Oreo devices.

But the following two behaviors are not triggered from any activity, but from clicks on the widget itself (= background) and work only on pre-Oreo devices :

  • Clicking on the ListView itself opens the browser to navigate to the url of that item.

  • Clicking on a button above the ListView opens the settings activity.

But on Oreo after getting exceptions like

Not allowed to start service Intent

I switched from IntentService to JobIntentService because :

From developer.android.com :

IntentService is subject to these restrictions IntentService is a service, and is therefore subject to the new restrictions on background services. As a result, many apps that rely on IntentService do not work properly when targeting Android 8.0 or higher. For this reason, Android Support Library 26.0.0 introduces a new JobIntentService class, which provides the same functionality as IntentService but uses jobs instead of services when running on Android 8.0 or higher.

Manifest :

<service
            android:name="com.example.MyWidgetService"
            android:permission="android.permission.BIND_JOB_SERVICE"/>

Service :

public class MyWidgetService extends JobIntentService {
    @Override
    protected void onHandleWork(Intent intent) {
        XLog.i("onHandleWork"); <-- never printed to log
    }
}

In Widget's RemoteViewsService :

remote.setOnClickPendingIntent(R.id.open, new Intent(..some-code..));

The modified code works on pre-Oreo devices but on Oreo clicking neither on a list-view item nor on the button does nothing, MyWidgetService.onHandleWork() is never invoked.

Any idea what I'm doing wrong ?

Wolf359
  • 2,620
  • 4
  • 42
  • 62

1 Answers1

2

JobIntentService isn't a way for handle clicks with PendingIntent, cuz it's not triggered it shortly (with JobIntentService it can receive a callback more than a minute or more...). So i just start service with startForegroundService, cuz it's guaranteed call you service as user click on your RemoteView.

P.S. Yes, you need to show a notification (something like AppNameWidget updating...) but it's works perfectly on oreo.

HeyAlex
  • 1,666
  • 1
  • 13
  • 31
  • But this really sucks from UX perspective. – c0dehunter Sep 18 '18 at 09:47
  • @PrimožKralj if you now better way, let us know about it. Cuz i still didnt find better solution :( – HeyAlex Sep 18 '18 at 11:19
  • I am investigating `goAsync()` method from `BroadcastReceiver` and then execute network calls in a separate thread (see link 1 below). The problem is that you need to finish in 10sec, so you need rather short network timeouts which could be a problem when there is bad internet connection or some server issues. If timeout happens, I will mitigate by rescheduling Alarm (my widget updates are called from Alarm because I need to update at 5min interval) to run a few seconds later to re-try widget update and keep doing this for a few times in case data is still not available. What do you think? – c0dehunter Sep 18 '18 at 11:27
  • See these links for more info on `goAsync()`: [1](https://stackoverflow.com/a/22741384/1181261), [2](https://stackoverflow.com/a/46181049/1181261), [3](https://developer.android.com/reference/android/content/BroadcastReceiver.html#goAsync()). – c0dehunter Sep 18 '18 at 11:27
  • @PrimožKralj i know about goAsync(), but when i was trying (1 year ago) to implement this way, getting trouble with unpredictable situations with broadcast lifetime actually. So i just make all updates via service and make small library as well (https://github.com/HeyAlex/WidgetUpdateHelper) . As about your way updating widget in case that you describe, found it rly nice idea. I really hate that bad android widget api, hope you achive that you want :D – HeyAlex Sep 18 '18 at 11:48
  • I am fighting this widget updating problem for a while now too. I know your library, it seems nice. My app offers multiple widgets from 3 widget providers (e.g. you can have 5 instances of widget A , 5 of widget B and 5 of widget C) and when update button on one of them is clicked, all of them must be updated. So I think if I use your library, 3 notifications will show, one for each widget provider, which would not look good. Can you confirm this? – c0dehunter Sep 18 '18 at 12:03
  • it will be updated one by one, every updating will show notification, and remove when finish, so it will show 15 times notification but in status bar will be only one. Not the best idea use my library, cuz it's still in internal usage, and i don't know how other ppl wants to use it, that's why the api of lib is still inconvenient :( – HeyAlex Sep 18 '18 at 12:20
  • @HeyAlex the problem is: users hate the foreground notifications. Also, in my weather app with 10000+ active users, even with StartForeground() in the onCreate() of IntentService - I still see some ANRs per day from Android 8+ user base. Currently I tries to move on WorkManager + goAsync(). Btw, OneTimeWorkRequest in the onUpdate() appWidgetProvider for me lead to loop after updateAppWidget() in Worker, not sure who, it worked great with IntentService.... – Alex Oct 28 '18 at 21:37