Errore ANR “Broadcast of Intent {act = com.google.firebase.INSTANCE_ID_EVENT” … “FirebaseInstanceIdInternalReceiver” per Android 7.1 e 8.0

Abbiamo un’app per Android con molti errori ANR segnalati di recente. Questo si verifica solo su Android 7.1 e 8.0 (non su es. 4.4, 5.0 o 6.0). L’ANR è:

Broadcast of Intent { act=com.google.firebase.INSTANCE_ID_EVENT flg=0x14 cmp=com.our.package.name/com.google.firebase.iid.FirebaseInstanceIdInternalReceiver (has extras) }

La domanda è: perché otteniamo questo ANR e cosa possiamo fare per evitare questo? Si noti che questo funziona bene su versioni precedenti di Android, che a mio avviso dimostra che non facciamo nessuno dei rookie-errori che causano ANR.

Sto attraversando un periodo davvero difficile per riprodurre questo bug. Dal momento che è solo su Android 7.1 e 8.0, penso che potrebbe avere a che fare con la nuova modalità doze e il risparmio della batteria, ma anche usando adb shell dumpsys deviceidle force-idle ecc. Mentre il test non riproduce questo problema, neanche mettendo in SystemClock.sleep(20000); diversi luoghi.

Il nostro codice per InstanceIdService è:

 public class InstanceIdService extends FirebaseInstanceIdService { private Analytics mAnalytics; @Override public void onCreate() { super.onCreate(); mAnalytics = new AnalyticsImpl(); boolean isFullVersion = getApplicationContext().getPackageName().endsWith("full"); mAnalytics.init(getApplicationContext(), isFullVersion); } @Override public void onTokenRefresh() { boolean initialLoginSucceeded = OurAppNameApplication.getInstance().getSettings().getInitialLoginSucceeded(); mAnalytics.logEvent("FCM_Token_Refresh_Triggered", "initialLoginSucceeded", String.valueOf(initialLoginSucceeded)); if (initialLoginSucceeded) { // We only report the FCM token to our server if the user has logged in at least once OurAppNameApplication.getInstance().getOurAppNameService().registerDeviceWithRetry(); } } } 

Utilizziamo Google Play Services e Firebase versione 11.2.0. La nostra targetSdkVersion è 25.

PS: Il codice mAnalytics.init(...) sopra ci dà un avvertimento di StrictMode, poiché inizializza Flurry . Ma questo è l’accesso al disco, non il traffico di rete. E inserendo SystemClock.sleep(20000); in questa posizione non triggers alcun ANR.

Perché otteniamo un ANR e cosa possiamo fare per evitarlo?

Modifica: Come da suggerimento nel commento di Bob Snyder, ho provato a testare con adb shell cmd appops set com.our.package.name RUN_IN_BACKGROUND ignore . Tuttavia, questo non produce alcun ANR, ma interrompe il funzionamento del nostro ricevitore Broadcast, come mostrato in logcat:

 09-21 10:39:25.314 943-6730/? W/ActivityManager: Background start not allowed: service Intent { act=com.google.firebase.INSTANCE_ID_EVENT pkg=com.our.package.name cmp=com.our.package.name/com.our.package.service.notifications.InstanceIdService (has extras) } to com.our.package.name/com.our.package.service.notifications.InstanceIdService from pid=4062 uid=10139 pkg=com.our.package.name 09-21 10:39:25.314 4062-4062/com.our.package.name E/FirebaseInstanceId: Error while delivering the message: ServiceIntent not found. 

La mia conclusione è che questo potrebbe non essere un modo corretto per riprodurre questo errore ANR.

Per completezza: tutti i comandi ADB utilizzati durante il test sono:

 adb shell dumpsys deviceidle force-idle adb shell dumpsys battery unplug adb shell am set-inactive com.our.package.name true adb install -r our-app.apk adb shell cmd appops set com.our.package.name RUN_IN_BACKGROUND ignore 

(In realtà, l’ultima riga viene eseguita più volte in parallelo con l’ adb install modo da essere sicuri che abbia effetto prima che l’installazione e il ripristino (delle impostazioni) vengano eseguiti e il token di registrazione Firebase venga automaticamente aggiornato dopo l’installazione.)

Prova l’ultima versione degli Play Services SDKs di Firebase e Play Services SDKs (v. 11.4.2). Cambia anche il tuo targetSDKVersion su 26 e BuildToolsVersion su 26.0.2.

Inoltre, ho ricevuto lo stesso errore per i dispositivi Google Pixel / Nexus in esecuzione su Android 8.0. Non ho ricevuto alcun nuovo rapporto dopo aver aggiornato tutte le librerie.

Perché otteniamo questo ANR e cosa possiamo fare per evitarlo?

Non sono proprio sicuro del motivo per cui ciò sta accadendo. Ho anche contattato il supporto di Firebase per conoscerne le ragioni, ma hanno chiesto l’intervento di MCV e poiché non so quale sia la causa del problema non sono stato in grado di fornire mcve. Sto utilizzando l’autenticazione Firebase solo nella mia app, quindi credo fermamente che il problema abbia a che fare con questo.