com.codename1.impl.FullScreenAdService Maven / Gradle / Ivy
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codename1.impl;
import com.codename1.components.InfiniteProgress;
import com.codename1.io.ConnectionRequest;
import com.codename1.io.NetworkManager;
import com.codename1.ui.Button;
import com.codename1.ui.Command;
import com.codename1.ui.Component;
import com.codename1.ui.Container;
import com.codename1.ui.Dialog;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.animations.CommonTransitions;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.events.ActionListener;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.GridLayout;
import com.codename1.ui.plaf.UIManager;
import java.util.Timer;
import java.util.TimerTask;
/**
* Abstract class for fullscreen ads that appear before and possibly after application
* execution as well as randomly between application screen transitions.
*
* @author Shai Almog
*/
public abstract class FullScreenAdService {
private boolean allowWithoutNetwork = true;
private int timeout = 10000;
private int adDisplayTime = 6000;
private int timeForNext = -1;
private boolean scaleMode;
private boolean allowSkipping;
private static Object LOCK = new Object();
/**
* Creates a new request for an ad
* @return the network operation
*/
protected abstract ConnectionRequest createAdRequest();
/**
* Component representing a given ad
* @return the ad that is currently pending
*/
protected abstract Component getPendingAd();
/**
* Just checks if an ad is already fetched
* @return returns true if an ad is already waiting in the queue
*/
protected abstract boolean hasPendingAd();
/**
* Removes the pending ad data so we can fetch a new ad
*/
protected abstract void clearPendingAd();
/**
* Returns the URL for the ad
* @return the ad URL
*/
protected abstract String getAdDestination();
/**
* Returns true if the connection failed
*/
protected abstract boolean failed();
/**
* Invoked on application startup, this code will download an ad or timeout
*/
public void showWelcomeAd() {
if(!UIManager.getInstance().wasThemeInstalled()) {
if(Display.getInstance().hasNativeTheme()) {
Display.getInstance().installNativeTheme();
}
}
ConnectionRequest r = createAdRequest();
r.setPriority(ConnectionRequest.PRIORITY_HIGH);
r.setTimeout(timeout);
InfiniteProgress ip = new InfiniteProgress();
Dialog ipDialog = ip.showInifiniteBlocking();
NetworkManager.getInstance().addToQueueAndWait(r);
if(failed()) {
ipDialog.dispose();
if(!allowWithoutNetwork) {
ipDialog.dispose();
Dialog.show("Network Error", "Please try again later", "Exit", null);
Display.getInstance().exitApplication();
} else {
return;
}
}
Component c = getPendingAd();
if(c != null) {
Form adForm = new AdForm(c);
adForm.setTransitionInAnimator(CommonTransitions.createEmpty());
adForm.setTransitionOutAnimator(CommonTransitions.createEmpty());
adForm.show();
}
}
/**
* Binds an ad to appear periodically after a given timeout
* @param timeForNext the timeout in which an ad should be shown in milliseconds
*/
public void bindTransitionAd(final int timeForNext) {
Runnable onTransitionAndExit = new Runnable() {
private long lastTime = System.currentTimeMillis();
public void run() {
long t = System.currentTimeMillis();
if(t - lastTime > timeForNext) {
lastTime = t;
Component c = getPendingAd();
if(c != null) {
Form adForm = new AdForm(c);
adForm.show();
}
}
}
};
CodenameOneImplementation.setOnCurrentFormChange(onTransitionAndExit);
CodenameOneImplementation.setOnExit(onTransitionAndExit);
Timer t = new Timer();
int tm = Math.max(5000, timeForNext - 600);
t.schedule(new TimerTask() {
public void run() {
if(!hasPendingAd()) {
ConnectionRequest r = createAdRequest();
r.setPriority(ConnectionRequest.PRIORITY_LOW);
r.setTimeout(timeout);
NetworkManager.getInstance().addToQueue(r);
}
}
}, tm, tm);
}
/**
* If set to true this flag allows the application to load even if an Ad cannot be displayed
* @return the allowWithoutNetwork
*/
public boolean isAllowWithoutNetwork() {
return allowWithoutNetwork;
}
/**
* If set to true this flag allows the application to load even if an Ad cannot be displayed
* @param allowWithoutNetwork the allowWithoutNetwork to set
*/
public void setAllowWithoutNetwork(boolean allowWithoutNetwork) {
this.allowWithoutNetwork = allowWithoutNetwork;
}
/**
* The timeout in milliseconds for an ad request
* @return the timeout
*/
public int getTimeout() {
return timeout;
}
/**
* The timeout in milliseconds for an ad request
* @param timeout the timeout to set
*/
public void setTimeout(int timeout) {
this.timeout = timeout;
}
/**
* @return the adDisplayTime
*/
public int getAdDisplayTime() {
return adDisplayTime;
}
/**
* @param adDisplayTime the adDisplayTime to set
*/
public void setAdDisplayTime(int adDisplayTime) {
this.adDisplayTime = adDisplayTime;
}
/**
* @return the scaleMode
*/
public boolean isScaleMode() {
return scaleMode;
}
/**
* @param scaleMode the scaleMode to set
*/
public void setScaleMode(boolean scaleMode) {
this.scaleMode = scaleMode;
}
/**
* @return the allowSkipping
*/
public boolean isAllowSkipping() {
return allowSkipping;
}
/**
* @param allowSkipping the allowSkipping to set
*/
public void setAllowSkipping(boolean allowSkipping) {
this.allowSkipping = allowSkipping;
}
void unlock(final ActionListener callback) {
AdForm adf = (AdForm)Display.getInstance().getCurrent();
synchronized(LOCK) {
adf.blocked = false;
LOCK.notify();
}
// move to the next screen so the ad will be shown and so we
// can return to the next screen and not this screen
Display.getInstance().callSerially(new Runnable() {
public void run() {
// prevent a potential race condition with the locking
if(Display.getInstance().getCurrent() instanceof AdForm) {
Display.getInstance().callSerially(this);
return;
}
callback.actionPerformed(null);
}
});
}
class AdForm extends Form {
boolean blocked = true;
private long shown = -1;
public AdForm(Component ad) {
BorderLayout bl = new BorderLayout();
setLayout(bl);
if(!isScaleMode()) {
bl.setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER);
}
addComponent(BorderLayout.CENTER, ad);
Command open = new Command("Open") {
public void actionPerformed(ActionEvent ev) {
synchronized(LOCK) {
blocked = false;
LOCK.notify();
}
// move to the next screen so the ad will be shown and so we
// can return to the next screen and not this screen
Display.getInstance().callSerially(new Runnable() {
public void run() {
// prevent a potential race condition with the locking
if(Display.getInstance().getCurrent() instanceof AdForm) {
Display.getInstance().callSerially(this);
return;
}
Display.getInstance().execute(getAdDestination());
}
});
}
};
Command skip = new Command("Skip") {
public void actionPerformed(ActionEvent ev) {
synchronized(LOCK) {
blocked = false;
LOCK.notify();
}
}
};
if(Display.getInstance().isTouchScreenDevice()) {
Container grid = new Container(new GridLayout(1, 2));
grid.addComponent(new Button(open));
if(isAllowSkipping()) {
grid.addComponent(new Button(skip));
}
addComponent(BorderLayout.SOUTH, grid);
} else {
addCommand(open);
if(isAllowSkipping()) {
addCommand(skip);
}
}
registerAnimated(this);
}
protected void onShow() {
shown = System.currentTimeMillis();
}
public void show() {
super.showBack();
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
try {
synchronized(LOCK) {
while(blocked) {
LOCK.wait(100);
}
}
} catch(Exception err) {
err.printStackTrace();
}
}
});
clearPendingAd();
}
public boolean animate() {
if(shown > -1 && System.currentTimeMillis() - shown >= adDisplayTime) {
blocked = false;
}
return false;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy