Does anyone know if any of the Android Advertising SDKs work with the new DreamService functionality? I tried using AdMob and first saw that the Interstitial class constructor explicitly requires an Activity. I saw the the AdView has a constructor that just needs a context so I tried that, but got a runtime exception telling me the problem was that I'm trying to inflate an AdView using a Context other than Activity. I looked into trying the Amazon Mobile Ads API, but it appears identical to the AdMob one.
I tried to get creative and start another Activity from my DreamService that creates an Interstitial ad, but it was created behind the DreamService UI (kinda makes sense since the Daydream overlays everything). Does anyone know of any solution to using Ads in a Daydream?
I came up with something that solves this issue, though I still don't really like the solution. Would welcome a more elegant approach if anyone knows of one.
What I did was use the mMedia SDK instead of AdMob. Their Interstitial and AdView classes can both take a Context rather than an Activity in the constructor. The Interstitial still didn't work out for me since it opens behind the Dream overlay. So what I ended up doing was adding an AdView to my Dream's XML layout, then setting its visibility to View.GONE until I wanted to display it. When it's time to display the ad I set it to View.VISIBLE.
The other issue I encountered was that after clicking the AdView it launches the browser with the ad's URL, which of course opens behind the Dream, defeating the purpose of showing an ad. So I ended up setting the Dream to be interactive, caught the onTouchEvent, then if the Ad is VISIBLE when the click happens call the Ad's callOnClick method. I also had to set the Ad's RequestListener to my Dream Service and implement the MMAdOverlayLaunched method, which is called when the Ad launches the browser. In this method I just called finish() to stop the Dream and let the browser display the Ad.
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
// Exit dream upon user touch
setInteractive(true);
// Hide system UI
setFullscreen(true);
// Set the dream layout
setContentView(R.layout.dream_layout);
//Initialize Ads
this.initAdvertising();
}
private void initAdvertising(){
MMSDK.initialize(this);
mDreamAd = (MMAdView) findViewById(R.id.adView);
//Separate thread will handle showing the ad
mDreamAd.setVisibility(View.GONE);
mAdRequest = new MMRequest();
//TODO add metadata to Request
mDreamAd.setMMRequest(mAdRequest);
mDreamAd.setListener(this);
mDreamAd.getAd();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event){
super.dispatchTouchEvent(event);
if(mDreamAd != null && mDreamAd.isShown()){
mDreamAd.callOnClick();
}
return true;
}
#Override
public void MMAdOverlayLaunched(MMAd ad) {
//Finish so we can display the ad the user has clicked
if(ad.equals(this.mDreamAd))
this.finish();
}
Related
When I display an Admob interstitial, it displays fine, and I have registered a listener to catch the onAdClosed event, but the problem is that I cannot actually do anything from that event that interacts with my UI because the interstitial has closed it all.
I'm creating the interstitial like this:
storyAd = new InterstitialAd(this);
storyAd.setAdUnitId("ca-app-pub-xxxxxxxxxxxxxxxx");
storyAd.setAdListener(new AdListener() {
#Override
public void onAdClosed() {
super.onAdClosed();
storyAd.loadAd(buildAdRequest());
if (prevMusicPlaying) {
toggleAudio();
}
loadNextPage();
}
});
storyAd.loadAd(buildAdRequest());
I have it in my manifest too:
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="#android:style/Theme.Translucent" />
The loadNextPage() call crashes because it tries to create a new fragment and add it to my activity, which it cannot do because the activity has been paused by the interstitial. So I just get this exception:
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1328)
at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1346)
at android.app.FragmentManagerImpl.popBackStack(FragmentManager.java:488)
How can I make it so that the InterstitialAd doesn't interfere in any way with the existing UI. It took a very long time to get the existing UI working with the various activity/fragment gotchas.
You are probably finishing the current activity before you are showing the interstitial and then relying on the interstitial callback to move to next page or screen for that matter
This is bad practice since you don't want your app flow to rely on the ad callbacks. there can be scenarios which an ad cant show at all
What you need to do is call
loadNextPage();
before you show an ad. when the ad will show it will simply go over the the app screen that way if there is an ad it will simply take over otherwise it will not effect the app
So, the answer is less than ideal but it works.
You update your data model in onAdClosed() but not anything related to the UI. Set a flag to indicate that the ad is closed or whatever you need to do.
Then in onResume() on the main Activity, you update the UI. You can check the flag from onAdClosed() or whatever and then update the GUI to reflect the new state.
Here is my scenario: when my app gets purged from memory by the OS and its reopened from the recent apps list, it goes straight to the Activity that was last open. When this happens I would like to initialize a couple of business objects.
My first approach to achieve this was to do the initialization in the InitializeLastChance method in the Setup class.
Inside the InitializeLastChance method I check if the current top activity is the MvxSplashScreenActivity. If it's not, I make the necessary initialization. The code is something like this:
protected override void InitializeLastChance()
{
try
{
var topActivity = Mvx.Resolve<IMvxAndroidCurrentTopActivity>().Activity;
if (topActivity.LocalClassName != _splashScreenName)
{
//Do special initialization
}
}
catch (Exception ex)
{
//Log error
}
base.InitializeLastChance();
}
This works as expected but the visual effect isn't the best: a blank screen with the name of the app appears for a couple of seconds while the initialization occurs. When the initialization is finished, the last open activity is loaded.
To avoid this blank screen, I wanted to try a different approach: show an Activity while the initialization is being done, similar to a splash screen, so that the user can have some feedback that something is happening. In this approach the ViewModel attached to the new Activity would do the initialization that I want.
To show this new activity, I tried creating a custom IMvxAppStart and register it in the App class, but that hasn't worked. My custom IMvxAppStart has the following code:
public class CustomAppStart
: MvxNavigatingObject
, IMvxAppStart
{
public void Start(object hint = null)
{
if (hint == null)
{
ShowViewModel<LoginViewModel>();
}
else
{
ShowViewModel<InitializationViewModel>();
}
}
}
I wanted to show the LoginViewModel when the app starts from scratch and in the cases where the app goes straight to the last loaded Activity, the InitializationViewModel would be shown. In the latter scenario the Start method isn't called. I've checked the MvvmCross source code and as far as I can understand, the Start method is called by the MvxSplashScreenActivity (correct me if I'm wrong). When an app is reopened and goes straight to the last opened Activity, the MvxSplashScreenActivity isn't used so the Start method in CustomAppStart is not called.
That being said, I have some questions regarding the CustomAppStart approach:
Is this approach the best way to show a splash screen or "initialization activity" in the cases where the app goes straight to the last opened activity?
How do I use the CustomAppStart in these situations, since it seems that the Start method is called only from the MvxSplashScreenActivity?
How do I pass a value to the hint parameter in the Start method?
Thanks
I implemented admob interstitials into my app and everything is working fine.
Admobs interstitials are full screen and this is fine, the problem is that somehow when the admob interstitial is shown in full screen, my app (in the background) also jumps into full screen.
Now when someone closes the ad, the app jumps from full screen back to being normal again and this looks like a bug to me, because it causes a small flickering effect.
Did anyone else notice this effect, or I am alone in this?
Is there some way to fix this? Can i force my app to stay that way and not jump to full screen? Or can I force the status bar on interstitials ads?
Thank in advance!
Edit, my sourcecode is very similiar to this (standard approach taken from google itself):
public class BannerExample extends Activity {
private InterstitialAd interstitial;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create the interstitial.
interstitial = new InterstitialAd(this);
interstitial.setAdUnitId(MY_AD_UNIT_ID);
// Create ad request.
AdRequest adRequest = new AdRequest.Builder().build();
// Begin loading your interstitial.
interstitial.loadAd(adRequest);
}
// Invoke displayInterstitial() when you are ready to display an interstitial.
public void displayInterstitial() {
if (interstitial.isLoaded()) {
interstitial.show();
}
}
}
update:
i integrated mopub which also offers full screen interstitials and interestingly enough this does not happen with mopub even though integrating it in the app is similar to admob. so i bet this is some odd behaviour of admob and not some bug in my app
It really depend on what is going on during Activity.onResume, when it call resume it try to update the view. It may look like flickering, but it just updating the view. Check your class and print some debug log to see what is it doing when you click the close button.
AdMob SDK don't control your class, so it only dismiss the ad view. What you do in your class cause the flickering. Without seeing the code, I cannot say for sure, maybe some code would be great.
Check my reply here:
Phonegap screen flickers with AdMob animation
Perhaps is a similar issue. Not every developer has the luxury of switching to a different provider (ie. if you work with a client)
I have an Android App which displays Interstitial Ads using Googles admob network. The good thing about admob is, its activity independent. I can load the ad in my MainActivity and whenever admob is ready with the ad, it will display it, even when I am not in MainActivity anymore. I already use the isLoaded() method to show the ad, and thats 90% of the time already working as desired.
But the other 10% it is not. There are certain activities which should remain adfree because the ad will decrease the quality of the game. If a phone is slow or the connection is slow and it takes a while to load an ad, the ad might pop up in the wrong activity.
Is there something I could call, which would close loaded ads and stops loading ads which are not displayed yet? This would take effect only on two activities whilst the others will remain as they are.
so in my main activity I call:
Ads.loadAdMobInterstitial(MainActivity.this);
and this is my class which handles Ads:
public class Ads {
public static InterstitialAd loadAdMobInterstitial(final Context context) {
int admobUnitId = string.admob_ad_unit_id;
final InterstitialAd iAd = new InterstitialAd(context);
iAd.setAdUnitId(context.getString(admobUnitId));
iAd.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
iAd.show();
}
});
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
iAd.loadAd(adRequest);
return iAd;
}
}
OK, first of all, you should NEVER call interstitialAd.show() from onAdLoaded(). As you have pointed out it will cause a poor user experience. It is also likely to get your Admob account banned.
I suspect that what you really want to do is to refactor your existing Activities into Fragments and host them all within your MainActivity. That way you will have the control you need to switch the interstitial on/off.
And make sure that you are showing your interstitial from a natural break point in your app rather than from onAdLoaded().
You can add a boolean flag in your onPause/onResume methods in the activity or fragment. Then check on adLoaded event like this:
interstitial.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
if(!paused) {
interstitial.show();
}
}
});
Load your interstitial ad in background, but don't use onAdLoaded() method.
When you are at the point in the app, where you want to show your interstitial, use this:
if (admobInterstitial.isLoaded()) {
admobInterstitial.show();
}
This will show interstitial ad only in case it is loaded. Otherwise nothing will happen.
I noticed that my app was receiving few clicks on the InterstitialAd, and I saw that the Ad could be instantly closed by pressing the Back button. Usually the ad takes a few seconds to appear, so the user can close it even before seeing it (when only a black screen appears).
I don't think that it's fair, is almost useless to show it. Is there anyway to prevent this from happening?
I did this, but nothing happened...
// When creating the InterstitialAd, I set the following listener
mInterstitial.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
isShowingInterstitialAd = true;
mInterstitial.show();
}
#Override
public void onAdClosed() {
isShowingInterstitialAd = false;
mAdView.setVisibility(View.VISIBLE);
mAdViewClose.setVisibility(View.VISIBLE);
}
});
// On the Activity's class
#Override
public void onBackPressed() {
if (isShowingInterstitialAd) {
return;
}
// ...
}
My understanding is that AdMob draws its own Activity on top of yours, so it has its own implementation of onBackPressed(), which means that you don't have control of anything that happens once you call mInterstitial.show(); until AdMob gives control back to your activity.
Don't sweat the little things like this.
You are much better off spending energy making your app better.
Some people will never click on ads. But if you provide an inapp purchase that removes the ads they may well buy that. That is a better return on investment for your dev effort.
IMHO
Depending on your OS, there are a few ways to override that back button. Search for back button override to find them.