Android:我可以阻止Java类(来自外部库)在运行时实例化

时间:2015-11-06 11:32:49

标签: java android admob

上下文:

我使用AdMob中介在我的应用中显示横幅广告。 我整合了Millennial广告网络SDK和Millennial AdMob适配器。

问题:我的应用支持Android API 9+,而Millennial SDK支持API 16+。更糟糕的是,SDK没有优雅地失败(没有向AdMob中介层返回任何广告,以便它可以继续沿着中介瀑布走下去),SDK在运行Android<的设备上崩溃了。 16(Fatal Exception: java.lang.NoSuchMethodError android.webkit.WebSettings.setAllowUniversalAccessFromFileURLs

显然,千禧一代的开发者并不打算解决这个问题,他们建议发布2个不同的APK(“没有他们的SDK”“16”,而他们的SDK使用“16+”),这是一个麻烦的解决方案。

我更喜欢更简单的解决方案:在运行Android API的设备上< 16,我想重现AdMob适配器丢失时会发生什么:AdMob中介只是转到下一个网络。 这意味着在我实例化AdMod中介横幅之前,卸载或删除 Millennial适配器类。

问题

有没有办法在运行时阻止给定类(来自第三方库)的任何未来瞬间? (例如,通过强制ClassNotFound异常)

3 个答案:

答案 0 :(得分:2)

使用两个广告单元。您可以在AdMob.com上设置两个横幅广告单元,一个在调解堆栈中使用MillennialMedia,另一个不在。然后,您可以在Bonatti建议的运行时检查设备的API级别,并在请求广告之前在AdView上set the ad unit ID进行检查。

如果MillennialMedia不在正在使用的广告单元的中介配置中,则Google移动广告SDK不会对其适配器进行实例化。

答案 1 :(得分:1)

我和你的情况完全相同。

经过大量的研究和类加载器的黑魔法等,我发现了一个肮脏但有效的解决方案:

// At onCreate() or wherever it makes sense

if (Build.VERSION.SDK_INT < 16) {
    // Must be done before requesting the first ad
    disableMMediaAdapter();
}
m_adView.loadAd(adRequest);

// ...

private void disableMMediaAdapter()
{
    try {
        Field fInitialized = MMSDK.class.getField("initialized");
        fInitialized.setAccessible(true);
        fInitialized.set(null, true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

通过欺骗SDK使其相信它已经初始化,当通过它请求广告并且将调用下一个中介适配器时,它将很难失败。

只要他们不改变他们的课程设置太多就行了。

答案 2 :(得分:0)

  

有没有办法阻止在运行时给定类的任何未来瞬间? (例如,通过强制ClassNotFound异常)

您可以在加载适配器之前检查操作系统版本,以及是否低于阈值

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.THE_VERSION_I_WANT_MINIMUM) {
   // doStuffs()
} else {
   throw new MyException("Stuffs have stuffened...");
}