6

I have created a function to show interstitial ad before showing another activity. It's working but onAdDismissedFullScreenContent is being called 2-3 sec lately after closing the ad. It causes previous screen to stand-by. There's a chance to re-click the button to show the wanted Activity.

I really don't understand how to resolve this issue.

Here is my code:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AdManager.showInterstitial(MainActivity.this, () -> {
                    Intent i = new Intent(MainActivity.this, MainActivity2.class);
                    startActivity(i);
                });
            }
        });
        AdManager.loadInterstitial(this);
    }
}

And this is Application Class:


public class App  extends Application {
    private static Context mContext;


    @Override
    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
        AdManager.Init(this);
    }

    public static Context getContext() {
        return mContext;
    }
}

AdManager Class:

public class AdManager {

    private static InterstitialAd mInterstitialAd;
    private static boolean loading, showing;


    public static void Init(Context context) {

        MobileAds.initialize(context, initializationStatus -> {
            loadInterstitial(context);
        });
    }


    public static void loadInterstitial(Context context) {

        if (context == null)
            context = App.getContext();

        Context finalContext = context;
        
        if (mInterstitialAd != null) {
            Toast.makeText(context,"already loaded",Toast.LENGTH_LONG).show();
            return;
        }
        if (loading) {
            Toast.makeText(context,"already another request is processing",Toast.LENGTH_LONG).show();
            return;
        }
        Toast.makeText(context,"requesting interstitial",Toast.LENGTH_LONG).show();

        loading = true;
        AdRequest adRequest = new AdRequest.Builder().build();

        InterstitialAd.load(context, "Interstial Ad Unit ID", adRequest, new InterstitialAdLoadCallback() {
            @Override
            public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
                mInterstitialAd = interstitialAd;
                Toast.makeText(finalContext,"ad loaded",Toast.LENGTH_LONG).show();
                loading = false;
            }

            @Override
            public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                mInterstitialAd = null;
                loading = false;
                Toast.makeText(finalContext,"ad failed to load",Toast.LENGTH_LONG).show();
            }

        });
    }

    public static void showInterstitial(Activity activity, @NonNull AdListener listener) {
        
        if (showing) {
            Toast.makeText(activity,"already showing",Toast.LENGTH_LONG).show();
            listener.onCompleted();
            return;
        }

        if (mInterstitialAd != null) {
            showNow(activity, listener);

        } else {
            Toast.makeText(activity,"mInterstitialAd is null",Toast.LENGTH_LONG).show();
            listener.onCompleted();
            loadInterstitial(activity.getApplicationContext());
        }

    }

    private static void showNow(Activity activity, AdListener listener) {

        if (mInterstitialAd != null && !showing) {
            showing = true;
            mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {
                @Override
                public void onAdDismissedFullScreenContent() {
                    Toast.makeText(activity,"Ad dismissed",Toast.LENGTH_LONG).show();
                    mInterstitialAd = null;
                    listener.onCompleted();
                    showing = false;
                    // times to load an new interstitial ad content
                    loadInterstitial(activity.getApplicationContext());
                }

                @Override
                public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
                    Toast.makeText(activity,"AdFailedToShowFullScreenContent",Toast.LENGTH_LONG).show();
                    mInterstitialAd = null;
                    listener.onCompleted();
                    showing = false;

                    // times to load an new interstitial ad content
                    loadInterstitial(activity.getApplicationContext());
                }


            });
            //  Now show the ad
            Toast.makeText(activity,"call to show ad",Toast.LENGTH_LONG).show();
            mInterstitialAd.show(activity);
        } else {
            Toast.makeText(activity,"either mInterstitialAd is null or ad already is showing",Toast.LENGTH_LONG).show();
            listener.onCompleted();
        }
    }

        public interface AdListener {
        void onCompleted();
    }

}

Please help.

Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38
Gouranga Das
  • 374
  • 3
  • 10
  • No use of `if (context == null) context = App.getContext(); Context finalContext = context;` as you are already showing a toast with that context without checking it. If it is null, it will anyways crash and your code won't reach there – Sambhav Khandelwal May 06 '22 at 09:53
  • Thank you, sir. I actually used ````Toast.makeText(...)```` to make the problem easier to understand and explain, even though it doesn't exist in my original code. However, according to your advice, I have re-edited the code in question, but sir, will you please guide me to solve the real problem? Because of this problem, I get an average of over 2,000 crashes and ANRs every day on the Google Play console. – Gouranga Das May 07 '22 at 05:06
  • Crashes? But, in the problem you stated about the delay – Sambhav Khandelwal May 07 '22 at 05:33
  • Before showing the interstitial ad in my app, I used the progress dialog for 1/2 second to stop the user from using the screen to reduce accidental clicks. And when the ad is dismissed, another activity is shown. Since the variable becomes null after showing the ad, and if the user becomes impatient due to delay and clicks again, "Null Pointer Exception" is created, which is the cause of the crash. You can understand by looking at the code on next comment . – Gouranga Das May 07 '22 at 06:45
  • Ok. @Gaurang. Stay tuned now. I will post the answer. But, before that I just want to clarify that are you ok with the delay? I can stop the user from clicking the button though. Will start typing when you answer in the comment here – Sambhav Khandelwal May 07 '22 at 06:47
  • `if (mInterstitialAd != null) { ProgressDialog dialog = ProgressDialog.show(activity, null, "Loading ad...", true, false);new Handler().postDelayed(() -> { dialog.dismiss(); mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() { @Override public void onAdDismissedFullScreenContent() { mInterstitialAd = null; listener.onCompleted(); } @Override public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) { mInterstitialAd = null; listener.onCompleted(); } }); mInterstitialAd.show(activity); }, 1000); }` – Gouranga Das May 07 '22 at 06:48
  • Not that Gaurang. I don't need this. I want to know what I had mentioned in my comment above – Sambhav Khandelwal May 07 '22 at 06:50
  • Ok, you may proceed. It would have been better if the delay could have been stopped. – Gouranga Das May 07 '22 at 06:53
  • Ok. Check ou the answer [here](https://stackoverflow.com/a/72150183/17133283) – Sambhav Khandelwal May 07 '22 at 06:57

1 Answers1

0

The delay problem


You can't really help it. The problem is from the admob. This will happen. But, to know more about it, we can post an issue abt that on the Google Issue Tracker.

The button problem


I dont think this is any hard task. Just follow the steps:

  1. Create a ProgressBar in your xml layout on top of the button and set its visibility to gone

  2. When the button is click and the ad is shown, you can set the button to invisible and the progress bar can be set to invisible.

  3. Then after a delay, the other activity opens without any harm to the activity from NullPointerException

Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38