I am asking for a best practice or implementation.
My app's core function providing service for a long time (2 to 4 hours). The users have some active time and when they use the service, the active time is consumed. The user can restore the active time by watching a rewarded video AD of AdMob.
The problem is, some of the users (less than 3%) cannot see any ADs on their device. I got many complaints that they cannot load the ADs. Most of the users not seeing ADs are using an AD-blocker, but some are under "AD-no fill" status (error code 3). In this case, it seems my app generates too many AD-requests (by users clicking "watch AD"), so AdMob cannot always fill the ADs. My app lets an user to watch ADs less than 10 times a day.
I have some plans and would like to know which one is better:
1) Include another AD-provider. When the AD of AdMob is not filled, my app loads another AD. Drawback: 2x code complexity and 2x maintenance effort.
2) When the real AD is not filled, load an test-AD of AdMob. Drawback: no money
3) When an AD is not filled, load another AD unit of AdMob. Drawback: I am not sure if this works. The AdMob should have determined the user (not AD-unit) is not getting an AD on this request, so generating another request doesn't help. And based on this AdMob loading multiple rewarded videos discussion, it is not allowed to load multiple AD-units.
4) The others I didn't come up with.
5) Is 10 times of watching rewarded-AD too many?
Although in the Admob banner ad not loading in android P thread, the workaround on the user end works (based on the users' feedback of my app), I still patched the app due to the issue of this thread.
My final approach is handling errors of errorCode == 0 or 3. Based on the AdMob document, there are 4 errors of onRewardedAdFailedToLoad() method:
errorCode == 0: ERROR_CODE_INTERNAL_ERROR - Something happened internally; for instance, an invalid response was received from the ad server.
errorCode == 1: ERROR_CODE_INVALID_REQUEST - The ad request was invalid; for instance, the ad unit ID was incorrect.
errorCode == 2: ERROR_CODE_NETWORK_ERROR - The ad request was unsuccessful due to network connectivity.
errorCode == 3: ERROR_CODE_NO_FILL - The ad request was successful, but no ad was returned due to lack of ad inventory.
Case 1 only happens by a careless developer. It should not happen. It is not user trigger-able.
Case 2 occurs when a user uses an AD-blocker or network connection is down. It is user trigger-able.
Case 0 and case 3 are not controllable by users nor developers.
My code can deal with the errors in case 0 and 3. This code ignore the errorCode == 2 to prevent users using AD-blocker or turning off the network to get rewards. From now on most of the users are happy.
Note: the code
(errorCode == 2 && BuildConfig.DEBUG)
is for testing purpose. I can turn off the network to trigger the errorCode == 2 to see if this approach works properly.
Here is all my code:
@Override
public void onRewardedVideoAdFailedToLoad(int errorCode) {
if (BuildConfig.DEBUG) { // ad should be loaded but not
Log.i(TAG, "Ad: onRewardedVideoAdFailedToLoad(): " + errorCode);
}
adButton.setEnabled(false);
adButton.setText(getString(R.string.text_ad_unavailable, errorCode));
if (errorCode == 0 || errorCode == 3 || (errorCode == 2 && BuildConfig.DEBUG)) {
noAdButton.setEnabled(true); // give 1/4 reward of watching AD
noAdButton.setVisibility(View.VISIBLE);
}
}