此文档是为方便使用Unity3d引擎的开发者嵌入有米广告SDK而撰写的,由于边幅有限,本文档只详细只针对以下几种广告形式的嵌入使用
更多有米广告的功能使用请查看 官方AndroidSDK文档 ,同时,有错漏之处,敬请各位开发者指正。
本教程在以下环境中进行开发示例:
然后一直点击Next,最后点击Finish完成Android工程的创建。
将 Unity3d的Android插件jar (Unity3d安装目录/Editor/Data/PlaybackEngines/androidplayer/release/bin/classess.jar)以及 有米AndroidSDK的jar (压缩包下/libs/YoumiSdk***.jar) 复制到Android工程目录下的 libs 文件夹(如果没有就新建这个目录)下,然后将这两个jar添加到项目中
下面贴出了详细的配置,开发者请酌情选择配置。
注意:
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.youmi.android.unity3d.demo"
android:versionCode="1"
android:versionName="1.0" >
android:minSdkVersion="9"
android:targetSdkVersion="17" />
android:name="android.permission.INTERNET" />
android:name="android.permission.READ_PHONE_STATE" />
android:name="android.permission.ACCESS_NETWORK_STATE" />
android:name="android.permission.ACCESS_WIFI_STATE" />
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
android:name="android.permission.GET_TASKS" />
android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
android:name="android.permission.ACCESS_FINE_LOCATION" />
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait" >
android:name="android.intent.action.MAIN" />
android:name="android.intent.category.LAUNCHER" />
android:name="com.unity3d.player.UnityPlayerActivity" >
android:name="unityplayer.ForwardNativeEventsToDalvik"
android:value="true" />
android:name="net.youmi.android.AdBrowser"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:theme="@android:style/Theme.Light.NoTitleBar" >
android:name="net.youmi.android.AdService"
android:exported="false" >
android:name="net.youmi.android.AdReceiver" >
android:name="android.intent.action.PACKAGE_ADDED" />
android:scheme="package" />
android:name="net.youmi.android.video.VideoActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar" >
android:name="net.youmi.android.ExpService"
android:exported="false" >
android:name="YOUMI_CHANNEL"
android:value="这里替换为非负整数的渠道号" >
为了方便起见,下面贴出了广告使用的简明代码,开发者可以酌情复制。
注意:
开发者复制代码后需要替换appid 和appsecret 为 自己在 有米主站 上面申请的appid和appsecret
package com.youmi.android.unity3d.demo;
import net.youmi.android.AdManager;
import net.youmi.android.banner.AdSize;
import net.youmi.android.banner.AdView;
import net.youmi.android.banner.AdViewListener;
import net.youmi.android.listener.Interface_ActivityListener;
import net.youmi.android.offers.OffersManager;
import net.youmi.android.offers.OffersWallDialogListener;
import net.youmi.android.offers.PointsChangeNotify;
import net.youmi.android.offers.PointsManager;
import net.youmi.android.spot.SpotDialogListener;
import net.youmi.android.spot.SpotManager;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity implements PointsChangeNotify {
/**
* 无积分Banner
*/
AdView mAdView;
/**
* Handler,用于线程与UI交互
*/
Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
// 初始化接口,应用启动的时候调用,参数:appId, appSecret, 是否开启调试模式
AdManager.getInstance(this).init("9b26c34dca959658", "f5821b6374083845", false);
// (可选)开启用户数据统计服务,(sdk v4.08之后新增功能)默认不开启,传入false值也不开启,只有传入true才会调用
AdManager.getInstance(this).setUserDataCollect(true);
// --------------------------------------------------------------------------------
// 积分广告初始化及相关设置
// 如果使用积分广告,请务必调用积分广告的初始化接口:
OffersManager.getInstance(this).onAppLaunch();
// (可选)注册积分监听-随时随地获得积分的变动情况
PointsManager.getInstance(this).registerNotify(this);
// --------------------------------------------------------------------------------
// 插屏接口初始化及相关设置
// (建议使用)预加载插播资源
SpotManager.getInstance(this).loadSpotAds();
// (可选) 设置插屏图片为竖屏
SpotManager.getInstance(this).setSpotOrientation(
SpotManager.ORIENTATION_PORTRAIT);
// (可选) 设置插屏广告动画效果为高级动画效果
SpotManager.getInstance(this).setAnimationType(SpotManager.ANIM_ADVANCE);
// --------------------------------------------------------------------------------
// 视频广告接口初始化及相关设置
// (建议使用)预加载视频数据
// 视频设置,提供视频的各种设置,如设置退出提示语,更改退出按钮,加载中的logo。
VideoAdManager.getInstance(this).getVideoAdSetting().setInterruptsTips("是否要退出视频");
VideoAdManager.getInstance(this).requestVideoAd(new VideoAdRequestListener() {
@Override
public void onRequestSucceed() {
Log.d("videoPlay", "请求成功");
}
@Override
public void onRequestFail(int errorCode) {
// 关于错误码的解读:-1为网络连接失败,请检查网络。-2007为无广告,-3312为该设备一天的播放次数已完,其他错误码一般为设备问题。
Log.d("videoPlay", "请求失败,错误码为:" + errorCode);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// (可选)注销积分监听
// 如果在onCreate调用了PointsManager.getInstance(this).registerNotify(this)进行积分余额监听器注册,那这里必须得注销
PointsManager.getInstance(this).unRegisterNotify(this);
// 回收积分广告占用的资源
OffersManager.getInstance(this).onAppExit();
// 回收插屏广告占用的资源
SpotManager.getInstance(this).onDestroy();
super.onDestroy();
}
public void showVideo() {
mHandler.post(new Runnable() {
@Override
public void run() {
VideoAdManager.getInstance(MainActivity.this).showVideo(MainActivity.this,
new VideoAdListener() {
// 视频播放失败
@Override
public void onVideoPlayFail() {
Log.d("videoPlay", "failed");
}
// 视频播放完成
@Override
public void onVideoPlayComplete() {
Log.d("videoPlay", "complete");
Toast.makeText(MainActivity.this, "您获得了1个金币的奖励", Toast.LENGTH_SHORT).show();
}
// 视频播放完成的记录向服务器发送是否成功
@Override
public void onVideoCallback(boolean callback) {
// 视屏播放记录发送是否回调成功
Log.d("videoPlay", "completeEffect:" + callback);
}
// 视频播放中途退出
@Override
public void onVideoPlayInterrupt() {
Log.d("videoPlay", "interrupt");
Toast.makeText(MainActivity.this, "视频未播放完成,无法获取奖励", Toast.LENGTH_SHORT).show();
}
@Override
public void onDownloadComplete(String id) {
}
@Override
public void onNewApkDownloadStart() {
}
@Override
public void onVideoLoadComplete() {
// TODO Auto-generated method stub
}
});
}
});
}
/**
* 调用无积分插播广告--可以在Unity3d中直接调用
*/
public void showSpot() {
mHandler.post(new Runnable() {
@Override
public void run() {
// 展示插屏广告,可以不调用loadSpot独立使用
SpotManager.getInstance(MainActivity.this).showSpotAds(MainActivity.this,
new SpotDialogListener() {
@Override
public void onShowSuccess() {
showTipsInUiThread("插屏广告展示成功", Toast.LENGTH_SHORT);
}
@Override
public void onShowFailed() {
showTipsInUiThread("插屏广告展示失败\n原因请查看Logcat-tag:YoumiSdk", Toast.LENGTH_LONG);
}
@Override
public void onSpotClosed() {
showTipsInUiThread("插屏广告关闭了", Toast.LENGTH_SHORT);
}
});
}
});
}
/**
* 如果插屏广告展示时,需要通过按返回键来进行关闭插屏广告的话,就调用下面这个方法(可选)
*
* @param type
* 0 表示按了返回键
* 1 标识按了home键
* @return true 插屏广告已经消失了
* false 插屏广告还没有消失
*/
public boolean closeSpot(int type) {
if (type == 0) {
if (!SpotManager.getInstance(this).disMiss()) {
// 如果没有插屏广告在展示,就返回true,执行开发者的逻辑
return true;
} else {
// 如果有插屏广告在展示,就返回false
return false;
}
}
if (type == 1) {
// 按home键时,调用尝试关闭插屏广告的代码
// 如果不调用此方法,则按home键的时候会出现图标无法显示的情况。
SpotManager.getInstance(this).onStop();
return true;
}
return true;
}
/**
* 实例化无积分Banner并且将其加入到游戏界面中 --可以在Unity3d中直接调用
*/
public void showBanner() {
if (mAdView == null) {
mHandler.post(new Runnable() {
@Override
public void run() {
// 实例化广告条
mAdView = new AdView(MainActivity.this, AdSize.FIT_SCREEN);
mAdView.setAdListener(new AdViewListener() {
@Override
public void onSwitchedAd(AdView arg0) {
showTipsInUiThread("广告条切换广告了", Toast.LENGTH_SHORT);
}
@Override
public void onReceivedAd(AdView arg0) {
showTipsInUiThread("广告条接收到广告了", Toast.LENGTH_SHORT);
}
@Override
public void onFailedToReceivedAd(AdView arg0) {
showTipsInUiThread("广告条展示失败", Toast.LENGTH_LONG);
}
});
// 创建布局来承载广告条
LinearLayout layout = new LinearLayout(MainActivity.this);
layout.addView(mAdView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
// 采用WindowManager来进行
WindowManager mWindowManager = (WindowManager) MainActivity.this
.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams mWmParams = new WindowManager.LayoutParams();
mWmParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWmParams.height = -2;
mWmParams.width = -1;
mWmParams.alpha = 1.0F;
mWmParams.format = 1;
mWmParams.gravity = Gravity.BOTTOM;
mWindowManager.addView(layout, mWmParams);
}
});
}
}
/**
* 展示全屏积分墙--可以在Unity3d中直接调用
*/
public void showOffers() {
mHandler.post(new Runnable() {
@Override
public void run() {
OffersManager.getInstance(MainActivity.this).showOffersWall(new Interface_ActivityListener() {
@Override
public void onActivityDestroy(Context context) {
// TODO Auto-generated method stub
showTipsInUiThread("全屏积分墙退出了", Toast.LENGTH_LONG);
}
});
}
});
}
/**
* 展示对话框积分墙--可以在Unity3d中直接调用
*/
public void showOffersDialog() {
mHandler.post(new Runnable() {
@Override
public void run() {
OffersManager.getInstance(MainActivity.this).showOffersWallDialog(MainActivity.this,
new OffersWallDialogListener() {
@Override
public void onDialogClose() {
showTipsInUiThread("积分墙对话框关闭了", Toast.LENGTH_LONG);
}
});
}
});
}
/**
* 查询积分--可以在Unity3d中直接调用
*
* @return
*/
public int queryPoints() {
return PointsManager.getInstance(MainActivity.this).queryPoints();
}
/**
* 消费积分--可以在Unity3d中直接调用
*
* @param p
* @return
*/
public boolean spendPoints(int p) {
return PointsManager.getInstance(MainActivity.this).spendPoints(p);
}
/**
* 奖励积分(如用户完成了某个你觉得需要奖励他积分的操作时调用此接口进行奖励)--可以在Unity3d中直接调用
*
* @param p
* @return
*/
public boolean awardPoints(int p) {
return PointsManager.getInstance(MainActivity.this).awardPoints(p);
}
/**
* 积分余额变动通知,单用户的积分发生变动(增加或者减少)时,会回调本方法,本方法执行在UI线程中
*/
@Override
public void onPointBalanceChange(int arg0) {
// 当积分余额变动时,通知unity3d进行界面更新,
// 参数1:发送游戏对象的名称
// 参数2:对象绑定的脚本接收该消息的方法
// 参数3:本条消息发送的字符串信息
UnityPlayer.UnitySendMessage("Main Camera", "UpdatePoints", String.valueOf(arg0));
}
public void showTipsInUiThread(final String str, final int duartion) {
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, str, duartion).show();
}
});
}
}
清理项目:依次点击菜单栏Project->Clean->选择项目->确定
重新构建项目:依次点击菜单栏Project->Build Project(如果此选项不可点击,请先取消自动构建项目的设置,即点击菜单栏Project->BuildAutomatically)
使用cmd等命令行工具,到达 Android工程项目根路径/bin/classes 目录下,运行命令 jar -cvf ..\youmiu3ddemo.jar *
生成给Unity3d项目使用的jar,生成的jar在 Android工程项目根路径/bin 目录下
至此,Android工程项目的准备工作已完成。
开始之前请开发者自行设置Android Sdk的路径: 依次进入Edit->Preferences->External Tools->Android SDK Location
注意:
Unity3d项目中的默认屏幕方向,需要与Android项目中的 AndroidManifest.xml 中所设置的保持一致,不然启动app之后旋转屏幕可能会app崩溃的现象
需要导入的资源列表:
在Assets目录下新建脚本,这里提供C#和Js两种脚本示例,任选一种即可:
using UnityEngine;
using System.Collections;
public class YoumiU3dDemo : MonoBehaviour {
AndroidJavaClass mJc;
AndroidJavaObject mJo;
private int mPoints;
// 更新积分,这个方法在Android项目中调用
void UpdatePoints(string points) {
this.mPoints = int.Parse(points);
}
void OnGUI(){
GUILayout.Label("Youmi Unity3d Demo");
GUILayout.Label("Current Points: "+mPoints);
// 调用Android工程提供的api——展示插屏广告
if(GUILayout.Button("Show Spot",GUILayout.Height(100))){
mJo.Call("showSpot");
}
// 调用Android工程提供的api——展示视频广告
if (GUILayout.Button ("Show Video", GUILayout.Height (150))) {
mJo.Call("showVideo");
}
// 调用Android工程提供的api——展示全屏积分墙
if(GUILayout.Button("Show Offers",GUILayout.Height(100))){
mJo.Call("showOffers");
}
// 调用Android工程提供的api——展示对话框积分墙
if(GUILayout.Button("Show Offers Dialog",GUILayout.Height(100))){
mJo.Call("showOffersDialog");
}
// 调用Android工程提供的api——展查询积分
if(GUILayout.Button("Query Points",GUILayout.Height(100))){
this.mPoints=mJo.Call<int>("queryPoints");
}
// 调用Android工程提供的api——奖励10积分
if(GUILayout.Button("Award 10 Points",GUILayout.Height(100))){
if(mJo.Call<bool>("awardPoints",10)){
this.mPoints=mJo.Call<int>("queryPoints");
}
}
// 调用Android工程提供的api——消耗5积分
if(GUILayout.Button("Spend 5 Points",GUILayout.Height(100))){
if(mJo.Call<bool>("spendPoints",5)){
this.mPoints=mJo.Call<int>("queryPoints");
}
}
if(GUILayout.Button("Exit",GUILayout.Height(100))){
Application.Quit();
}
}
void Start () {
mJc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");
mJo=mJc.GetStatic<AndroidJavaObject>("currentActivity");
mJo.Call("showBanner");
}
void Update () {
if(Input.GetKeyDown(KeyCode.Escape)){
// 如果开发者使用了插屏广告,那么当按返回键的时候,逻辑应该如下:
// 1、如果插屏广告在展示时,返回键应该先关闭正在展示的插屏广告,在按一次返回键才执行开发者自己的逻辑(如:退出应用)
// 2、如果插屏广告没有在展示时,就进行自己的逻辑(如:退出应用等)
// 当插屏广告已经消失了,就执行后续逻辑(这里为退出应用)
// Android示例项目中定义0为返回键
if (mJo.Call<bool>("closeSpot", 0) == true) {
Application.Quit();
}
}
if(Input.GetKeyDown(KeyCode.Home)){
// 按Home键时,调用尝试关闭插屏广告的代码,开发者可以实现后续逻辑
// Android示例项目中定义1为Home键
if (mJo.Call<bool>("closeSpot", 1) == true) {
}
}
}
}
private var mPoints:int;
var mJc:AndroidJavaClass;
var mJo:AndroidJavaObject;
// 更新积分,这个方法在Android项目中调用
function UpdatePoints(points:String){
mPoints=parseInt(points);
}
function OnGUI(){
GUILayout.Label("Youmi Unity Demo");
GUILayout.Label("Current Points:"+mPoints);
// 调用Android工程提供的api——展示插屏广告
if(GUILayout.Button("Show Spot",GUILayout.Height(100))) mJo.Call("showSpot");
// 调用Android工程提供的api——展示全屏积分墙
if(GUILayout.Button("Show Offers",GUILayout.Height(100))) mJo.Call("showOffers");
// 调用Android工程提供的api——展示对话框积分墙
if(GUILayout.Button("Show Offers Dialog",GUILayout.Height(100))) mJo.Call("showOffersDialog");
// 调用Android工程提供的api——展查询积分
if(GUILayout.Button("Query Points",GUILayout.Height(100))) mPoints=mJo.Call.<int>("queryPoints");
// 调用Android工程提供的api——奖励10积分
if(GUILayout.Button("Award 10 Points",GUILayout.Height(100)))
if(mJo.Call.<boolean>("awardPoints",10))
mPoints=mJo.Call.<int>("queryPoints");
// 调用Android工程提供的api——消耗5积分
if(GUILayout.Button("Spend 5 Points",GUILayout.Height(100)))
if(mJo.Call.<boolean>("spendPoints",5))
mPoints=mJo.Call.<int>("queryPoints");
//退出
if(GUILayout.Button("Exit",GUILayout.Height(100))) Application.Quit();
}
function Start () {
mJc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");
mJo=mJc.GetStatic.<AndroidJavaObject>("currentActivity");
mJo.Call("showBanner");
}
function Update () {
if(Input.GetKeyDown(KeyCode.Escape)){
// 如果开发者使用了插屏广告,那么当按返回键的时候,逻辑应该如下:
// 1、如果插屏广告在展示时,返回键应该先关闭正在展示的插屏广告,在按一次返回键才执行开发者自己的逻辑(如:退出应用)
// 2、如果插屏广告没有在展示时,就进行自己的逻辑(如:退出应用等)
// 当插屏广告已经消失了,就执行后续逻辑(这里为退出应用)
// Android示例项目中定义0为返回键
if (mJo.Call.<boolean>("closeSpot", 0)) {
Application.Quit();
}
}
if(Input.GetKeyDown(KeyCode.Home)){
// 按Home键时,调用尝试关闭插屏广告的代码,开发者可以实现后续逻辑
// Android示例项目中定义1为Home键
if (mJo.Call.<boolean>("closeSpot", 1)) {
}
}
}
注意:
本示例中,demo生成了几个按钮,需要将脚本绑定到摄像机
至此,工作已经完毕,可以进行编译运行,此时建议连上手机进行调试
附:Demo运行界面