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.