I am developing a game and it's coming along quite nicely. I do have a bit of a problem about the AdMob ad refreshing though. Every time the ad is refreshed or it draws a different aspect of the ad, my frame rate plummets and almost makes the game unplayable. Here is what I have for the loading of the ad...
ad = new AdView(this, AdSize.BANNER, "...");
AdRequest adRequest = new AdRequest();
adRequest.addTestDevice("...");
adRequest.addTestDevice("...");
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
ad.setLayoutParams(lp);
RelativeLayout layout = new RelativeLayout(this);
layout.addView(renderView);
layout.addView(ad);
ad.loadAd(new AdRequest());
setContentView(layout);
My solution for rendering the ad on top of the SurfaceView was to just add it to a RelativeLayout and add both the SurfaceView and AdView to it. This all works fine and dandy, but every time the ad refreshes (UI or new Ad request), it bogs down the UI thread, which in turn slows down my render thread.
Is there a way that I can make all of this work together nicely to have all work done by the AdView done separately from the main thread? I am not too sure about dynamically updating the current layout from another thread.
Thanks for the help.
I had this problem too. I found it was caused by Google ads which animate when they change, rather than static Admob banner ads which don't animate at all. There's a setting in your admob app settings for controlling whether Google ads are used... try turning it off to see if it makes a difference.
Apologies for resurrecting this question, but I have managed to come across the same issue, and found out that turning LAYER_TYPE_SOFTWARE on the AdView's internal WebView made it smoother.
I have confirmed this working on my side with version 8.4.0 running on Android 5.1, although it is possible that this workaround will benefit more devices with stronger CPUs.
In my activity's onResume I have
/*
* The AdView attaches it's internal WebView only once it
* has been loaded, so we need to wait until that happens.
*/
adView.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
runOnWebView(mAdView, new WebViewAction() {
#Override
public void run(WebView view) {
// the most important part is here
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
});
}
});
with the runOnWebView method and WebViewAction interface defined as
/**
* Recursively searches for a WebView instance located in
* the hierarchy of view and invokes the callback method on
* action with the found instance.
*/
private void runOnWebView(View view, WebViewAction action) {
if (view instanceof WebView) {
action.run((WebView) view);
return;
}
if (view instanceof ViewGroup) {
final ViewGroup parent = (ViewGroup) view;
for (int i = 0; i < parent.getChildCount(); i++) {
runOnWebView(parent.getChildAt(i), action);
}
}
}
private interface WebViewAction {
void run(WebView view);
}
Related
In short: We use reacte native on android and use the native VideoView to show videos with ads using the Google IMA SDK for android. The video plays, the ads play, but the Webview containing "read more" and "skip ad" is not visible. It's added to the view hierarchy, but it's size 0,0 and it has no children. When I use the exact same code in a native app. Everything works as expected.
Some more context:
The video player / google ima sdk integration is copied straight from the google ima example app.
When the component is placed in a native anroid app everything works fine.
When inspecting the view-hierachy it's clear the webview is added and it's size is 0,0
When adding a native webview myself it's is rended perfectly fine.
Relevant code from the React Native component:
#SuppressLint("ViewConstructor")
public class ReactVideoViewWithAds extends FrameLayout implements
LifecycleEventListener {
private VideoPlayerWithAdPlayback mVideoPlayerWithAdPlayback;
private RelativeLayout mCompanionAdSlot;
private VideoPlayerController mVideoPlayerController;
public ReactVideoViewWithAds(ThemedReactContext themedReactContext) {
super(themedReactContext);
createViews();
themedReactContext.addLifecycleEventListener(this);
}
private void createViews() {
FrameLayout.LayoutParams companionAdLayoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
(int) (50 * getResources().getSystem().getDisplayMetrics().density));
companionAdLayoutParams.gravity = Gravity.CENTER_HORIZONTAL;
mCompanionAdSlot = new RelativeLayout(getContext());
mCompanionAdSlot.setBackgroundColor(Color.BLUE);
addView(mCompanionAdSlot, companionAdLayoutParams);
//player with ad playback
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
mVideoPlayerWithAdPlayback = new VideoPlayerWithAdPlayback(getContext());
addView(mVideoPlayerWithAdPlayback, layoutParams);
initPlayer();
}
private void initPlayer() {
mVideoPlayerController = new VideoPlayerController(
getContext(),
mVideoPlayerWithAdPlayback,
null,
null,
"nl",
mCompanionAdSlot,
null);
}
This question had the solution in a comment
When adding views dynamically in a native component it seems you need to manually trigger a layout cycle in order for react-native to pick up on the changes. (perhaps related to react native updating it's shadow-view)
#Override
public void requestLayout() {
super.requestLayout();
post(measureAndLayout);
}
private final Runnable measureAndLayout = new Runnable() {
#Override
public void run() {
measure(
MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY));
layout(getLeft(), getTop(), getRight(), getBottom());
}
};
i added banner ads from admob to my game and the banner add appears only after the first refresh (30 seconds) . And for the first 30 seconds it's there and if you click the bottom of the page where the addvertisment should be it takes you to the advertising page but the ad is not visible.
You can see for yourself when you start the game and click bottom of the screen.
Game #1
And my other game (if you start the intent from the menu in this game ( like facebook) and then return to the menu, ads appear instantly):
Game #2
Anyone had this happen ? What can i do to fix this ?
How I initialize my ads :
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout layout = new RelativeLayout(this);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
opener = new AndroidGalleryOpener(this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
View gameView = initializeForView(new Zaidimas(opener), config);
AdView adView = new AdView(this);
adView.setAdUnitId("xxxxx my secret number xxxxxxxx");
adView.setAdSize(AdSize.BANNER);
adView.loadAd(new AdRequest.Builder()
.build());
layout.addView(gameView);
RelativeLayout.LayoutParams adParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
adParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
adParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
layout.addView(adView, adParams);
setContentView(layout);
//initialize(new Zaidimas(opener), config);
}
It is hard to say what happens in your case, but I have a suspect that your libgdx screen with the admob banner might show up before the ad finished loading. You can try adding an AdListener that forces the ad-view to draw itself once the ad finished loading. Something like:
adView.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
System.out.println("ad banner finished loading!");
adView.setVisibility(View.GONE);
adView.setVisibility(View.VISIBLE);
}
});
The code looks a bit odd, but changing visibility should really make sure that your adView gets drawn again ;-)
If you're using a Relative Layout be sure to include the position of the view relative to other layout objects. I was having the same issue until I placed android:layout_below="#+id/adView" on the object directly below my adView object. You could probably just as well place android:layout_above="#+id/someView" on the adView object itself.
I hide admob adview by view.gone:
//adView.setClickable(false);
//adView.clearFocus();
//adView.setEnabled(false);
//adView.setFilterTouchesWhenObscured(true);
//adView.setFocusable(false);
//adView.setFocusableInTouchMode(false);
adView.setVisibility(View.GONE);
adView.startAnimation( animation );
This hides the ad, but the adview itself is still touchable, so if I touch the adview's space, it still opens the browser and redirects me to the ad, although the ad itself is not visible.
How to disable the touch event too? I've tried all lines above but none of them worked.
Any advice?
Setting adView.setVisibility(View.GONE) and removing the AdMob view from the view hierarchy will hide the ad and prevent user interaction in most cases.
Don't forget to end the AdView lifecycle when the Activity displaying the ad is finished (destroyed). From the AdMob SDK Javadoc:
public void destroy()
Destroys the AdView. The AdView should no longer be used after this method is called.
Make a call to destroy() in the Activity's onDestroy() callback:
#Override
public void onDestroy() {
if (adView != null) {
adView.destroy();
}
super.onDestroy();
}
Try to use setOnTouchListener and Override onTouch like you want. Also you can use removeView():
LinearLayout linLay = (LinearLayout)findViewById(R.id.ad_layout);
linLay.removeView(adView);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
linLay.addView(adView, params);
and add it back when you need.
final com.google.ads.AdView ad = (AdView) findViewById(R.id.rect_ad);
if ( ad != null) {
ad.stopLoading();
ad.destroy();
getWindowManager().removeView(ad);
}
even this code doesn't destroy AdMob =(((
I have it's Handler and WebView in memory holding my activity
I am trying to display an advertisement using Greystrip in AndEngine.
I cannot figure out how this is done because it doesnt use a Layout to inflate views, but yet sprites.
i use BaseGameActivity to create my application for each scene i would like to display adds on.
In GreyStrip this is how they tell you to integrate ads in your application..
Before adding calls in your application to GSSDK, you need to
incorporate the SDK into your AndroidManifest.xml. Add the following
in the section, replacing
with a package identifier that is unique to your application. This
Content Provider manages local storage of ad content, while the
Activity manages ad display.
<provider android:name="com.greystripe.android.sdk.AdContentProvider"
android:authorities="<YOUR_APPLICATION_PACKAGE>.AdContentProvider"
android:multiprocess="true"
android:exported="false" />
<activity android:name="com.greystripe.android.sdk.AdView"
android:configChanges="keyboard|keyboardHidden|orientation" >
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
To initialize the Greystripe SDK, call the initialize method at
startup. This should be done within your application’s onCreate()
method. This call will spawn a background thread to initialize our
activity, and then return control to your app. In this background, the
Greystripe activity will download ads as well as any SDK updates.
Parameters: ctx: Your application Context instance appId: Use the
appId provided during app registration. Providing an invalid appId
will cause the SDK to display error notification ads.
public static GSSDK initialize(Context ctx, String appId)
To use a banner, place the following in your main.xml file:
<view class="com.greystripe.android.sdk.BannerView"
android:id="#+id/gsBanner"
android:layout_width="320dp"
android:layout_height="48dp"/>
To reference the banner view in code, use findViewById, as with any
main.xml element:
BannerView myBanner = (BannerView) findViewById(R.id.gsBanner);
To request adds call
myBanner.refresh();
Now the problem is since i dont have an xml layout i cant figure out how i inflate the layout for the ad view?
Anyone have any ideas?
EDIT:
Ive seen someone do it like this in a tutorial online, but how can i inflate this in andengine?
try {
String applicationId = Utils.scrapeIgnoreCase(externalParams, "<param name=\"id\">", "</param>");
GSSDK.initialize(context, applicationId);
BannerView myBanner = new BannerView(context);
myBanner.setLayoutParams(view.getLayoutParams());
myBanner.addListener(new GreyStripeBannerListener());
view.addView(myBanner);
myBanner.refresh();
myBanner.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Click();
}
});
I'm using AdMob but it should be similar.
Like #Sergey Benner referenced, you have to override onSetContentView in your activity, then create the RenderSurfaceView and your ad view manually.
First of all, create a FrameLayout to contain AndEngine's view and the ad view.
Add AndEngine's view and create your ad view, then set the frame layout as the content view.
#Override
protected void onSetContentView() {
//Creating the parent frame layout:
final FrameLayout frameLayout = new FrameLayout(this);
//Creating its layout params, making it fill the screen.
final FrameLayout.LayoutParams frameLayoutLayoutParams =
new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,
FrameLayout.LayoutParams.FILL_PARENT);
//Creating the banner view.
BannerView bannerView = new BannerView(this);
//....
//Do any initiallizations on the banner view here.
//....
//Creating the banner layout params. With this params, the ad will be placed in the top of the screen, middle horizontally.
final FrameLayout.LayoutParams bannerViewLayoutParams =
new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.TOP | Gravity.CENTER_HORIZONTAL);
//Creating AndEngine's view.
this.mRenderSurfaceView = new RenderSurfaceView(this);
mRenderSurfaceView.setRenderer(mEngine, this);
//createSurfaceViewLayoutParams is an AndEngine method for creating the params for its view.
final android.widget.FrameLayout.LayoutParams surfaceViewLayoutParams =
new FrameLayout.LayoutParams(super.createSurfaceViewLayoutParams());
//Adding the views to the frame layout.
frameLayout.addView(this.mRenderSurfaceView, surfaceViewLayoutParams);
frameLayout.addView(bannerView, bannerViewLayoutParams);
//Setting content view
this.setContentView(frameLayout, frameLayoutLayoutParams);
}
Place this method in your BaseGameActivity class.
I'm trying to hide the Ads from AdMob after 2 minutes, what I've done is, after 2 minutes, I'll stop requesting fresh ad and to hide AdView, have written
if (adView.getVisibility() == AdView.VISIBLE)
adView.setVisibility(AdView.GONE);
what's happening is Ad becomes invisible but still occupies the space, not releasing it. and I want to release that space.
Any Ideas, Thanks in Advance.
if (adView.getVisibility() == AdView.VISIBLE)
adView.setVisibility(View.GONE);
I would use a flag and wrap it like this. Then set it to true/false whenever.
if (Settings.ADMOB_ACTIVE) {
if (Settings.D) {
Log.d(TAG, "Adding Admob");
}
final AdView adView = new AdView(this, AdSize.BANNER, Settings.PUBLISHERID);
final LinearLayout layout = (LinearLayout)findViewById(R.id.adLayout);
if (adView != null && layout != null) {
layout.addView(adView);
final AdRequest request = new AdRequest();
request.setTesting(true);
adView.loadAd(request);
}
}
I handled this function inside a thread, that's why I got exception and it didn't releases the space, instead now I used Thread Handler to handle the function and now its working fine and now its not occupying any space.