Issue
I used this AdMob manual to add an interstitial advertisement to my app. The app has a MainActivity with a WebView for handling the game-play of a puzzle, and a top bar and navigation drawer for handling the navigation.
The interstitial works fine for text and image ads, but not for video ads. After closing a video ad, the WebView is gone (the top bar and navigation drawer are still there). If I then click on a menu item in the navigation drawer, which should navigate to a new page in the WebView, the app crashes with the following NullPointerException (tested on Android 4.2 and 6.0 device):
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.webkit.WebView.loadUrl(java.lang.String)' on a null object reference
at com.bd.test.MainActivity.k(Unknown Source)
at com.bd.test.MainActivity.a(Unknown Source)
at android.support.design.widget.aa.a(Unknown Source)
at android.support.v7.view.menu.i.a(Unknown Source)
at android.support.v7.view.menu.m.b(Unknown Source)
at android.support.v7.view.menu.i.a(Unknown Source)
at android.support.design.internal.d.onClick(Unknown Source)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:742)
at android.os.Handler.dispatchMessage(Handler.java:97)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5457)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
The menu item click handler calls the loadUrl function of my WebView object mWebView, which is somehow set to null while showing or closing the interstitial video ad.
Could there be interference between two WebView's; mine and the one that shows the interstitial ad (similar to what I observed earlier with banner ads)?
Or am I simply making a mistake in my code? The relevant parts of my MainActivity are given below:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
protected WebView mWebView;
protected InterstitialAd mInterstitialAd;
protected int pageId = R.id.nav_home;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initToolbar();
//initDrawer();
//initNavigationView();
initAdInterstitial();
if (savedInstanceState != null) {
return;
}
initWebView();
navigate();
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
pageId = item.getItemId();
navigate();
return true;
}
protected void navigate() {
// Close drawer if it is open.
if(mDrawer.isDrawerOpen(GravityCompat.START)) {
mDrawer.closeDrawer(GravityCompat.START);
}
if(pageId == R.id.nav_home) {
mWebView.loadUrl(URL_INDEX);
}
else if(pageId == R.id.nav_level0) {
mWebView.loadUrl(getLevelUrl(0));
}
else if(pageId == R.id.nav_level1) {
mWebView.loadUrl(getLevelUrl(1));
}
else if(pageId == R.id.nav_level2) {
mWebView.loadUrl(getLevelUrl(2));
}
else if(pageId == R.id.nav_level3) {
mWebView.loadUrl(getLevelUrl(3));
}
else if(pageId == R.id.nav_history) {
mWebView.loadUrl(URL_LAST_PLAYED);
}
}
protected void initWebView() {
mWebView = (WebView) findViewById(R.id.webview);
// Enable Javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setDefaultTextEncodingName("utf-8");
// Deprecated.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
Context c = mWebView.getContext();
webSettings.setDatabasePath(c.getFilesDir().getPath() + c.getPackageName() +
"/databases/");
}
mWebView.setWebViewClient(new WebViewClient() {
/*
* HERE IS WHERE THE INTERSTITIAL AD IS SHOWN.
*
* Shows the interstitial ad every n-th page load.
*/
public void onPageFinished(WebView view, String url) {
// After WebView page is loaded:
// Update page load count.
navigationCount = (navigationCount + 1) % adFrequency;
// Show ad once every n-th page load.
if(navigationCount == 0) {
showAd();
}
}
});
}
protected void initAdInterstitial() {
mInterstitialAd = new InterstitialAd(this);
mInterstitialAd.setAdUnitId(getString(R.string.interstitial_ad_unit_id));
mInterstitialAd.setAdListener(new AdListener() {
@Override
public void onAdClosed() {
requestNewInterstitial();
}
});
requestNewInterstitial();
}
protected void requestNewInterstitial() {
AdRequest adRequest = new AdRequest.Builder().build();
mInterstitialAd.loadAd(adRequest);
}
public void showAd() {
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
}
}
}
Solution
I suspect it is due to this line in onCreate()
if (savedInstanceState != null) {
return;
}
When you return to your Activity you will have a non null savedInstanceState so will never initialise your WebView.
NB It helps if you de-obfuscate your stacktraces or publish source with the line numbers.
Answered By - William
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.