1

[Edit: I have just replaced adView.setVisibility(View.GONE) with adView.setVisibility(View.INVISIBLE) the WebView loads and nothing crashes, so it really looks like it is something to do with when I remove the AdView xml element, rather than just making it invisible. Making it invisible is not ideal, as you get a white empty bar at the bottom where the Ad should have been. So it really looks like it is something to do with reloading the Webview or messing with the UI. My html/javascript code is solid and can handle any dimension changes.]

I have a Webview above a banner for an advert (the "ca-app-pub-3940256099942544/6300978111" is the test ad id, so I am not given out any personal info)

<WebView
    android:id="@+id/webView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginBottom="5dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toTopOf="@+id/adView" />

<!-- "BANNER" or "LARGE_BANNER" -->
<com.google.android.gms.ads.AdView
    android:id="@+id/adView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:adSize="BANNER"
    app:adUnitId="ca-app-pub-3940256099942544/6300978111"/>

Note: the app:layout_constrain... in the Webview. I think that might be part of the problem.

At start up, I am checking for purchases. If the user has made any purchases whatsoever, I turn off the ads with the code:

public void turnAdvertsOff() {
    advertsOn = false;
    AdView adView = (AdView) m_Context.findViewById(R.id.adView);
    adView.destroy();
    adView.setVisibility(View.GONE);
}

With the line adView.setVisibility(View.GONE); the program crashes with the unfounded allegation:

I/chromium: [INFO:CONSOLE(6381)] "Uncaught Error: Java exception was raised during method invocation", source: file:///android_asset/www/index.html?IsAndroidWebview=true (6381)
D/WebView: loadUrl=about:blank
D/WebView: destroy

However, I know there is nothing wrong in the Webview, as when I hash out the line //adView.setVisibility(View.GONE);, the WebView loads fine.

Does anyone know why?

Is it anything to do with the app:layout_constraint.., and if so how do I overcome it?

Rewind
  • 2,554
  • 3
  • 30
  • 56
  • The webview is constrained to the adview: `app:layout_constraintBottom_toTopOf="@+id/adView"`, so what happens when the adview is gone? –  Aug 11 '18 at 18:16
  • OK, so is there anything I could do to change these constraints at runtime in the turnAdvertsOff function? Or could I push the adView banner to just offscreen at the bottom? I am easy, I do not mind what solution I use providing there is a solution. (I come from a html/javascript background and you can pretty much do whatever your imagination can think of with `div`s in that world.) – Rewind Aug 11 '18 at 18:35
  • First make sure that this is the problem. Unconstaint the webview from the adview and try. –  Aug 11 '18 at 18:36
  • I am new to xml, how could I do this with a Webview on top of a banner ad? – Rewind Aug 11 '18 at 18:45
  • try the layout I posted in my answer. replace the name of the activity –  Aug 11 '18 at 18:50
  • Use LogCat to examine the Java stack trace associated with your crash: https://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this -- what you have is not a stack trace and is not a crash. – CommonsWare Aug 11 '18 at 22:56
  • The LogCat seems to keep on going after the program closes. – Rewind Aug 12 '18 at 18:48

3 Answers3

0

This is what is recommended to hide the adView:

adView.pause();
adView.setVisibility(View.GONE); 
  • No, it is still causing problems and crashing; this time on the line `adView.destroy();`. I spent some time doing breakpoints, and there appears to be ads loading into the banner prior to the `turnAdvertsOff()` function call. Could this be the problem instead? (Note: if I hash out the `adView.destroy()` and `adView.setVisibility` functions then it all works fine again.) – Rewind Aug 11 '18 at 19:05
  • So delete `adView.destroy()` and keep `adView.setVisibility(View.GONE);` –  Aug 11 '18 at 19:08
  • OK, done that `adView.destroy()` is hashed out and `adView.setVisibility(View.GONE);` remains, but it crashes on the `setVisibility`. – Rewind Aug 11 '18 at 19:12
  • Try `adView.setVisibility(View.INVISIBLE);` –  Aug 11 '18 at 19:14
  • When I replace `adView.setVisibility(View.GONE);` with `adView.setVisibility(View.INVISIBLE);` it still crashes on that INVISIBLE line. Is this because an ad is already loaded into the BANNER? – Rewind Aug 11 '18 at 19:17
  • It crashed on the `adView.pause();`. Thanks for your help so far, someone has just come to the door. I'll be back in an hour. – Rewind Aug 11 '18 at 19:24
0

Try using a LinearLayout as below

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<WebView
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginBottom="5dp"
    android:layout_weight="1" />

<!-- "BANNER" or "LARGE_BANNER" -->
<com.google.android.gms.ads.AdView
    android:id="@+id/adView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:adSize="BANNER"
    android:layout_gravity="center"
    app:adUnitId="ca-app-pub-3940256099942544/6300978111" />
</LinearLayout>

SMART_BANNER

NirmalCode
  • 2,140
  • 1
  • 14
  • 19
0

OK, I have found the answer, and it is not obvious. It is a combination of @mTak 's answer and a critical bit of how Android apps work (which is something I did not realise since I come from an html/javascript world and multi-threading is something programmers have absolute control over in that environment).

The purchases checks were being made on another thread. So the attempt at doing adView.setVisibility(View.GONE) was causing grief to the program. It does not seem to like you messing with the UI except on the main UI thread.

So this is how I changed my code to make the Android protocols happy:

My Purchase check (in a separate thread, but in the MainActivity). Note, stringListARR is just an array of strings with the product codes that the user had purchased. So if there was at least one purchase, whatever it was, I had decided to turn off adverts:

// Any purchase means we have no adverts
myAdverts.advertsOn = stringListARR.size() > 0 ? false : true;
// This is the evil line of code that caused the problem - this was being called not on the UI thread
//if(!myAdverts.advertsOn) myAdverts.turnAdvertsOff();

// And this is how to do it properly forcing it to be run on the UI thread
// 'this' in the following is my MainActivity
if(!myAdverts.advertsOn){
    this.runOnUiThread(new Runnable(){
        @Override
        public void run() {
            myAdverts.turnAdvertsOff();
        }
     });
}

And @mTak was perfectly right how to do things properly. My turnAdvertsOff() looks like this:

public void turnAdvertsOff() {
    advertsOn = false;
    AdView adView = (AdView) m_Context.findViewById(R.id.adView);
    adView.pause();
    adView.setEnabled(false);
    adView.setVisibility(View.GONE);
}

So thanks to @mTak and thanks to this almost unfindable thread on google which gave me the idea:

https://groups.google.com/forum/#!topic/google-admob-ads-sdk/d30EAC1zGFo

In fact, if any people here on Stackoverflow are answering questions about crashes when people are messing with the UI in Android, this runOnUiThread might be the first solution that springs to mind. It is not obvious and a pain to discover.

Rewind
  • 2,554
  • 3
  • 30
  • 56