google play serviceを9.8.0にしてから一部の端末で起動直後にクラッシュすると報告がありました。クラッシュログによるとAdvertisingIdClient#getAdvertisingIdInfoがnullを返していることが分かりましたが、手元の端末では再現出来ず。ユーザーとやり取りしながら調査し、解決するまでのやり取りを備忘録として残しておきます。

google play developer consoleのクラッシュログ
クラッシュログを送信してもらう
Fabricを入れていましたが、起動直後のクラッシュログが取れなかったので、クラッシュログをGoogle Play Developer Consoleに送信してもらいました。以下のクラッシュログが発生していました。
1 2 3 |
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.android.gms.ads.identifier.AdvertisingIdClient$Info.getId()' on a null object reference at com.socdm.d.adgeneration.utils.AdIDUtils$1.run(Unknown Source) at java.lang.Thread.run(Thread.java:818) |
stack overflowに同じクラッシュログが報告されていないか確認
stack overflowの投稿にもgoogle play serviceを9.8.0にしてからnullを返すと言っています。
I got an issue since I bumped the play-services version to v9.8.0. I notice that the method AdvertisingIdClient#getAdvertisingIdInfo sometimes returns null (i have not identified any pattern to reproduce this case yet).
AdvertisingIdClient#getAdvertisingIdInfo sometimes returns null since v9.8.0
回答の一部でもそう思うが、有益なリンクが見つけられない。Android Stuidoでデコンパイルしてnull返すところが分かるが、ドキュメントによるとその可能性はないと書いてありました。
I’m seeing this too, but can’t find any useful links about it. If you use Android Studio to decompile the
getAdvertisingIdInfo
method you can clearly see a path where it will returnnull
but the docs don’t see to think that is possible
SDKで修正されていないか確認
私のアプリでは使用しているAdGenerationという広告のSDKでクラッシュしていたので、リリースノートを確認してみました。
ver 2.4.1.3リリース (2016/11/16)
- アプリのGoogle Play Servicesが9.8でビルドした際にクラッシュするが場合あった点を修正
SDKのソースコードが公開されていないので、何を修正したか分からなかったので、SDKのコードをデコンパイルして確認しました。
修正前のコード(ADG-2.3.1.jar)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
(new Thread(new Runnable() { public final void run() { try { Info var1; if((var1 = AdvertisingIdClient.getAdvertisingIdInfo(this.a)).getId().length() > 0) { AdIDUtils.a = var1.getId(); } AdIDUtils.b = var1.isLimitAdTrackingEnabled(); return; } catch (NoClassDefFoundError var8) { AdIDUtils.traceFromException(var8); return; } catch (IOException var9) { AdIDUtils.traceFromException(var9); return; } catch (GooglePlayServicesRepairableException var10) { AdIDUtils.traceFromException(var10); return; } catch (GooglePlayServicesNotAvailableException var11) { AdIDUtils.traceFromException(var11); return; } catch (SecurityException var12) { AdIDUtils.traceFromException(var12); } finally { AdIDUtils.b(true); } } })).start(); |
修正後のコード(ADG-2.4.2.jar)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
(new Thread(new Runnable() { public final void run() { try { Info var1; if((var1 = AdvertisingIdClient.getAdvertisingIdInfo(this.a)).getId().length() > 0) { AdIDUtils.a = var1.getId(); } AdIDUtils.b = var1.isLimitAdTrackingEnabled(); return; } catch (NoClassDefFoundError var9) { AdIDUtils.traceFromException(var9); return; } catch (IOException var10) { AdIDUtils.traceFromException(var10); return; } catch (GooglePlayServicesRepairableException var11) { AdIDUtils.traceFromException(var11); return; } catch (GooglePlayServicesNotAvailableException var12) { AdIDUtils.traceFromException(var12); } catch (SecurityException var13) { AdIDUtils.traceFromException(var13); return; } catch (NullPointerException var14) { AdIDUtils.traceFromException(var14); return; } finally { AdIDUtils.b(true); } } })).start(); |
NullPointerExceptionをキャッチするコードが追加されていました。
1 2 3 4 |
} catch (NullPointerException var14) { AdIDUtils.traceFromException(var14); return; } |
実機テスト
手元の実機での確認とれないので怖かったですが、ベータ版リリースし、ユーザーさんに確認してもらいました。
クラッシュが無くなったことを確認できたので、恐らくAdvertisingIdClient#getAdvertisingIdInfoがnullを返しているタイミングがあり、ADG-2.4.2.jarでの修正で問題ないことを判断し、アプリを全体公開しました。
まとめ
手元で確認とれなかったり、AdvertisingIdClient#getAdvertisingIdInfoがnull返す可能性があることに確証が持てなかったので、リリースをとても躊躇いました。公式ドキュメントでもnullチェックに関しては記述が無かったのでどこを見て良いか分からず。ベータリリースをしてユーザーにテストをしてもらわないといけない状況になったのでとても焦りました。
最終的にはAdvertisingIdClient#getAdvertisingIdInfoがnullを返すことが分かったので修正は問題ないことが分かりました。
この記事が同じ現象に合われている方に、少しでも役にたてばと思います。