海外广告变现形式有许多种,我所知道的大概有:admob、facebook、youtube、亚马逊等。之前做facebook广告的时候,经常遇到账号被封的情况,让人很头疼(如果有大佬知道怎么经营facebook广告,可以一起探讨)。所以目前公司主要业务是admob广告。申请账户就不说了。要持有外币卡或者双币信用卡。这里主要介绍下admob广告的实现方式:
广告文档介绍:
admob广告文档
我这里主要介绍banner广告以及插屏广告的实现以及封装。激励视频广告以及原生广告可以参考文档或者官方demo
1、banner广告:
首先需要AdView,你可以在布局中进行设置例如:
还有需要设置必要属性:
ads:adSize
- 将此属性设置为要使用的广告尺寸。如果您不想使用该常量定义的标准尺寸,可改为设置一个自定义尺寸。有关详情,请参阅下面的“横幅广告尺寸”部分。ads:adUnitId
- 将此属性设置为为您应用中展示广告的广告单元指定的唯一标识符。如果您要在不同的活动中展示横幅广告,则其中每个都需要一个广告单元。 另外也可以在代码中进行设置:
AdView adView = new AdView(this);
adView.setAdSize(AdSize.BANNER);
adView.setAdUnitId("ca-app-pub-3940256099942544/6300978111");
我个人是在代码中设置的,这样的话,广告位id 更加的灵活。假如你的广告位id出问题了,你可以通过服务器或者firebase remoteConfig(前面博客有介绍)拉取账号信息。
值得注意的是,在测试广告的时候,尽量使用测试id,否则账号会被停封。
测试广告id:
横幅广告 ca-app-pub-3940256099942544/6300978111
插页式广告 ca-app-pub-3940256099942544/1033173712
插页式视频广告 ca-app-pub-3940256099942544/8691691433
激励视频广告 ca-app-pub-3940256099942544/5224354917
原生高级广告 ca-app-pub-3940256099942544/2247696110
原生高级视频广告 ca-app-pub-3940256099942544/1044960115
I/Ads: Use AdRequest.Builder.addTestDevice("33BE2250B43518CCDA7DE426D04EE231")
to get test ads on this device."
3.修改代码,以便用您的测试设备 ID 调用 AdRequest.Builder.addTestDevice()
。您可以为多个设备多次调用这个方法。
AdRequest request = new AdRequest.Builder()
.addTestDevice("33BE2250B43518CCDA7DE426D04EE231") // An example device ID
.build();
展示横幅广告代码:
import ...
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
public class MainActivity extends AppCompatActivity {
private AdView mAdView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MobileAds.initialize(this,
"ca-app-pub-3940256099942544~3347511713");
mAdView = findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);
}
}
广告监听:
mAdView.setAdListener(new AdListener() {
@Override
public void onAdLoaded() {
// Code to be executed when an ad finishes loading.
}
@Override
public void onAdFailedToLoad(int errorCode) {
// Code to be executed when an ad request fails.
}
@Override
public void onAdOpened() {
// Code to be executed when an ad opens an overlay that
// covers the screen.
}
@Override
public void onAdLeftApplication() {
// Code to be executed when the user has left the app.
}
@Override
public void onAdClosed() {
// Code to be executed when when the user is about to return
// to the app after tapping on an ad.
}
});
到目前为止,广告就可以正常显示了,如下图:
封装:
本次封装均是结合firebase remoteConfig进行封装,代码如下:
import android.content.Context;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.kkw.apps.anexplorer.AppFlavour;
import com.kkw.apps.anexplorer.firebase.AdsInfoBean;
import com.kkw.apps.anexplorer.firebase.CustomCtrlControl;
import com.kkw.apps.anexplorer.firebase.InterstitalUtils;
import com.kkw.apps.anexplorer.misc.CrashReportingManager;
import static com.kkw.apps.anexplorer.DocumentsApplication.isTelevision;
/**
* A Wrapper which wraps AdView along with loading the view aswell
*/
public class AdWrapper extends FrameLayout {
private AdView mAdView;
private AdsInfoBean mAdsInfoBean;
private Context mContext;
private boolean showInterstiatial = true;
public AdWrapper(Context context) {
super(context);
//remove get admob id from firebaseConfig
this.mContext = context;
init(context);
}
public AdWrapper(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
init(context);
}
public AdWrapper(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
init(context);
}
private void init(Context context) {
//Ads
this.mAdsInfoBean = CustomCtrlControl.getAdsInfoBean();
if (!isTelevision() && null != mAdsInfoBean) {
initAd();
} else {
initInterstitialAd();
}
}
public void initInterstitialAd() {
requestNewInterstitial();
}
public void initAd() {
mAdView = CustomCtrlControl.loadBanner(this, mContext, mAdsInfoBean);
if (null != mAdView) {
mAdView.setAdListener(adListener);
}
}
private void requestNewInterstitial() {
if (AppFlavour.isPurchased()||!CustomCtrlControl.verifyAdsInfoInter(mAdsInfoBean)) {
return;
}else {
InterstitalUtils.getShareInstance().init(mContext, mAdsInfoBean);
}
}
private void showInterstitial() {
if (AppFlavour.isPurchased()) {
return;
}
if (CustomCtrlControl.verifyAdsInfoInter(mAdsInfoBean)) {
InterstitalUtils.getShareInstance().showIntertital(new InterstitalUtils.AdCloseListener() {
@Override
public void OnAdClosed() {
}
});
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// showInterstitial();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
showAd();
}
@Override
protected Parcelable onSaveInstanceState() {
showInterstiatial = false;
return super.onSaveInstanceState();
}
private void showAd() {
//使用!移除广告
if (AppFlavour.isPurchased()) {
return;
}
if (isInEditMode()) {
return;
}
//Fixes GPS AIOB Exception
try {
if (null != mAdView) {
mAdView.loadAd(new AdRequest.Builder().build());
}
} catch (Exception e) {
CrashReportingManager.logException(e);
}
}
AdListener adListener = new AdListener() {
@Override
public void onAdLoaded() {
super.onAdLoaded();
if (null != mAdView) {
mAdView.setVisibility(View.VISIBLE);
}
}
@Override
public void onAdFailedToLoad(int errorCode) {
super.onAdFailedToLoad(errorCode);
if (null != mAdView) {
mAdView.setVisibility(View.GONE);
}
}
};
public static AdView loadBanner(FrameLayout frameLayout, Context context,AdsInfoBean adsInfoBean){
AdView mAdView =null;
if (verifyAdsInfoBanner(adsInfoBean)) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
mAdView= new AdView(context);
MobileAds.initialize(context,adsInfoBean.getmAppId());
mAdView.setAdSize(AdSize.SMART_BANNER);
mAdView.setAdUnitId(adsInfoBean.getmBannerId());
frameLayout.addView(mAdView, params);
}else {
return null;
}
return mAdView;
}
}
使用:只需要在布局中使用即可:
插屏广告:
插屏广告的初始化以及显示不能同时进行。需要在oncreat时进行加载,在该展示的时候进行展示。一起进行不会显示广告。
官方文档使用:
package ...
import com.google.android.gms.ads.InterstitialAd;
public class MainActivity extends Activity {
private InterstitialAd mInterstitialAd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MobileAds.initialize(this,
"ca-app-pub-3940256099942544~*******");
mInterstitialAd = new InterstitialAd(this);
mInterstitialAd.setAdUnitId("ca-app-pub-3940256099942544/***");
mInterstitialAd.loadAd(new AdRequest.Builder().build());
}
}
插页式广告应在应用流程的自然停顿期间(例如在游戏的不同关卡之间或者在用户完成一项任务之后)展示。要展示插页式广告,请使用 isLoaded()
方法验证加载已完成,然后再调用 show()
。上一个代码示例中的插页式广告可以在按钮的 OnClickListener
中展示,如下所示:
mMyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
} else {
Log.d("TAG", "The interstitial wasn't loaded yet.");
}
}
});
监听:
mInterstitialAd.setAdListener(new AdListener() {
@Override
public void onAdLoaded() {
// Code to be executed when an ad finishes loading.
}
@Override
public void onAdFailedToLoad(int errorCode) {
// Code to be executed when an ad request fails.
}
@Override
public void onAdOpened() {
// Code to be executed when the ad is displayed.
}
@Override
public void onAdLeftApplication() {
// Code to be executed when the user has left the app.
}
@Override
public void onAdClosed() {
// Code to be executed when when the interstitial ad is closed.
}
});
插屏广告有很多讲究,但凡违反google规定,都会收到google发来的邮件。在规定时间没更改,会被封号。到时候,之前的收益只能靠申诉拿回来了。
考虑插页式广告是否为适合您应用的恰当广告类型。
在具有自然过渡点的应用中,插页式广告的效果最好。此类过渡点通常存在于应用内的任务结束时,例如分享完图片或完成一个游戏关卡时。用户希望可以在操作过程中休息一下,因此这时展示插页式广告不会影响用户体验。请务必考虑在应用流程的哪些时间点展示插页式广告,以及用户可能会以什么方式响应。
务必在展示插页式广告时暂停操作。
插页式广告类型多样,包括文字广告、图片广告和视频广告等。确保应用在展示插页式广告时,也会暂停使用某些资源,以便供广告使用,这一点十分重要。例如,当您发出展示插页式广告的调用后,请务必暂停应用产生的所有音频输出。您可以在 onAdClosed()
事件处理程序中恢复声音播放,该处理程序会在用户结束与广告的互动之后被调用。此外,请考虑在广告展示时暂停所有密集计算任务(例如游戏循环)。这将确保用户不会遇到图像无响应/响应慢或者视频卡顿的现象。
留出充足的加载时间。
确保在恰当的时间展示插页式广告十分重要,同样,确保用户无需等待广告的加载也十分重要。在打算调用 show()
前,请事先通过调用 loadAd()
加载广告,这可确保应用在广告展示时间到来前完全加载插页式广告。
不要向用户展示太多广告。
虽然提高插页式广告在应用中的展示频率似乎是增加收入的绝佳方式,但这么做也会影响用户体验并降低点击率。确保用户不会频繁受到干扰,使其可以享受使用应用的过程。
广告展示,如下图:
封装:
import android.content.Context;
import android.util.Log;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import com.google.android.gms.ads.MobileAds;
/**
* 单例模式实现插屏广告
*/
public class InterstitalUtils {
private static InterstitalUtils sInstance;
private AdCloseListener mAdCloseListener;
private boolean isReLoad = false;
private InterstitialAd mInterstitialAd;
public static InterstitalUtils getShareInstance() {
if (null == sInstance) {
synchronized (InterstitalUtils.class) {
if (null == sInstance) {
sInstance = new InterstitalUtils();
}
}
}
return sInstance;
}
public void init(Context context, AdsInfoBean adsInfoBean) {
if (null == adsInfoBean) {
return;
}
MobileAds.initialize(context, adsInfoBean.getmAppId());
mInterstitialAd = new InterstitialAd(context);
mInterstitialAd.setAdUnitId(adsInfoBean.getmIntertId());
mInterstitialAd.setAdListener(new AdListener() {
@Override
public void onAdClosed() {
super.onAdClosed();
if (null != mAdCloseListener) {
mAdCloseListener.OnAdClosed();
}
loadIntertital();
}
@Override
public void onAdFailedToLoad(int i) {
super.onAdFailedToLoad(i);
if (isReLoad == false) {
isReLoad = true;
loadIntertital();
}
Log.e("```inter-error",""+i);
}
@Override
public void onAdLeftApplication() {
super.onAdLeftApplication();
}
@Override
public void onAdOpened() {
super.onAdOpened();
}
@Override
public void onAdLoaded() {
super.onAdLoaded();
}
@Override
public void onAdClicked() {
super.onAdClicked();
}
});
loadIntertital();
}
private void loadIntertital() {
if (null != mInterstitialAd && !mInterstitialAd.isLoading() && !mInterstitialAd.isLoaded()) {
AdRequest adRequest = new AdRequest.Builder()/**.addTestDevice("9305F4AADEB37CC388BCEDFDE50B4B4A")**/.build();
mInterstitialAd.loadAd(adRequest);
}
}
public void showIntertital(AdCloseListener adCloseListener) {
if (canShowIntertital()) {
isReLoad = false;
this.mAdCloseListener = adCloseListener;
mInterstitialAd.show();
} else {
loadIntertital();
adCloseListener.OnAdClosed();
}
}
private boolean canShowIntertital() {
return null != mInterstitialAd && mInterstitialAd.isLoaded();
}
public interface AdCloseListener {
void OnAdClosed();
}
}
调用:
AdsInfoBean是通过firebase remoteConfig得到的。里面封装的是id信息:
public class AdsInfoBean {
private String mAppId;
private String mBannerId;
private String mIntertId;
private String mRewardId;
private String mCustomId;
public String getmAppId() {
return mAppId;
}
public void setmAppId(String mAppId) {
this.mAppId = mAppId;
}
public String getmBannerId() {
return mBannerId;
}
public void setmBannerId(String mBannerId) {
this.mBannerId = mBannerId;
}
public String getmIntertId() {
return mIntertId;
}
public void setmIntertId(String mIntertId) {
this.mIntertId = mIntertId;
}
public String getmRewardId() {
return mRewardId;
}
public void setmRewardId(String mRewardId) {
this.mRewardId = mRewardId;
}
public String getmCustomId() {
return mCustomId;
}
public void setmCustomId(String mCustomId) {
this.mCustomId = mCustomId;
}
@Override
public String toString() {
return "AdsInfoBean{" +
"mAppId='" + mAppId + '\'' +
", mBannerId='" + mBannerId + '\'' +
", mIntertId='" + mIntertId + '\'' +
", mRewardId='" + mRewardId + '\'' +
", mCustomId='" + mCustomId + '\'' +
'}';
}
}
调用:
在activity初始化时:
InterstitalUtils.getShareInstance().init(this,adsInfoBean);
在触发广告时调用展示:
InterstitalUtils.getShareInstance().showIntertital(new InterstitalUtils.AdCloseListener() {
@Override
public void OnAdClosed() {
// loadAd();
}
});
ok,今天的admob广告就结束到这里了,有关激励视频以及原生广告实现欢迎一起探讨。记住,不要违反admob广告相关条约,以及展示广告的位置和时机。否则,封号就不远了。
学习资料地址为:资料自取