起動時にクラッシュする広告の挙動を制御する

はじめに

この手の技術メモ、ローカルでは覚書としてこまめに書いているんですが

今週頭あたりは、マウスが効かなくなるトラブルやってまして大変申し訳無いです

いい加減ノート買えということなんでしょうか・・(苦笑


動作環境

  • macOS Sierra
  • 16G
  • HDDタイプのiMac
  • AS 3.0-Beta3
  • gradle plugin 2.3.3
  • gradle plugin 3.0-beta3
  • gradle runtime-4.1-bin

状況的な話

インストール率を測る広告のContentProviderが自動的に動いてしまい

  • Firebase未初期化状態で広告ID取ろうとしてクラッシュするという話で。
    • Applicationの初期化が動かない
  • まあ同じようなケースで、位置情報のPermissionとらずに動いてしまいクラッシュなケースも有り

とアドバイスいただいたので下記の方法で対処してみた話

対処法

  • 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も初期化されるはず

という方針。

同じような仕組みのライブラリ

DeployGateもContentProviderで自動初期化しているらしいんですけどね、、

特にaarだとManifestが自動マージなのでエラー起きた時に凄く悩む。。。