全文 11160 字数 455 行数;
目的将Unity应用 App上架到AmazonAppStore,接入亚马逊的广告,切换到亚马逊内购,本来是上架到Google的;
文章中接入广告的部分适用于Max聚合和Ironsource聚合;
文章目录
一.更换包名
通常包括:
1.
2.MainActivity.java
3.MyApplication.java
4.AndroidManifest.xml
5.google-services相关
…
二.Amazon包不需要firebase(需求)
去掉FIRE_BASE宏,要么删除Firebase
删除google-services
如果还需要 就替换google-services文件
三.Amazon包af中的channel=Amazon 区分大小写(需求)
AndroidManifest中加入
<meta-data android:name="CHANNEL" android:value="Amazon" />
四.Amazon包数数ID不变通过用户属性拆分2个平台, 新增version,参数Google & Amazon,对应包走对应用户属性(需求)
数数上报
AnalyticDataHelper.SetUserProperty(UserProperty.version,"Amazon");
五.Amazon包暂时关闭评分功能(需求)
自行关闭
六.Amazon包的内购(主要)
1.先切换到Amazon平台
3.下载测试Json用在线json解析看
Json在线解析及格式化验证
如果有多个订阅VIP,几个subscriptionParent不能一样,因为订阅成功会返回这个值,并且把原来IAPManager中的购买成功回调ProcessPurchase如果有ID校验从原来的
foreach (IAPProduct product in m_ActiveProducts)
{
if (product.productId == e.purchasedProduct.definition.id)
{
result = product.ProcessPurchase(e);
if (result == PurchaseProcessingResult.Complete)
{
consumePurchase = true;
}
resultProcessed = true;
}
}
改成
for (int i = 0; i < m_ActiveProducts.Count; i++)
{
if (m_ActiveProducts[i].productId == e.purchasedProduct.definition.id||
(e.purchasedProduct.definition.id=="weekly"&&m_ActiveProducts[i].productId=="7Days_VIP")||
(e.purchasedProduct.definition.id=="monthly"&&m_ActiveProducts[i].productId=="30Days_VIP")||
(e.purchasedProduct.definition.id=="yearly"&&m_ActiveProducts[i].productId=="360Days_VIP"))
{
result = m_ActiveProducts[i].ProcessPurchase(e);
if (result == PurchaseProcessingResult.Complete)
{
consumePurchase = true;
}
resultProcessed = true;
}
}
SubscriptionChecker里的CheckID换成sub的id
很难受
订单返回的ID不是productId,而是json中的subscriptionParent
如果有类似
IAPManager.Instance.GetSubscriptionInfo(productID)
传入的ID要从之前的productId(例:30Days_VIP)
换成son中的subscriptionParent(例:monthly)
就是说30Days_VIP只用在CataLog,iap按钮上,成功回调校验里 monthly用在获取订阅信息,和成功的主要校验,甚至上报;
就是Services-IAP-Catalog里的商品ID和数量要<=导出商品json文件amazon.sdktester.json中的数量;
1.如果付款界面弹不出来,就是Json文件和catalog不对应;
2.如果付款成功之后UI没有表现,就是result = m_ActiveProducts[i].ProcessPurchase(e)上面的判断没走通,id没对应;
3.如果付款完一切正常,再次购买别的商品,出现上一个订单没完成的弹窗,就是成功回调里的
return (consumePurchase) ? PurchaseProcessingResult.Complete : PurchaseProcessingResult.Pending;
没走到;
七.Amazon包的广告接入(主要)
1.使用admob的开屏(因为不支持max开屏)
2.更换max或者Ironsource广告相关,开屏广告相关一系列ID和key
3.额外处理APS
下载资源
导入unity_aps\unity_aps下面的 APS_Core_1_7_0.unitypackage
点击安装max支持如果是Ironsource就安装对应的
向Android清单添加权限/活动
清单文件中必须存在以下权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
如果您希望传递地理位置信息,请在您的清单文件中包含以下权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
(必要)在下添加以下内容清单文件的部分:
<activity android:name="com.amazon.device.ads.DTBInterstitialActivity"/>
<activity android:name="com.amazon.device.ads.DTBAdActivity"/>
然后开始把aps广告与之前的max广告混合(Ironsource逻辑一样下面代码以max为例)
新增Amazon广告ID(换成自己广告位的ID)
//amazon
public const string AmazonBannerSlotId = "edb16a-007e-40af-a3b5-742e840e4eab";
public const string AmazonBannerPadSlotId = "680e96-945f-465e-b760-983df01408b23";
public const string AmazonInterstitialVideoSlotId = "50f2ff-2ea1-46ec-80b4-062c3d067ca1";
public const string AmazonRewardVideoSlotId = "1c69e0-e71b-475f-904b-d073e6d18213";
public const string AmazonAppId = "85a752-9410-4fb1-aab2-8dd2332c9d8a";
Amazon广告初始化
#if !UNITY_EDITOR
Amazon.Initialize(AdMaxType.AmazonAppId);
Amazon.SetAdNetworkInfo(new AdNetworkInfo(DTBAdNetwork.MAX));
#endif
加载Amazon的APS广告(只需要改加载逻辑)
下面因项目聚合而异(以max为例)
加载Banner
之前的
MaxSdk.LoadRewardedAd(adUnit);
把之前的加载banner部分换成
private void LoadBanner()
{
#if UNITY_EDITOR
AdsManager.instance.CreateBanner(AdMaxType.BannerId, MaxSdkBase.BannerPosition.BottomCenter);
return;
#endif
int width;
int height;
string slotId;
if (MaxSdkUtils.IsTablet())
{
width = 728;
height = 90;
slotId = AdMaxType.AmazonBannerPadSlotId;
}
else
{
width = 320;
height = 50;
slotId = AdMaxType.AmazonBannerSlotId;
}
var apsBanner = new APSBannerAdRequest(width, height, slotId);
apsBanner.onSuccess += (adResponse) =>
{
MaxSdk.SetBannerLocalExtraParameter(AdMaxType.BannerId, "amazon_ad_response", adResponse.GetResponse());
AdsManager.instance.CreateBanner(AdMaxType.BannerId, MaxSdkBase.BannerPosition.BottomCenter);
MaxSdk.SetBannerExtraParameter(AdMaxType.BannerId,"allow_pause_auto_refresh_immediately", "true");
AdsManager.instance.HideBanner();
};
apsBanner.onFailedWithError += (adError) =>
{
MaxSdk.SetBannerLocalExtraParameter(AdMaxType.BannerId, "amazon_ad_error", adError.GetAdError());
AdsManager.instance.CreateBanner(AdMaxType.BannerId, MaxSdkBase.BannerPosition.BottomCenter);
MaxSdk.SetBannerExtraParameter(AdMaxType.BannerId,"allow_pause_auto_refresh_immediately", "true");
AdsManager.instance.HideBanner();
};
apsBanner.LoadAd();
}
如果是Ironsource聚合,banner宽高只能是320*50
特别注意事项(上面代码已经写了):亚马逊banner之前在安卓接入时遇到非预期场景仍展示banner,无法隐藏掉的情况,请开发同学此次接入的时候关注该问题是否还会复现,如果是的话,采用下方hide方式:MaxSdk.SetBannerExtraParameter(“替换实际banner unit id”,“allow_pause_auto_refresh_immediately”, “true”);
加载rewardedVideoAd
之前的
MaxSdk.LoadRewardedAd(adUnit);
把之前的加载激励广告部分换成
private bool m_isFirstLoadRewardAd = true;
public override void cacheAdVideo()
{
#if UNITY_EDITOR
string adUnit = AdMaxType.Reward_Android.ToString();//!avVideoRevive ? AdMaxType.Reward_Android.ToString() : AdMaxType.Reward_Android_revive.ToString();
GameLog.Debug("[AdManager] AppLovin SDK is cacheAdVideo" + adUnit);
MaxSdk.LoadRewardedAd(adUnit);
return;
#endif
if (m_isFirstLoadRewardAd)
{
m_isFirstLoadRewardAd = false;
var rewardedVideoAd = new APSVideoAdRequest(320, 480, AdMaxType.AmazonRewardVideoSlotId);
rewardedVideoAd.onSuccess += (adResponse) =>
{
string adUnit = AdMaxType.Reward_Android.ToString();
MaxSdk.SetRewardedAdLocalExtraParameter(adUnit, "amazon_ad_response", adResponse.GetResponse());
Debug.Log("[AdManager] AppLovin SDK is cacheAdVideo" + adUnit);
MaxSdk.LoadRewardedAd(adUnit);
};
rewardedVideoAd.onFailedWithError += (adError) =>
{
string adUnit = AdMaxType.Reward_Android.ToString();
MaxSdk.SetRewardedAdLocalExtraParameter(adUnit, "amazon_ad_error", adError.GetAdError());
Debug.Log("[AdManager] AppLovin SDK is cacheAdVideo" + adUnit);
MaxSdk.LoadRewardedAd(adUnit);
};
rewardedVideoAd.LoadAd();
}
else
{
string adUnit2 = AdMaxType.Reward_Android.ToString();//!avVideoRevive ? AdMaxType.Reward_Android.ToString() : AdMaxType.Reward_Android_revive.ToString();
GameLog.Debug("[AdManager] AppLovin SDK is cacheAdVideo" + adUnit2);
MaxSdk.LoadRewardedAd(adUnit2);
}
}
加载interstitialVideoAd
之前的
string adUnit = AdMaxType.Interstitial_android.ToString();
string adUnit2 = AdMaxType.Interstitial_android2.ToString();
#if UNITY_EDITOR
if (!isInterstitialVideoAvailableStr(adUnit))
{
Debug.Log("[AdManager] AppLovin SDK is cacheInterstitialVideo" + adUnit);
MaxSdk.LoadInterstitial(adUnit);
AnalyticDataHelper.Track("adi_request_load", new Dictionary<string, object>()
{
});
}
if (!isInterstitialVideoAvailableStr(adUnit2))
{
Debug.Log("[AdManager] AppLovin SDK is cacheInterstitialVideo" + adUnit2);
MaxSdk.LoadInterstitial(adUnit2);
AnalyticDataHelper.Track("adi_request_load", new Dictionary<string, object>()
{
});
}
Debug.Log("[AdsManager] adi_request_load ");
return;
#endif
改成
private bool m_isFirstLoadIntersAd = true;
public override void cacheInterstitialVideo()
{
string adUnit = AdMaxType.Interstitial_android.ToString();
string adUnit2 = AdMaxType.Interstitial_android2.ToString();
#if UNITY_EDITOR
if (!isInterstitialVideoAvailableStr(adUnit))
{
Debug.Log("[AdManager] AppLovin SDK is cacheInterstitialVideo" + adUnit);
MaxSdk.LoadInterstitial(adUnit);
AnalyticDataHelper.Track("adi_request_load", new Dictionary<string, object>()
{
});
}
if (!isInterstitialVideoAvailableStr(adUnit2))
{
Debug.Log("[AdManager] AppLovin SDK is cacheInterstitialVideo" + adUnit2);
MaxSdk.LoadInterstitial(adUnit2);
AnalyticDataHelper.Track("adi_request_load", new Dictionary<string, object>()
{
});
}
Debug.Log("[AdsManager] adi_request_load ");
return;
#endif
if (m_isFirstLoadIntersAd)
{
m_isFirstLoadIntersAd = false;
var interstitialVideoAd = new APSVideoAdRequest(320, 480, AdMaxType.AmazonInterstitialVideoSlotId);
interstitialVideoAd.onSuccess += (adResponse) =>
{
Debug.Log("interstitialVideoAd.onSuccess");
MaxSdk.SetInterstitialLocalExtraParameter(AdMaxType.Interstitial_android, "amazon_ad_response", adResponse.GetResponse());
MaxSdk.SetInterstitialLocalExtraParameter(AdMaxType.Interstitial_android2, "amazon_ad_response", adResponse.GetResponse());
MaxSdk.LoadInterstitial(adUnit);
MaxSdk.LoadInterstitial(adUnit2);
};
interstitialVideoAd.onFailedWithError += (adError) =>
{
Debug.Log("interstitialVideoAd.onFailedWithError");
MaxSdk.SetInterstitialLocalExtraParameter(AdMaxType.Interstitial_android, "amazon_ad_error", adError.GetAdError());
MaxSdk.SetInterstitialLocalExtraParameter(AdMaxType.Interstitial_android2, "amazon_ad_error", adError.GetAdError());
MaxSdk.LoadInterstitial(adUnit);
MaxSdk.LoadInterstitial(adUnit2);
};
interstitialVideoAd.LoadAd();
}
else
{
if (!isInterstitialVideoAvailableStr(adUnit))
{
Debug.Log("[AdManager] AppLovin SDK is cacheInterstitialVideo" + adUnit);
MaxSdk.LoadInterstitial(adUnit);
AnalyticDataHelper.Track("adi_request_load", new Dictionary<string, object>()
{
});
}
if (!isInterstitialVideoAvailableStr(adUnit2))
{
Debug.Log("[AdManager] AppLovin SDK is cacheInterstitialVideo" + adUnit2);
MaxSdk.LoadInterstitial(adUnit2);
AnalyticDataHelper.Track("adi_request_load", new Dictionary<string, object>()
{
});
}
Debug.Log("[AdsManager] adi_request_load ");
}
}
APS接入End;
4.测试APS广告
要启用SDK日志记录和测试模式,请调用以下方法。
// Enable testing and logging.
Amazon.EnableTesting (true); // Make sure to take this off when going live.
Amazon.EnableLogging (true);
查看错误代码集成验证
日志过滤errorCode
1.ErrorCode–400
Response :{“instrPixelURL”:“https://aax-us-east.amazon-adsystem.com/x/px/p/null/”,“errorMessage”:“[INVALID_REQUEST]”,“errorCode”:“400”,“status”:“error”}
后台广告尺寸配置问题,注意banner 有pad和普通两个尺寸
八.Amazon包广告需求ID更换
1.更换Max(Ironsource)相关的ID
2.更换AndroidManifest中的AppID
3.更换Amazon 广告ID
4.更换开屏相关的ID(包括Assets-GoogleMobileAds-Settings选项下的appid)
注:开屏 admob 正式ID,在未上架之前不填广告,技术代码则需要替换测试ID,然后打包给测试,测试好没问题之后,上线之前技术代码侧再换成正式ID