起動時にクラッシュする広告の挙動を制御する
はじめに
この手の技術メモ、ローカルでは覚書としてこまめに書いているんですが
今週頭あたりは、マウスが効かなくなるトラブルやってまして大変申し訳無いです
はー。MBPのバッテリーが膨張しすぎて、右キーが押されたままの状態になってしまい
— close_yutori (@kimukou2628) 2017年8月29日
アクセシビリティ>キーボード・マウス>他のマウス接続時に 内蔵トラックパッドを無視
までたどり着くのに死ぬ思いした(一回バッテリ浮かして物理的に無効にして実行
デフォルト無効は無理なんかなー
MBPちゃん妊娠したんだ😅 https://t.co/0shuyYVLbl
— さきちゃんの中の人、夏太り中😭 (@serenegiant) 2017年8月30日
おばぁちゃんを妊娠させるとは(@@)冗談です。iFixitの分解レポートみると新しいのはメモリもSSDもバッテリーもディスプレーもガッツリ固定されていてなにもできないってことで、MBPが妊娠するのは計画的陳腐化ではないかと。要するに古いのはとっとと買い換えろという林檎神のご神託😇
— さきちゃんの中の人、夏太り中😭 (@serenegiant) August 30, 2017
林檎神的にはiPad+物理キーボード+CPU/メモリ/SSD強化がMBPみたいなのりかもしれないですね^^;
— さきちゃんの中の人、夏太り中😭 (@serenegiant) August 30, 2017
そのうちVPNで繋いでシンクライアント的に使うことしか許さん(🍎`ε´🍎)みたいなことを言い出すのかも^^;
いい加減ノート買えということなんでしょうか・・(苦笑
動作環境
- macOS Sierra
- 16G
- HDDタイプのiMac
- AS 3.0-Beta3
- gradle plugin 2.3.3
- gradle plugin 3.0-beta3
- gradle runtime-4.1-bin
状況的な話
これ広告ライブラリのreciverとかでよく起こるエラーなんだけど、その場合回避方法無いよね(汗 / “AdvertisingIdClient#getAdvertisingIdInfoがnullを返すのでアプリが…” https://t.co/epBLwA4qHY #Google
— close_yutori (@kimukou2628) August 23, 2017
インストール率を測る広告のContentProviderが自動的に動いてしまい、
- Firebase未初期化状態で広告ID取ろうとしてクラッシュするという話で。
- Applicationの初期化が動かない
- まあ同じようなケースで、位置情報のPermissionとらずに動いてしまいクラッシュなケースも有り
Serviceにバインドされて初期化される前にgetAdvertisingInfoを呼んじゃってるんじゃないのかなぁ?
— さきちゃんの中の人、夏太り中😭 (@serenegiant) 2017年8月23日
ServiceにもApplicationありますけどだめでした?あとReceiverとかServiceをdisableで設定しといてアプリが起動したあとで有効にするとかじゃだめなんですかねぇ?PackageManagerのsetComponentEnableSettingとか☺️
— さきちゃんの中の人、夏太り中😭 (@serenegiant) August 24, 2017
とアドバイスいただいたので下記の方法で対処してみた話
対処法
- AndroidManifest.xml
<receiver android:name="hoge.fuga.InstallTracking" android:exported="true"> <intent-filter> <action android:name="com.android.vending.INSTALL_REFERRER" /> </intent-filter> </receiver>
=>
<receiver android:name="hoge.fuga.InstallTracking" android:exported="true" android:enabled="false"> <intent-filter> <action android:name="com.android.vending.INSTALL_REFERRER" /> </intent-filter> </receiver>
@Override public void onCreate() { //TODO: でもこれすぐ初期化されるわけではない。多少遅延する FirebaseApp.init(getApplicationContext()); } private boolean initF =false; @Override protected void attachBaseContext(Context base) { if(base instanceof Activity){ if(!initF && checkPlayServices((Activity)base)){ disableComponent(base,hoge.fuga.InstallTracking,true) initF = true; } super.attachBaseContext(base); } else{ super.attachBaseContext(base); } } private boolean checkPlayServices(Activity activity) { GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); int resultCode = apiAvailability.isGooglePlayServicesAvailable(activity); if (resultCode != ConnectionResult.SUCCESS) { return false; } return true; } public void disableComponent(Context cxt, Class<?> cls, boolean disabled) { int newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED; if (!disabled) { newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED; } ComponentName compName = new ComponentName(cxt, cls); PackageManager pm = cxt.getPackageManager(); pm.setComponentEnabledSetting(compName, newState, PackageManager.DONT_KILL_APP); }
- disableComponent は下記のサイト参照
ようは、
- Activityが初期化されるタイミングまで遅延
- そこまで待てば、GooglePlayServicesも初期化されるはず
という方針。
同じような仕組みのライブラリ
Android用のDeployaGate SDK。build.gradleで組み込むだけで、エントリを呼び出すコード不要、というのが気になったので、ソース読んでみた。https://t.co/KcftCkNLOy
— Jiro@Jota+開発 (@jiro_aqua) August 19, 2017
コンテントプロバイダのonCreateでエントリ呼んでる。うまい
リリースビルドでSDK有効にするための注意書きの一つぐらいあってもいいと思う。つか、普通DeployGateにデバッグビルド上げるものなの?
— Jiro@Jota+開発 (@jiro_aqua) 2017年8月19日
よく見たら、forceApplyOnReleaseBuild=true がデフォルト設定になってた。おけ。https://t.co/KcftCkNLOy
— Jiro@Jota+開発 (@jiro_aqua) 2017年8月22日
DeployGateもContentProviderで自動初期化しているらしいんですけどね、、
特にaarだとManifestが自動マージなのでエラー起きた時に凄く悩む。。。