Skip to content

Instantly share code, notes, and snippets.

@robUx4
Last active August 29, 2015 13:58

Revisions

  1. robUx4 revised this gist Apr 14, 2014. 1 changed file with 31 additions and 29 deletions.
    60 changes: 31 additions & 29 deletions ActivityWithAds.java
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,9 @@
    package com.levelup.touiteur;

    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;

    import android.annotation.SuppressLint;
    import android.app.Activity;
    @@ -47,60 +49,47 @@ public abstract class ActivityWith_Ads extends Activity {
    */
    private static boolean adClicked;

    static {
    static {
    List<IntentFilter> badFilters = new ArrayList<IntentFilter>(12);

    // intents from the Play Store manifest
    IntentFilter playStoreAssetBrowser = new IntentFilter();
    playStoreAssetBrowser.addAction(Intent.ACTION_MAIN);
    playStoreAssetBrowser.addAction(Intent.ACTION_SEARCH);
    playStoreAssetBrowser.addCategory(Intent.CATEGORY_LAUNCHER);
    playStoreAssetBrowser.addCategory("android.intent.category.APP_MARKET"); // Intent.CATEGORY_APP_MARKET
    playStoreAssetBrowser.addCategory(Intent.CATEGORY_DEFAULT);
    badFilters.add(playStoreAssetBrowser);

    IntentFilter playStoreMarket = new IntentFilter();
    playStoreMarket.addAction(Intent.ACTION_VIEW);
    playStoreMarket.addAction("android.nfc.action.NDEF_DISCOVERED");
    playStoreMarket.addAction("com.google.android.finsky.NAVIGATIONAL_SUGGESTION");
    playStoreMarket.addCategory(Intent.CATEGORY_BROWSABLE);
    playStoreMarket.addCategory(Intent.CATEGORY_DEFAULT);
    playStoreMarket.addDataScheme("market");
    playStoreMarket.addDataAuthority("search", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_LITERAL);
    playStoreMarket.addDataScheme("http");
    playStoreMarket.addDataAuthority("market.android.com", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_LITERAL);
    playStoreMarket.addDataScheme("http");
    playStoreMarket.addDataAuthority("market.android.com", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_PREFIX);
    playStoreMarket.addDataScheme("https");
    playStoreMarket.addDataAuthority("market.android.com", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_LITERAL);
    playStoreMarket.addDataScheme("https");
    playStoreMarket.addDataAuthority("market.android.com", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_PREFIX);
    badFilters.add(filterWithData(playStoreMarket, "market", "search"));
    badFilters.add(filterWithData(playStoreMarket, "market", "details"));
    badFilters.add(filterWithData(playStoreMarket, "http", "market.android.com", "/", PatternMatcher.PATTERN_LITERAL));
    badFilters.add(filterWithData(playStoreMarket, "http", "market.android.com", "/", PatternMatcher.PATTERN_PREFIX));
    badFilters.add(filterWithData(playStoreMarket, "https", "market.android.com", "/", PatternMatcher.PATTERN_LITERAL));
    badFilters.add(filterWithData(playStoreMarket, "https", "market.android.com", "/", PatternMatcher.PATTERN_PREFIX));

    IntentFilter playStoreStore = new IntentFilter();
    playStoreStore.addAction(Intent.ACTION_VIEW);
    playStoreStore.addAction("android.nfc.action.NDEF_DISCOVERED");
    playStoreStore.addCategory(Intent.CATEGORY_BROWSABLE);
    playStoreStore.addCategory(Intent.CATEGORY_DEFAULT);
    playStoreStore.addDataScheme("http");
    playStoreStore.addDataAuthority("play.google.com", null);
    playStoreStore.addDataPath("/store", PatternMatcher.PATTERN_PREFIX);
    playStoreStore.addDataScheme("https");
    playStoreStore.addDataAuthority("play.google.com", null);
    playStoreStore.addDataPath("/store", PatternMatcher.PATTERN_PREFIX);
    playStoreStore.addDataScheme("http");
    playStoreStore.addDataAuthority("play.google.com", null);
    playStoreStore.addDataPath("/redeem", PatternMatcher.PATTERN_PREFIX);
    playStoreStore.addDataScheme("https");
    playStoreStore.addDataAuthority("play.google.com", null);
    playStoreStore.addDataPath("/redeem", PatternMatcher.PATTERN_PREFIX);
    badFilters.add(filterWithData(playStoreStore, "http", "play.google.com", "/store", PatternMatcher.PATTERN_PREFIX));
    badFilters.add(filterWithData(playStoreStore, "https", "play.google.com", "/store", PatternMatcher.PATTERN_PREFIX));
    badFilters.add(filterWithData(playStoreStore, "http", "play.google.com", "/redeem", PatternMatcher.PATTERN_PREFIX));
    badFilters.add(filterWithData(playStoreStore, "https", "play.google.com", "/redeem", PatternMatcher.PATTERN_PREFIX));

    IntentFilter playStorePurchase = new IntentFilter();
    playStorePurchase.addAction("com.android.vending.billing.PURCHASE");
    playStorePurchase.addCategory(Intent.CATEGORY_DEFAULT);
    badFilters.add(playStorePurchase);

    badIntentFilters = new IntentFilter[] { playStoreAssetBrowser, playStoreMarket, playStoreStore, playStorePurchase, };
    badIntentFilters = badFilters.toArray(new IntentFilter[]{});
    }

    private static boolean isBadIntent(Context context, Intent intent) {
    @@ -252,6 +241,19 @@ protected void onStart() {
    super.onStart();
    }

    private static IntentFilter filterWithData(IntentFilter baseFilter, String scheme, String authority) {
    IntentFilter result = new IntentFilter(baseFilter);
    result.addDataScheme(scheme);
    result.addDataAuthority(authority, null);
    return result;
    }

    private static IntentFilter filterWithData(IntentFilter baseFilter, String scheme, String authority, String path, int type) {
    IntentFilter result = filterWithData(baseFilter, scheme, authority);
    result.addDataPath(path, type);
    return result;
    }

    @Override
    public void setIntent(Intent newIntent) {
    if (null == newIntent) {
  2. robUx4 created this gist Apr 2, 2014.
    263 changes: 263 additions & 0 deletions ActivityWithAds.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,263 @@
    package com.levelup.touiteur;

    import java.lang.reflect.Field;
    import java.util.HashMap;

    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.app.Instrumentation;
    import android.content.ContentResolver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.PatternMatcher;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnTouchListener;
    import android.view.ViewGroup;

    public abstract class ActivityWith_Ads extends Activity {

    private final static String TAG = "AdSafe";
    private final static boolean HAS_ADS = true;

    /**
    * Extra field you should put on your external browser Intents to make sure they're not blocked
    */
    public static final String EXTRA_BYPASS_BLOCK = "com.levelup.touiteur.extra.urlbypass";

    private static final IntentFilter badIntentFilters[];
    /**
    * The {@link android.app.Instrumentation Instrumentation} of the process where filters are added
    */
    private static Instrumentation mInstrumentation;
    /**
    * The list of {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} currently registered to block some intents
    * for the whole process
    */
    private static Instrumentation.ActivityMonitor registeredMonitors[];

    /**
    * Flag to indicate an ad was clicked so the resulting Intent launched is OK
    */
    private static boolean adClicked;

    static {
    // intents from the Play Store manifest
    IntentFilter playStoreAssetBrowser = new IntentFilter();
    playStoreAssetBrowser.addAction(Intent.ACTION_MAIN);
    playStoreAssetBrowser.addAction(Intent.ACTION_SEARCH);
    playStoreAssetBrowser.addCategory(Intent.CATEGORY_LAUNCHER);
    playStoreAssetBrowser.addCategory("android.intent.category.APP_MARKET"); // Intent.CATEGORY_APP_MARKET
    playStoreAssetBrowser.addCategory(Intent.CATEGORY_DEFAULT);

    IntentFilter playStoreMarket = new IntentFilter();
    playStoreMarket.addAction(Intent.ACTION_VIEW);
    playStoreMarket.addAction("android.nfc.action.NDEF_DISCOVERED");
    playStoreMarket.addAction("com.google.android.finsky.NAVIGATIONAL_SUGGESTION");
    playStoreMarket.addCategory(Intent.CATEGORY_BROWSABLE);
    playStoreMarket.addCategory(Intent.CATEGORY_DEFAULT);
    playStoreMarket.addDataScheme("market");
    playStoreMarket.addDataAuthority("search", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_LITERAL);
    playStoreMarket.addDataScheme("http");
    playStoreMarket.addDataAuthority("market.android.com", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_LITERAL);
    playStoreMarket.addDataScheme("http");
    playStoreMarket.addDataAuthority("market.android.com", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_PREFIX);
    playStoreMarket.addDataScheme("https");
    playStoreMarket.addDataAuthority("market.android.com", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_LITERAL);
    playStoreMarket.addDataScheme("https");
    playStoreMarket.addDataAuthority("market.android.com", null);
    playStoreMarket.addDataPath("/", PatternMatcher.PATTERN_PREFIX);

    IntentFilter playStoreStore = new IntentFilter();
    playStoreStore.addAction(Intent.ACTION_VIEW);
    playStoreStore.addAction("android.nfc.action.NDEF_DISCOVERED");
    playStoreStore.addCategory(Intent.CATEGORY_BROWSABLE);
    playStoreStore.addCategory(Intent.CATEGORY_DEFAULT);
    playStoreStore.addDataScheme("http");
    playStoreStore.addDataAuthority("play.google.com", null);
    playStoreStore.addDataPath("/store", PatternMatcher.PATTERN_PREFIX);
    playStoreStore.addDataScheme("https");
    playStoreStore.addDataAuthority("play.google.com", null);
    playStoreStore.addDataPath("/store", PatternMatcher.PATTERN_PREFIX);
    playStoreStore.addDataScheme("http");
    playStoreStore.addDataAuthority("play.google.com", null);
    playStoreStore.addDataPath("/redeem", PatternMatcher.PATTERN_PREFIX);
    playStoreStore.addDataScheme("https");
    playStoreStore.addDataAuthority("play.google.com", null);
    playStoreStore.addDataPath("/redeem", PatternMatcher.PATTERN_PREFIX);

    IntentFilter playStorePurchase = new IntentFilter();
    playStorePurchase.addAction("com.android.vending.billing.PURCHASE");
    playStorePurchase.addCategory(Intent.CATEGORY_DEFAULT);

    badIntentFilters = new IntentFilter[] { playStoreAssetBrowser, playStoreMarket, playStoreStore, playStorePurchase, };
    }

    private static boolean isBadIntent(Context context, Intent intent) {
    if (null != intent.getComponent() && TextUtils.equals(intent.getComponent().getPackageName(), context.getPackageName())) {
    // this intent is launching some of our activities
    if (TextUtils.equals(intent.getComponent().getClassName(), "com.admarvel.android.ads.AdMarvelActivity")) {
    Intent testIntent = new Intent(Intent.ACTION_VIEW);
    testIntent.addCategory(Intent.CATEGORY_BROWSABLE);
    testIntent.setData(Uri.parse(intent.getStringExtra("url")));
    intent = testIntent; // fall through to test the target that wasn't clicked
    } else if (TextUtils.equals(intent.getComponent().getClassName(), "com.admarvel.android.ads.AdMarvelVideoActivity")) {
    // this Intent was launched without the user clicking in the ad area
    Log.e(TAG, "AdMarvelVideoActivity launched without click intent:" + intent + " extras:" + intent.getExtras());
    } else if (TextUtils.equals(intent.getComponent().getClassName(), "com.google.ads.AdActivity")) {
    Bundle adData = intent.getBundleExtra("com.google.ads.AdOpener");
    if ("intent".equals(adData.get("action"))) {
    Object params = adData.get("params");
    if (params instanceof HashMap) {
    Intent testIntent = new Intent(Intent.ACTION_VIEW);
    testIntent.addCategory(Intent.CATEGORY_BROWSABLE);
    testIntent.setData(Uri.parse(((HashMap<String, String>) params).get("u")));
    intent = testIntent; // fall through to test the target that wasn't clicked
    }
    }
    } else if (TextUtils.equals(intent.getComponent().getClassName(), "com.millennialmedia.android.MMActivity")) {
    // this Intent was launched without the user clicking in the ad area
    Log.e(TAG, "MMActivity launched without click intent:" + intent + " extras:" + intent.getExtras());
    } else if (TextUtils.equals(intent.getComponent().getClassName(), "com.millennialmedia.android.VideoPlayer")) {
    // this Intent was launched without the user clicking in the ad area
    Log.e(TAG, "VideoPlayer launched without click intent:" + intent + " extras:" + intent.getExtras());
    } else {
    return false; // all other activities we know about should not be blocked
    }
    }

    ContentResolver resolver = context.getContentResolver();
    for (IntentFilter monitor : badIntentFilters) {
    if (monitor.match(resolver, intent, true, "IntentBlock") >= 0) {
    Log.d(TAG, "bad intent detected intent:" + intent + " extras:" + intent.getExtras());
    return true;
    }
    }
    return false;
    }

    public static boolean isIntentLegal(Context context, Intent intent) {
    if (adClicked || intent.hasExtra(EXTRA_BYPASS_BLOCK))
    return true;

    return !isBadIntent(context, intent);
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
    // it will be done in the other version otherwise
    if (isIntentLegal(this, intent)) {
    unregisterIntentBlockers();
    }
    }

    super.startActivityForResult(intent, requestCode);
    }

    @SuppressLint("NewApi")
    @Override
    public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
    if (isIntentLegal(this, intent)) {
    unregisterIntentBlockers();
    }

    super.startActivityForResult(intent, requestCode, options);
    }

    public static void registerIntentBlockers() {
    if (null != mInstrumentation && null == registeredMonitors) {
    Log.v(TAG, "register intent blockers in " + mInstrumentation);
    registeredMonitors = new Instrumentation.ActivityMonitor[badIntentFilters.length];
    for (int i = 0; i < badIntentFilters.length; ++i) {
    registeredMonitors[i] = new Instrumentation.ActivityMonitor(badIntentFilters[i], null, true);
    mInstrumentation.addMonitor(registeredMonitors[i]);
    }
    }
    }

    public static void unregisterIntentBlockers() {
    if (null != mInstrumentation && null != registeredMonitors) {
    Log.v(TAG, "unregister intent blockers in " + mInstrumentation);
    for (int i = 0; i < registeredMonitors.length; ++i) {
    mInstrumentation.removeMonitor(registeredMonitors[i]);
    }
    registeredMonitors = null;
    }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.id.MainLayout);

    ViewGroup mAdGroup = (ViewGroup) findViewById(R.id.AdItem);
    if (!HAS_ADS) {// || !InvisiblePreferences.getInstance().getBoolean(InvisiblePreferences.Show_Ads)) {
    ((ViewGroup) mAdGroup.getParent()).removeView(mAdGroup);
    mAdGroup = null;
    } else {
    mAdGroup.setVisibility(View.GONE);
    View adClick = mAdGroup.findViewById(R.id.adClick);
    adClick.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
    // ad touched
    adClicked = true;
    return false;
    }
    });
    }
    }

    @Override
    protected void onStart() {
    adClicked = false;
    if (HAS_ADS) {
    try {
    Field instrumentationField = Activity.class.getDeclaredField("mInstrumentation");
    instrumentationField.setAccessible(true);
    Instrumentation instrumentation = (Instrumentation) instrumentationField.get(this);
    Log.v(TAG, this + " Found instrumentation:" + instrumentation);
    if (null == mInstrumentation) {
    mInstrumentation = instrumentation;
    } else if (mInstrumentation != instrumentation) {
    Log.d(TAG, this + " different instrumentation:" + instrumentation + " was:" + mInstrumentation);
    unregisterIntentBlockers();
    mInstrumentation = instrumentation;
    }
    registerIntentBlockers();
    if (null == mInstrumentation) {
    Log.d(TAG, "Could not find instrumentation in " + this);
    }
    } catch (NoSuchFieldException e) {
    Log.d(TAG, "Failed to get the activity instrumentation in " + this, e);
    } catch (IllegalAccessException e) {
    Log.d(TAG, "Failed to get the activity instrumentation in " + this, e);
    } catch (IllegalArgumentException e) {
    Log.d(TAG, "Failed to get the activity instrumentation in " + this, e);
    }
    }

    super.onStart();
    }

    @Override
    public void setIntent(Intent newIntent) {
    if (null == newIntent) {
    Log.e(TAG, "Intent blockers are not compatible with an Activity that has no intent set");
    newIntent = new Intent();
    }
    super.setIntent(newIntent);
    }
    }
    7 changes: 7 additions & 0 deletions Launch URL.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    launchIntent.putExtra(ActivityWithAds.EXTRA_BYPASS_BLOCK, true); // make sure we're not blocked
    launchIntent.addCategory(Intent.CATEGORY_BROWSABLE);
    if (null!=referrer)
    launchIntent.putExtra("android.intent.extra.REFERRER", referrer);
    launchIntent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
    activity.startActivity(launchIntent);
    17 changes: 17 additions & 0 deletions MainLayout.xml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="150dip" >

    <com.admarvel.android.ads.AdMarvelView
    android:id="@+id/adMarcel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal" />

    <View
    android:id="@+id/adClick"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

    </FrameLayout>
    26 changes: 26 additions & 0 deletions MyApp.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    package com.levelup.touiteur;

    import android.annotation.SuppressLint;
    import android.app.Application;
    import android.content.Intent;
    import android.os.Bundle;

    public class MyApp extends Application {

    @Override
    public void startActivity(Intent intent) {
    if (ActivityWithAds.isIntentLegal(this, intent)) {
    ActivityWithAds.unregisterIntentBlockers();
    super.startActivity(intent);
    }
    }

    @SuppressLint("NewApi")
    @Override
    public void startActivity(Intent intent, Bundle options) {
    if (ActivityWithAds.isIntentLegal(this, intent)) {
    ActivityWithAds.unregisterIntentBlockers();
    super.startActivity(intent, options);
    }
    }
    }