Unity项目添加广告,内购测试并上线APP Store
Ⅰ.添加广告并真机测试
1.用示例广告ID演示Admob Unity 插件
参考(admob官方文字教程)
导入插件包
设置Admob应用ID
示例广告id(测试时务必用示例广告id)
注意导出的app包主文件已变,不要打开错了。
(即在xcode内打开的主文件由.xcodeproj变成.xcworkspace)
添加一个示例激励广告
...
using GoogleMobileAds.Api;
...
public class GoogleMobileAdsDemoScript : MonoBehaviour
{private RewardBasedVideoAd rewardBasedVideo;...public void Start(){#if UNITY_ANDROID//示例广告的appIDstring appId = "ca-app-pub-3940256099942544~3347511713";#elif UNITY_IPHONEstring appId = "ca-app-pub-3940256099942544~1458002511";#elsestring appId = "unexpected_platform";#endif// Initialize the Google Mobile Ads SDK.初始化MobileAds.Initialize(appId);// Get singleton reward based video ad reference.激励广告是单例模式,把脚本关联上单例this.rewardBasedVideo = RewardBasedVideoAd.Instance;this.RequestRewardBasedVideo();//尽早加载广告资源}private void RequestRewardBasedVideo(){#if UNITY_ANDROID//示例广告IDstring adUnitId = "ca-app-pub-3940256099942544/5224354917";#elif UNITY_IPHONEstring adUnitId = "ca-app-pub-3940256099942544/1712485313";#elsestring adUnitId = "unexpected_platform";#endif// Create an empty ad request.创建一个新广告请求AdRequest request = new AdRequest.Builder().Build();// Load the rewarded video ad with the request.加载this.rewardBasedVideo.LoadAd(request, adUnitId);}
}
hello world示例里创建的广告需求
广告事件
...
using GoogleMobileAds.Api;
...
public class GoogleMobileAdsDemoScript : MonoBehaviour
{private RewardBasedVideoAd rewardBasedVideo;...public void Start(){// Get singleton reward based video ad reference.this.rewardBasedVideo = RewardBasedVideoAd.Instance;// Called when an ad request has successfully loaded.rewardBasedVideo.OnAdLoaded += HandleRewardBasedVideoLoaded;// Called when an ad request failed to load.rewardBasedVideo.OnAdFailedToLoad += HandleRewardBasedVideoFailedToLoad;// Called when an ad is shown.rewardBasedVideo.OnAdOpening += HandleRewardBasedVideoOpened;// Called when the ad starts to play.rewardBasedVideo.OnAdStarted += HandleRewardBasedVideoStarted;// Called when the user should be rewarded for watching a video.rewardBasedVideo.OnAdRewarded += HandleRewardBasedVideoRewarded;// Called when the ad is closed.rewardBasedVideo.OnAdClosed += HandleRewardBasedVideoClosed;// Called when the ad click caused the user to leave the application.rewardBasedVideo.OnAdLeavingApplication += HandleRewardBasedVideoLeftApplication;this.RequestRewardBasedVideo();}private void RequestRewardBasedVideo(){#if UNITY_ANDROIDstring adUnitId = "ca-app-pub-3940256099942544/5224354917";#elif UNITY_IPHONEstring adUnitId = "ca-app-pub-3940256099942544/1712485313";#elsestring adUnitId = "unexpected_platform";#endif// Create an empty ad request.AdRequest request = new AdRequest.Builder().Build();// Load the rewarded video ad with the request.this.rewardBasedVideo.LoadAd(request, adUnitId);}public void HandleRewardBasedVideoLoaded(object sender, EventArgs args){MonoBehaviour.print("HandleRewardBasedVideoLoaded event received");}public void HandleRewardBasedVideoFailedToLoad(object sender, AdFailedToLoadEventArgs args){MonoBehaviour.print("HandleRewardBasedVideoFailedToLoad event received with message: "+ args.Message);}public void HandleRewardBasedVideoOpened(object sender, EventArgs args){MonoBehaviour.print("HandleRewardBasedVideoOpened event received");}public void HandleRewardBasedVideoStarted(object sender, EventArgs args){MonoBehaviour.print("HandleRewardBasedVideoStarted event received");}public void HandleRewardBasedVideoClosed(object sender, EventArgs args){MonoBehaviour.print("HandleRewardBasedVideoClosed event received");}public void HandleRewardBasedVideoRewarded(object sender, Reward args){string type = args.Type;double amount = args.Amount;MonoBehaviour.print("HandleRewardBasedVideoRewarded event received for "+ amount.ToString() + " " + type);}public void HandleRewardBasedVideoLeftApplication(object sender, EventArgs args){MonoBehaviour.print("HandleRewardBasedVideoLeftApplication event received");}
}
展示广告&重新加载一段新的广告
2.使用自己创建的真实广告ID并真机测试
参考来源-admob测试广告
上面说的是用示例广告测试,下面我们说真实广告真机测试。
3.问题爬坑:
1.编译时
bug:framework not found iosurface for architecture arm64
bug:framework not found fileprovider for architecture arm64
解决方法:参考
点击上面的地址,下个9.0以上的版本,下完解压后不用安装,直接打开包内容。按照路径拷贝(拷贝到iPhoneOS.sdk而不是iPhonexx.x.sdk下面)。拷贝完在xcode打开的项目里清除,然后编译就OK了。
2.注意不要搞混id
Start()里是该应用注册的admob id,Request()里是该应用的广告单元id。
3.注册代理来监听事件的位置
激励广告常用两个事件:OnAdRewarded (发放奖励),OnAdClosed(关掉了视频就再请求加载新广告,暂停音效和游戏进程在这里恢复)。
之前看油管教程说注册和取消注册放在OnEnabled()和OnDisabled()里,但我试了没有反应,最后按照官方指导的把注册放在Start()里,取消还是放在Ondisabled()里(能否注销还未测试)。
4.怎样发放奖励
在创建广告单元时要填写reward的类型(type)和数量(amount),所以发放奖励不要再自己另写了。
5.编译时崩溃并xcode日志提示The Google Mobile Ads SDK was initialized incorrectly.
参考上面在unity内对admob adID的设置。也可以参考
6.build出的xcode工程里没有scworkspace文件
是cocoapods的版本问题,大概流程是 ①卸载已有的cocoapods - ②安装新版cocoapods - ③拉取cocoapods依赖的库 - ④更新。参考来源
①打开终端,先卸载
sudo gem uninstall cocoapods -n/usr/local/bin
命令窗口中,遇到对话,输入y,并回车
②卸载完毕后,继续执行命令安装新版
sudo gem install cocoapods -n/usr/local/bin
如果成功安装就进行下一步,如果提示错误
ERROR: Could not find a valid gem ‘cocoapods’ (>= 0), here is why:
Unable to download data from https://rubygems.org/ — SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/specs.4.8.gz)”
则输入下面命令
gem source -r https://rubygems.org/
gem source -a http://rubygems.org/
sudo gem install cocoapods
可成功安装。参考来源
如果提示ruby版本过低,则输入以下命令查看ruby源
gem sources -l //查看ruby源
默认情况下会显示
https://rubygems.org/
如果科学的使用了上网,则掠过下一步,如果没有:
//***********************//
ruby
源在墙内是访问不到的,需要置换为国内,原来一直用的是淘宝的,由于淘宝源不再更新,所以不在使用,现在用下面这个
//删除原始的源
gem sources --remove https://rubygems.org/
//添加新源(国内Ruby镜像)
gem source -a https://gems.ruby-china.com
只有在终端中出现下面文字才表明你上面的命令是成功的:
https://gems.ruby-china.com added to sources
为了验证你的Ruby
镜像是并且仅是gems.ruby-china
,可以用以下命令查看:
gem sources -l //检测是否成功
//*************************//
然后升级gem,gem是管理ruby的标准包
sudo gem update --system //升级gem
目前查看gem
版本为
gem -v //查看版本
正常的话就重新安装cocoapods
sudo gem install cocoapods -n/usr/local/bin
③拉取cocoapods依赖的库
打开访达Command + Shift + G,输入~/.cocoapods,到达该目录,删除该目录下所有内容,然后在该.cocoapods目录下创建repos文件夹。
在终端里一个一个执行下面三个命令(一个执行完了再输入下一个)
cd ~/.cocoapods/repos
git clone --depth 1 https://github.com/CocoaPods/Specs.git master
pod repo update
第二个命令会执行的久一些,如果出现拉取失败的各种提示,比如我的提示
error: RPC failed; curl 56 LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno 54
则可按参考来源尝试,我是没登GitHub,登陆了再次输入克隆命令后花了些时间就成功了。(所以可以尝试多克隆几次)
④最后一句命令完成后cocoapods就更新完毕,unity内重新build后就能看到xcworkspace文件了。
Ⅱ.添加内购并真机测试
1.基础iOS文件设置
登陆苹果开发者账号,选择Certificates,Identifiers & Profiles
其实这些步骤如果完成上面的真机测试的话都已经使用过了。
即有证书(Certificates)才能证明自己的身份,App IDs提供app 的bundle ID,配置文件(pp)容许开发者把应用装到测试机器上。参考1 参考2
2.协议、税务和银行业务 设置
点击苹果开发者账号的appstore connect(如果不是苹果机的话直接浏览器里搜然后用苹果开发者账号登陆)。
点击 协议、税务和银行业务
进入后点击
浙商银行网站查询CNAPS
3. 我的APP 设置
返回appstore connect首页,点击 我的APP,点击+号创建app。
如果提示“您没有适用于 iOS App的合格套装ID”,证明现在你没有还未管理的bundle ID了。
回到Appstore connect-我的App继续创建App
填写好基础信息
如果提示bundle ID不匹配无法创建的话,说明当前已有的bundle ID都已申请绑定好app了,再注册个新的bundle id就好了。
下图在要上线提交前再填写,只是沙箱真机测试的话不用管。
之后我们点击 功能 添加内购项目
苹果对上面内购类型的解释:
填写完毕后如下
上面 元数据丢失是因为我没有填写屏幕快照和审核信息,完整填写后就会显示准备提交。上面显示的“您的首个App内购买项目必须以新的App版本提交”不用管,意思是要在appstore内让玩家使用的话必须提交。沙箱真机测试就不用了。
4.设置沙盒测试
5.Unity内内购设置
先按照参考里在Unity的Services打开In-App Purchasing并导入官方包。
1.如果使用IAPButton(几乎没有代码,特点是丑)
参考
之后新建camera模式的canvas并添加iap button
之后点击iap catalog填写信息
ID就填写之前在appstore connect里设置的id
Title和Description填写
然后点开Apple Configuration填写之前设置的该内购的标价。
Apple SKU和 Apple Team ID
添加完后关闭iap catalog选择刚添加的product ID
然后添加购买完成的代码
2.单用脚本实现内购
首先Unity内Window > Unity IAP > IAP Receipt Validation Obfuscator.打开验证混淆窗口。如果使用Google Play则复制进Google的公钥,如果只用Apple的话不用添加任何东西直接点红框按钮,Unity会在文件里生成Tangle文件。这个工具主要是加密收据并验证收据。
新建IAP脚本如下
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Security;
using System;public class IAP : MonoBehaviour, IStoreListener
{IStoreController m_StoreController; // The Unity Purchasing system.IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems.IAppleExtensions m_AppleExtensions;ConfigurationBuilder builder;public string coins100 = "com.mycompany.app.100coins";//消耗型public string newMap = "com.mycompany.app.newMap";//非消耗型public string subscription = "com.mycompany.app.subscription";//非续期型订阅public string newableSub = "com.mycompany.app.newablesubscription";//可续期型订阅//建议使用可续期型订阅通过SubscriptionManager读取是否到期等属性void Start(){if (m_StoreController == null){InitializePurchasing();}}public void InitializePurchasing()//添加商品并初始化内购系统{if (IsInitialized())return;builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());builder.AddProduct(coins100, ProductType.Consumable);//在这里添加内购产品builder.AddProduct(newMap, ProductType.NonConsumable);builder.AddProduct(subscription, ProductType.Subscription);builder.AddProduct(newableSub, ProductType.Subscription);UnityPurchasing.Initialize(this, builder);}private bool IsInitialized()//判定是否初始化,初始化在OnInitialized()里{return m_StoreController != null && m_StoreExtensionProvider != null;}void BuyProductID(string productId)//充值内购按钮调用{if (IsInitialized()){// ... look up the Product reference with the general product identifier and the Purchasing // system's products collection.Product product = m_StoreController.products.WithID(productId);// If the look up found a product for this device's store and that product is ready to be sold ... if (product != null && product.availableToPurchase){Console.WriteLine(string.Format("异步购买: '{0}'", product.definition.id));m_StoreController.InitiatePurchase(product);//开始购买}else{Console.WriteLine("购买失败:无此产品或此产品无法购买");}}else{Console.WriteLine("购买失败:IAP未完成初始化");}}//恢复购买按钮调用,用于Non-Consumable(比如关卡等)和renewable Subscription(可续期订阅),消耗类和非续期订阅不可恢复public void RestorePurchases(){if (!IsInitialized()){Debug.Log("购买失败:IAP还未完成初始化");return;}//和以前不同的是:不要在这里判断平台,应该在UI里判断,如果不是ios则不要显示恢复按钮if (m_StoreExtensionProvider != null){IAppleExtensions apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();// Begin the asynchronous process of restoring purchases. Expect a confirmation response in // the Action below, and ProcessPurchase if there are previously purchased products to restore.apple.RestoreTransactions((result) => {if (result){Console.WriteLine("正在恢复: " + result + ". If no further messages, no purchases available to restore.");//注意这里恢复的是购买的非消耗品。会自动调用一次非消耗品的脚本//在此为://else if (string.equals(e.purchasedproduct.definition.id, newmap, stringcomparison.ordinal))//{// debug.log(string.format("processpurchase: pass. product: '{0}'", e.purchasedproduct.definition.id));// // todo: the non-consumable item has been successfully purchased, grant this item to the player.//}里的todo}else{Console.WriteLine("恢复购买失败");}});}}public void CheckSub()//使用SubscriptionManager检查订阅是否到期{m_AppleExtensions = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();foreach (var item in m_StoreController.products.all){if (item.receipt != null){if (item.definition.type == ProductType.Subscription){string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];SubscriptionManager p = new SubscriptionManager(item, intro_json);SubscriptionInfo info = p.getSubscriptionInfo();Console.WriteLine("产品ID: " + info.getProductId());Console.WriteLine("购买日期: " + info.getPurchaseDate());Console.WriteLine("到期时间为: " + info.getExpireDate());//返回产品下次自动续订或到期的日期(对于已取消的自动续订订阅)Console.WriteLine("是否已订阅 :" + info.isSubscribed().ToString());//非自动更新订阅返回“Result.Unsupported”Console.WriteLine("是否已过期 :" + info.isExpired().ToString());//非自动更新订阅返回“Result.Unsupported”Console.WriteLine("是否续期: " + info.isCancelled());//意味着已订阅,但不会续期,非自动更新订阅返回“Result.Unsupported”Console.WriteLine("产品是否为免费试用版 :" + info.isFreeTrial());//非自动更新订阅返回“Result.Unsupported”Console.WriteLine("是否自动续订: " + info.isAutoRenewing());//非自动更新订阅返回“Result.Unsupported”Console.WriteLine("下个结算日期前剩余时间: " + info.getRemainingTime());//下一个结算日期之前剩余的时间,返回“TimeSpan”Console.WriteLine("是否在介绍期内: " + info.isIntroductoryPricePeriod());//非自动更新订阅返回“Result.Unsupported”Console.WriteLine("介绍价格: " + info.getIntroductoryPrice());//该产品的介绍价格,返回格式为“0.99USD”的值Console.WriteLine("介绍期剩余时间: " + info.getIntroductoryPricePeriod()); //没有介绍价格期的订阅产品返回“TimeSpan.Zero”Console.WriteLine("介绍期内可应用此产品的数量: " + info.getIntroductoryPricePeriodCycles());//返回intif (info.isSubscribed() == Result.True){if (info.isExpired() == Result.False){if (String.Equals(info.getProductId(), newableSub, StringComparison.Ordinal)){Console.WriteLine(string.Format("订阅有效:", info.getProductId()));//这里写执行}}elseConsole.WriteLine("订阅过期");}}}}}public void CheckSubscriptionReceipt()//另一种检查订阅方法,通过receipt里的expiredate和当前时间对比来判断是否过期{var appleConfig = builder.Configure<IAppleConfiguration>();//关于applestore的配置var receiptData = Convert.FromBase64String(appleConfig.appReceipt);//将receipt转换为64位AppleReceipt receipt = new AppleValidator(AppleTangle.Data()).Validate(receiptData);//AppleReceiptParser收据验证//这里如果不使用unity的收据混淆则为:AppleReceipt receipt = new AppleReceiptParser().Parse(receiptData);foreach (AppleInAppPurchaseReceipt productReceipt in receipt.inAppPurchaseReceipts){//这里如果有多个订阅的话,可以先匹配productID,再读取productTypeif (productReceipt.productType == 3)//有三种类型:消耗/非消耗/订阅 {Console.WriteLine("订阅productID = " + productReceipt.productID);DateTime expirationDate = productReceipt.subscriptionExpirationDate;//订阅到期时间Console.WriteLine("订阅到期时间 = " + expirationDate.ToString());DateTime now = DateTime.Now.ToUniversalTime();//转换为世界时间if (DateTime.Compare(now, expirationDate) < 0)//DateTime.Compare(t1,t2);t1早于t2小于0(等于0,大于0)Console.WriteLine("订阅未过期");//在这里写逻辑else//订阅无效,在这里写逻辑Console.WriteLine("订阅已过期");}}}//--------IStoreListener接口public void OnInitialized(IStoreController controller, IExtensionProvider extensions){Debug.Log("初始化通过");m_StoreController = controller;m_StoreExtensionProvider = extensions;}public void OnInitializeFailed(InitializationFailureReason error){Debug.Log("初始化失败,原因:" + error);}public void OnPurchaseFailed(Product i, PurchaseFailureReason p){Debug.Log(string.Format("购买失败. Product: '{0}', 原因: {1}", i.definition.storeSpecificId, p));}public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)//在这里写内购成功后的操作{bool validPurchase = true; // Presume valid for platforms with no R.V.var validator = new CrossPlatformValidator(GooglePlayTangle.Data(),AppleTangle.Data(), Application.identifier);try{//验证收据var result = validator.Validate(e.purchasedProduct.receipt);// For informational purposes, we list the receipt(s)Console.WriteLine("收据已验证. Contents:");foreach (IPurchaseReceipt productReceipt in result){AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt;if (null != apple){Console.WriteLine(apple.productID);Console.WriteLine(apple.purchaseDate);Console.WriteLine(apple.originalTransactionIdentifier);Console.WriteLine(apple.subscriptionExpirationDate);Console.WriteLine(apple.cancellationDate);Console.WriteLine(apple.quantity);}}}catch (IAPSecurityException){Console.WriteLine("无效收据");validPurchase = false;}if (validPurchase){if (string.Equals(e.purchasedProduct.definition.id, coins100, StringComparison.Ordinal)){Debug.Log(string.Format("购买成功. ID: '{0}'", e.purchasedProduct.definition.id));//这里写逻辑}else if (string.Equals(e.purchasedProduct.definition.id, newMap, StringComparison.Ordinal)){Debug.Log(string.Format("购买成功. ID: '{0}'", e.purchasedProduct.definition.id));//这里写逻辑}else if (string.Equals(e.purchasedProduct.definition.id, subscription, StringComparison.Ordinal)){Debug.Log(string.Format("购买成功. ID: '{0}'", e.purchasedProduct.definition.id));//这里写逻辑}else if (string.Equals(e.purchasedProduct.definition.id, newableSub, StringComparison.Ordinal)){Debug.Log(string.Format("购买成功. ID: '{0}'", e.purchasedProduct.definition.id));//这里写逻辑}else{Debug.Log(string.Format("购买失败. Unrecognized product: '{0}'", e.purchasedProduct.definition.id));}}// Return a flag indicating whether this product has completely been received, or if the application needs // to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still // saving purchased products to the cloud, and when that save is delayed. return PurchaseProcessingResult.Complete;}}
要说的是,里面有一个RestorePurchase方法和两个检查订阅是否过期的方法。经我测试保险起见在OnInitialized()里先调用RestorePurchases()再调用CheckSub()来恢复订阅逻辑。CheckSubscriptionReceipt()时见效时不见效。
注意如果要使用订阅的话最好用自动更新型订阅,方便Restore,同时SubscriptionManager里的各种属性也只对自动更新型有效。
如果使用服务器,则可以验证收据 参考
3.关于自动续订的各种情况
如果需要最新unity IAP的例子参考 和 Unity IAP 手册
4.问题爬坑
1.日志显示“初始化失败,原因:NoProductsAvailable”
有可能是因为没添加成功内购物品,日志里会显示UnityIAP:Received 0 products,且之后日志每项内购项目都会Unvailable product com.xxxxxx.xxxx 之类的。原因是开发者过期了,续费后不仅要在Developer Account里重新同意协议,还要在App connect的“协议,税务和银行业务”选项里重新统一一遍,直到下面你的app显示有效后就可以了。
Ⅲ.上线App Store
1.打包
xcode内Product→Archive打包。
然后验证
问题爬坑
1.Xcode内Build,Archive,Debug,Release,Profile,Analyze的区别
参考来源
Build则是xcode内的那个播放键,就是生成真机测试版本,archive是生成打包appstore上传的文件。
可能出现的问题
2.提示:“Code signing is required for product type 'Application' in SDK 'iOS 11.2”
参考来源
我出现这条提示时因为我把pp文件里的release版(需要distribution identity绑定)填成了debug版(developer identity),换成对应的就OK了。
3.提示:“Invalid bitcode version (Producer: '802.0.42.0_0' Reader: '800.0.42.1_0')”
参考来源
4.valid时提示UIApplicationExitsOnSuspend key invaild
参考来源
5.提示The Google Mobile Ads SDK was initialized incorrectly
参考来源
<key>GADIsAdManagerApp</key>
<true/>
6.提示all ios apps submitted to the app store must be built with the ios 13 sdk or later
是因为xcode版本太低了,先升级xcode。如果macOS版本太低升级不了Xcode的话先升级macOS
2.上传到AppStore(即上传在AppConnect里的“构建版本”)
参考来源
问题爬坑:
①xcode 上传ipa时卡在authenticating,进度条不动了
建议更新下梯子,换个流畅的通道很快就好了。
②xcode内上传完成,但app connect内一直构建版本为空
ipa因为不合规定被打回了,登入注册developer账号的邮箱,苹果会发邮件并说明是什么原因。
修改后再次上传时记得版本号要升一阶。
③提交版本被打回,苹果邮箱提示ITMS-90809: Deprecated API Usage
因为使用了UIWebView API,在Unity和Admob的框架里都有使用。
虽然Unity和Admob都说已解决了问题。unity哪些版本修复了
此外,Unity引擎在所有受支持的版本中均删除了对UIWebview的引用:
2017.4.33f1
2018.4.10f1
2019.2.7f2
2019.3.0b4
2020.1.0a5
但我使用2019.3.8f1 2019.3.9f1 2018.4.22f1的中国特供版(是的,只能从unity.com下载)都还是有问题。
只有2020.1.0a25版本的Unity没有问题。(new:2019.3.13f1 中国特供版经我测试也没有问题)
查找当前版本有没有问题不用archive后上传后被拒后看邮件。直接在当前版本里新建空项目,转换到ios platform后build
然后在终端cd 你build好的文件夹 回车后 参考来源
grep -r UIWebView .
就会显示是否有UIWebview的引用。
admob说它修复了,但我更新了最新版本admob unity包 5.1.0 ,在使用unity 2020.1.0a25 版本下的空文件,还是提示有UIWebView的引用。所以目前我只能取消了游戏使用Admob,等之后版本出来会继续试看哪些能用。
查到的修改UIWebView 里面有修改libiPhone.a内的UIWebView的脚本,我试了还是不行。
④ xcode内上传了,app connect里的构建版本为空,也没有邮件提醒
在app connect 里查看 活动 选项卡,里面有你的版本,如果显示正在处理的话,20分钟以内会处理好,然后就可以在构建版本里选择你上传的版本了。20分钟还是正在处理的话 试试这个 。
⑤更新到最新的admob运行时提醒EntryPointNotFoundException: GADUCreateRewardedAd
没有问题不用管,这是移动端的调用,打包到真机后就不会有提醒了。
⑥app connect显示上传截屏尺寸不对
unity内项目build的时选simulator,然后在xcode内用模拟器针对appstore要求的各个尺寸截图。
⑦上传截屏显示不要使用Alhpa通道
直接mac打开截屏图片然后 文件-导出-取消勾选Alpha然后导出新图片就可以了。
Unity项目添加广告,内购测试并上线APP Store相关推荐
- Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解
这是第二篇 Cocos 2d-X Lua 游戏添加苹果内购(一) 图文详解准备流程 这是前面的第一篇,详细的说明了怎样添加内购项目以及填写银行信息提交以及沙盒测试员的添加使用以及需要我们注意的东西,结 ...
- Cocos 2d-X Lua 游戏添加苹果内购(一) 图文详解准备流程
事前准备 最近给游戏添加了苹果的内购,这一块的东西也是刚刚做完,总结一下,其实这里不管是游戏还是我们普通的App添加内购这一块的东西都是差不多的,多出来的部分就是我们Lua和OC的交互的部分,以前刚开 ...
- ios 内购正式环境_iOS app内购
一.测试账户生成 1.添加沙盒测试员 在App Store Connect中选择 Users and Access打开页面后在sandbox 下点击Testers,点击添加按钮(+),输入测试信息然后 ...
- Unity如何接入应用内购In-AppPurchase
一.前言 很多游戏需要接入内购IAP,对于苹果端,我们直接对接苹果就行了,但是android平台太多,国内,我们需要接入支付宝,微信,或者华为支付,小米支付等.国外,我们需要接入谷歌支付,亚马逊等等, ...
- iOS 内购提示不允许App内购买项目,打开内购方式和检测不允许内购的方法。
这个问题是屏幕使用时间里面关闭了内购功能 打开方法如下 设置->屏幕使用时间->内容和隐私访问限制->iTunes Store与App Store购买项目->APP内购买项目- ...
- iOS内购测试自动订阅型产品
最近产品需要涉及到订阅型的内购创建,上一次使用自动订阅内购还是好几年的事情了,很多内容大都忘得差不多了,加上苹果设计的内购又增加了一些新功能和改变,不得不重新来审视下自动订阅型内购,而官方又没有中文文 ...
- U3D如何添加IOS内购,自制内购小插件
参考资料:http://www.cocoachina.com/bbs/read.php?tid-69165-fpage-2.html 网上很多IAP的教程,但是较少有结合U3D的教程.所以我在此进行简 ...
- iOS内购IAP(In App Purchases)入门
成为ios开发者最大的好处就是,你编写的应用程序会有很多方式可以赚钱.比如,收费版,免费挂广告版,还有就是程序内置购买. 程序内置购买会让你爱不释手,主要有以下原因: 相比程序本身的下载收费以,你还可 ...
- ios 内购 未能连接上苹果服务器,ios - 模拟器如何调试内购内容,无法连接iTunes Store...
PHPzhong2017-04-18 09:16:422楼 请参照此checkList 1.您是否在iOS Dev Center中打开了对应应用AppID的In-App Purchases功能?登陆i ...
最新文章
- django 的用户验证及登录状态保持
- spoj Pattern Find(kmp)
- ros和java通讯_ROS学习之路(二)——通信架构(上)
- Javascript 問題汇总(不定期更新)【一】
- oracle 怎么创建类型,ORACLE—002:Create之创建类型
- 因为一个字符校对问题,我的大厂面试挂了
- Ajax的JSP示例以及相关知识介绍,适合于入门者
- 丰富的else语句及简洁的with语句 - 零基础入门学习Python034
- 上下文无关问法cfg
- 拖拽功能 php,js实现拖拽功能
- python中的commands模块
- 软件工程大作业:网上购物系统
- PostgreSql增删改(与mysql差异)
- 计算机日志存储在哪里,Win7系统日志存放位置的更改
- modbusx协议讲解
- LaTeX的正负号写法
- javaScript算术题(经典案例)
- 蓝牙那些事儿(5)——关于重传
- [词语辨析] Try, Attempt, Endeavour “尝试” 的用法
- 数学建模02 —— 多属性决策模型