当前位置: 首页 > news >正文

Unity2022接入Google广告与支付SDK、导出工程到Android Studio使用JDK17进行打包完整流程与过程中的相关错误及处理经验总结

注:因为本人也是第一次接入广告与支付SDK相关的操作,网上也查了很多教程,很多也都是只言片语或者缺少一些关键步骤的说明,导致本人也是花了很多时间与精力踩了很多的坑才搞定,发出来也是希望能帮助到其他人在遇到相似问题的时候能少踩坑少熬夜少加班,至少能提供一个解决问题的思路,理论上该经验可适用于任意版本的SDK接入,总归思路都是差不多的,文章内容可能会不定期修改,如果存在不准确或理解错误的地方,可评论区通知我进行修改

注意翻墙问题,毕竟国内对于国外的网站很多是没办法进行访问的。
文章中所使用的各软件及插件版本说明(可能存在遗留的地方,可能后期修改补档吧,大部分通用没问题大概率不会改了)

Unity:2022.3.15

Unity所使用的 Google SDK:9.0.0(一开始使用的8.5版本,结果刚好弄完的时候该版本弃用了,只能换成了9.0.0,但9.0中所使用的SDK版本是23版本的,23版本需要JDK17与Gradle8.0才能编译,所以只能导出到Android Studio进行编译)

Google Play 支付采用的是接入原生支付进行操作的,版本为6.0,文章中主要包含一些经验总结,因为思路总体也是参考了其他人的文章

1、广告SDK接入

Google SDK获取地址:Google 广告 SDK Mobile Ads SDK (Unity)

需要关注的点:

1、广告SDK弃用时间,相关链接:弃用和停用  |  Unity  |  Google for Developers ,注意其中的版本信息对应的是Android原生SDK的版本信息,新手注意别搞混了,Unity所使用的插件中的版本信息需要从Github中对应版本的日志中进行查看

2、Android Gradle插件可使用的Gradle版本,相关链接:Android Gradle 插件 8.7 版本说明  |  Android Studio  |  Android Developers,注意让看这个主要是为了后边使用Android Studio进行编译的时候,知道该用那个版本进行编译

3、广告SDK接入流程并不复杂,心平气和看完操作步骤就可以搞定,别像我一样的因为加班太多太过浮躁导致简单的问题复杂化,所以具体接入步骤不做详细说明,根据SDK获取的界面中按照官方的步骤进行接入即可,需注意的关注的是,SDK所使用的JDK版本、Gradle版本是否与当前Unity版本是否兼容,例如本人使用的是Unity2022.3.15+广告SDK的9.0版本,而Unity2022没有办法更换使用JDK17(至少我没找到办法),所以需要导出到Android Studio进行打包操作

4、打包时google Setting中的应用id一定要填写,不填写的话,就算打包成功了,进行安装后同样也会因为ID未找到从而无法成功运行应用

5、接入的SDK版本较低时,SDK被弃用后,可以在安卓日志中看到Google的通知,广告不会正常播放,效果就是点击后没有任何效果

6、成功接入广告并打包后,正常情况下就可以看到广告的内容

7、播放广告后的奖励回调函数,记得一定使用协程进行操作,也就说传入的回调函数可以是普通函数,但关于传入的回调函数的最终执行时一定使用一个协程去运行, 因为直接进行调用,会导致应用直接就给闪退了

关于广告的部分就先到这里,因为广告的接入不难,难点都在打包的过程中了

2、原生支付SDK接入

接入原生支付后(也就是加入jar包后),需要打包后才能看到效果在编辑器中是没有办法看到效果的

先说明一下思路来源相关链接:

Unity接入GooglePlay内购V4 V5 V6(源生Android方式)_unity接入google内购-CSDN博客

后台UnityPlayer.UnitySendMessage不生效(Android) | 梓喵出没

第一个链接为参考原生支付接入的方法,而第二个则是对UnityPlayer.UnitySendMessage调用一次后再次进行调用时,没有任何反应的处理,至于为什么没有反应,简单来说就是被sendMessage调用的函数代码所在的activity需要保持在前台,一旦被切换为其他activity后,再次调用代码就没有什么效果了,我解释的可能太过笼统或者不正确,详细的解释请自行百度吧,或者遇到了的时候自然就懂了,所以这里推荐对于Unity内部方法的调用采用第二个链接中的方法,直接一劳永逸,即编写一个C#脚本继承AndroidJavaProxy类,用于实现Java代码中的接口,在初始化java对象时,new一个实现了Java接口函数的类同时传递给java对象,并保存一下对对象的引用,然后呢,直接把收到的对象当成一个接口使用就好了例如下边实现

C#代码:

代码只有部分啊,别全抄了,只是做参考,因为该代码也只是对第一个链接中的代码修改后得到的

public class IAPMessage : AndroidJavaProxy{public IAPMessage() : base("com.XXX.unitytogoolgleplaylib.IAPMessage"){}#region callback from Objective-c/JAR//获取到产品列表回调public void RecieveProductInfos(string jsonData){if (string.IsNullOrEmpty(jsonData)) return;var infoData = JsonConvert.DeserializeObject<IAPProductInfoData>(jsonData);OnProductInfoReceived(infoData);}//产品列表请求失败public void ProductRequestFail(string message){OnProductInfoFail(message);}//购买成功回调public void ProductBuyComplete(string productId){OnProductBuyComplete(productId);}//购买失败回调public void ProductBuyFailed(string jsonData){var infoData = JsonConvert.DeserializeObject<BuyFailData>(jsonData);OnBuyProductFail(infoData.productId, infoData.error);}//获取商品回执回调public void ProvideContent(string msg) { }//购买取消回调public void ProductBuyCancled(string productId){OnBuyProductCancled(productId);}/// <summary>/// 恢复购买成功/// </summary>/// <param name="productId"></param>public void RestoreComplete(string productId){OnRestoreCompleted(productId);}public void ConnectTips(){Debug.LogWarning("Java Connect!");}public void ConnectTips1(string str){Debug.LogWarning($"Java Connect Test {str}!");}private void ClearCallback(){ProductBuyFailedCallback = null;ProductBuyCompleteCallback = null;ProductBuyCancledCallback = null;}#endregion//接收到产品信息void OnProductInfoReceived(IAPProductInfoData info){Debug.Log("[IAPMessage]Unity接收到商品信息:" + info.ToString());SDKGuanLiQi.SetInitShopState(true);}//接收到产品信息void OnProductInfoFail(string error){Debug.Log("[IAPMessage]Unity商品信息请求失败:" + error);SDKGuanLiQi.SetInitShopState(false);}//购买完成void OnProductBuyComplete(string productId){Debug.Log("[IAPMessage]购买完成" + productId);ProductBuyCompleteCallback?.Invoke();ClearCallback();}//购买失败void OnBuyProductFail(string productId, string error){Debug.Log(string.Format("[IAPMessage]购买失败:{0} 错误信息{1}", productId, error));ProductBuyFailedCallback?.Invoke();ClearCallback();}//购买取消void OnBuyProductCancled(string productId){Debug.Log("[IAPMessage]购买取消" + productId);ProductBuyCancledCallback?.Invoke();ClearCallback();}//恢复完成void OnRestoreCompleted(string productId){}}

Java代码:

package com.XXX.unitytogoolgleplaylib;// 与C#交互的接口
public interface IAPMessage
{//获取到产品列表回调public void RecieveProductInfos(String jsonData);//产品列表请求失败public void ProductRequestFail(String message);//购买成功回调public void ProductBuyComplete(String productId);//购买失败回调public void ProductBuyFailed(String jsonData);//获取商品回执回调public void ProvideContent(String msg);//购买取消回调public void ProductBuyCancled(String productId);/// <summary>/// 恢复购买成功/// </summary>/// <param name="productId"></param>public void RestoreComplete(String productId);
}

然后调用时赋值的方式参考图:

第一张图为Android Studio中的项目截图,第二张则是C#代码截图,演示一下的,没什么难度一试便会了,很简单

但需要注意的是接入的com.android.billingclient版本与JDK版本兼容性的问题,推荐接入6.0.1,因为本人接入的就是这个版本的,下面再附加上一张我的模块的build.gradle配置图

补档:第25行中的jar包实际上就是Unity的jar包,导入后可以通过import com.unity3d.player,直接使用UnityPlayer.UnitySendMessage方法,从而不用通过反射的方式去进行调用,该jar包的路径为:你的Unity安装路径\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes,

上方路径中的mono所在的位置中的il2cpp下相对于的位置也有一个jar包,这个jar包我没试过,有兴趣的可以试试。

注:因为考虑到兼容性的问题,所以对于插件的部分的指定的目标SDK我就设置为了32版本使用JDK进行构建,弄得太低了的话,担心在后期又要进行升级,就很麻烦,总之就是多一事不如少一事,总之具体设置为那个版本就看你的需求了

同时构建完成后jar包可在下图中的路径下边找到,就不用去解压aar包了,毕竟每次都去解压比较麻烦

这里补档说明一下, 因为是对支付模块的单独构建打包,在构建时可能会因为插件中所需要使用的其他插件的版本问题而导致构建失败,出现这些问题的时候,可以在下图中修改一下所使用的Gradle版本和其他模块的版本,修改为你构建时所需要的版本,同样的图中的内容仅作参考:

因为我使用的Android Studio版本是2024.2.1版本的,所以使用其他版本的配置方式可能存在一些细节上的不同

3、导出工程后再Android Studio中进行构建

这里是大头,因为这里边的坑才是最多的,导出的方法不做详细解释,只对使用Android Studio打开导出的项目包后的操作进行说明

1、修改Gradle版本

这里需要修改的为编译时使用的Gradle版本与Android Gradle 插件版本,修改编译时的Gradle版本路径如下图,直接修改配置文件中的版本号就好了,至于需要修改为那个版本,就需要查看Android Gradle插件版本所需要的版本了

修改Android Gradle插件版本,看下边截图了,也是直接修改版本号就行了:

修改Gradle方法(同时也是修改JDK、NDK的操作步骤之一)还有一个就是如下图,按照截图顺序操作修改为所需要的版本后应用一下就好了:

2、为build.gradle配置文件添加命名空间名称 namespace "com.XXX.XXX"

如下图,下图为unityLibary下的build.gradle配置文件添加命名空间,注意命名空间名称只能为namespace "com.unity3d.player",改成其他的都会出问题,然后记得删得NDK的配置路径,因为可能你所使用的插件所需的最低NDK版本比Unity所提供的NDK版本高,反正删了少一堆问题就对了,里边使用的JavaVersion版本也随手改一下,避免使用Android Studio修改Java 版本的时候,没有修改到的情况出现

删掉或者注释掉下图中框起来的部分可以加快打包的时间,之前百度优化包体时看到的其他的解释是,去掉再次进行il2cpp的编译过程还是什么的是,反正删掉了不影响编译结果,出现其他问题的话,再次加回来再次编译就行了

然后在其他的build.gradle文件中找到android {......}的内容块,并在android{.....}块中的第一行加入命名空间 namespace "这里修改为你的应用的包名",例如下图,包名可在下面第二张图中找到

3、修改JDK、NDK、Build Tools版本等

打开Project Structur窗口,操作步骤参考上方修改Gradle版本的第二个方法,然后根据下图中框选的部分,修改所需要的SDK、JDK、NDK、Build Tools等的版本后应用保存一下,如果没有所需要的版本的话,可以在File-》Settings打开Settings窗口后,看下边第二张图

没错就是这张图,注意如果要通过修改配置文件的方式配置修改Gradle版本版本的话,记得下图中的Distribution的配置就不要进行修改

然后SDK、NDK、Build Tools的安装看这张图,记得勾选右下角的show package details选项看到更多的内容

4、修改所有能找到的AndroidManifest.xml文件,注意是所有(主要是为了减小打包后的包体大小,不介意包体大小的可以不改)

在application后边加上android:extractNativeLibs="true"参考下图

如果已经存在android:extractNativeLibs配置并且为false,就修改为true,添加这段的具体原因则是为了启用压缩功能,详情自行百度,毕竟本人也不是做安卓开发的这段也只是搜索优化时偶然看到的

5、修改settings.gradle文件,如下图,非必要步骤

其实就是使用Unity原本的配置就好了,添加上这一步的主要原因是为了避免因为将maven仓库的源修改为使用国内镜像时,导致一些jar包下载搜索不到的问题,毕竟接入的是google的SDK,翻墙都没问题了,使用原本的配置也就不会出现对下载速度造成影响的问题了

结语

好了,恭喜你完成以上步骤后就可以同步一下然后进行apk的构建了,其中可能因为省略了一些步骤看着会比较迷茫,后期我不定时改改吧,因为连续加班也是弄得脑袋不舒服,详细步骤需要关注的点也可能少了一些,不过还是欢迎留言,看到了也都会第一时间进行回复的

第二十一篇文章的图片

最后2025年1月1日,元旦节快乐

祝大家都能拥有幸福开心满意的工作,并且每天都能不加班可以多陪陪家人

相关文章:

Unity2022接入Google广告与支付SDK、导出工程到Android Studio使用JDK17进行打包完整流程与过程中的相关错误及处理经验总结

注&#xff1a;因为本人也是第一次接入广告与支付SDK相关的操作&#xff0c;网上也查了很多教程&#xff0c;很多也都是只言片语或者缺少一些关键步骤的说明&#xff0c;导致本人也是花了很多时间与精力踩了很多的坑才搞定&#xff0c;发出来也是希望能帮助到其他人在遇到相似问…...

反向传播算法的偏置更新步骤

偏置的更新步骤 假设我们有一个三层神经网络&#xff08;输入层、隐藏层和输出层&#xff09;&#xff0c;并且每层的激活函数为 sigmoid 函数。我们需要更新隐藏层和输出层的偏置。以下是详细的步骤&#xff1a; 1. 计算误差项&#xff08;Error Term&#xff09; 输出层的…...

条款47:请使用 traits classes 表现类型信息(Use traits classes for information about types)

条款47&#xff1a;请使用 traits classes 表现类型信息 1.1 提出问题 想一想&#xff0c;下面的功能如何实现&#xff1f;&#xff08;可以查看std::advance源码&#xff09; template<typename IterT, typename DistT> void advance(IterT& iter, DistT d); /…...

yolov5和yolov8的区别

1. yolov5有建议框&#xff0c;yolov8没有建议框 2. yolov5标签中有自信度&#xff0c;而yolov8没有自信度。因为自信度是建议框和真实框的交集 3. yolov5有三个损失函数&#xff0c;回归问题&#xff1a;预测框和建议框的损失(中心点宽高偏移量的损失)&#xff1a;CIOUFocal…...

Redis 实现分布式锁

文章目录 引言一、Redis的两种原子操作1.1 Redis 的原子性1.2 单命令1.3 Lua 脚本1.4 对比单命令与 Lua 脚本 二、Redis 实现分布式锁2.1 分布式锁的概念与需求2.1.1 什么是分布式锁&#xff1f;2.1.2 分布式锁的常见应用场景 2.2 基于 Redis 的分布式锁实现2.2.1 锁的获取与释…...

django StreamingHttpResponse fetchEventSource实现前后端流试返回数据并接收数据的完整详细过程

django后端环境介绍&#xff1a; Python 3.10.14 pip install django-cors-headers4.4.0 Django5.0.6 django-cors-headers4.4.0 djangorestframework3.15.2 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple 总环境如下&#xff1a; Package Version -…...

SpringSpringBoot常用注解总结

目录 1. SpringBootApplication 2. Spring Bean 相关 2.1. Autowired 2.2. Component,Repository,Service, Controller 2.3. RestController 2.4. Scope 2.5. Configuration 3. 处理常见的 HTTP 请求类型 3.1. GET 请求 3.2. POST 请求 3.3. PUT 请求 3.4. DELETE 请…...

24.小R的随机播放顺序<字节青训营-中等题>

1.题目 问题描述 小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌&#xff0c;播放后将其从歌单中移除。如果歌单中还有歌曲&#xff0c;则会将当前第一首歌移到最后一首。这个过程会一直重复&#xff0c;直到歌单中没有任何歌曲。 例如&#xff0c;给定歌单 [5, …...

【QT】增删改查 XML 文件的类

使用单例类模板实现的对XML文件的节点、属性、文本进行增删改查,可以直接用! 直接POST代码,比较简单好用。 针对以下格式的xml文件比较适用 每个节点的名称都不一样,节点包含了各种属性。 <?xml version="1.0" encoding="UTF-8"?> <config…...

Linux-掉电保护方案

参考链接 https://blog.csdn.net/pwl999/article/details/109411919硬件设计 设备树 驱动程序 #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/gpio.h>int irq;//中断服务函数 irqreturn_t tes…...

php获取字符串中的汉字

在PHP中&#xff0c;可以使用正则表达式来提取字符串中的汉字。汉字通常位于Unicode范围\u4e00-\u9fa5之内&#xff0c;因此可以使用preg_match_all函数配合适当的正则表达式来实现。 以下是一个PHP代码示例&#xff0c;它会从给定的字符串中提取出所有的汉字&#xff1a; fu…...

java: JDK isn‘t specified for module ‘product-service‘问题解决

目录 问题 解决方法 1.打开File->Project Structure... 2.将Project SDK修改为17 Oracle OpenJDK 17.0.12&#xff0c;并Apply&#xff0c;OK 问题 添加module后报错&#xff1a;java: JDK isnt specified for module product-service 查看pom.xml文件也添加了对应的JDK…...

使用工厂+策略模式实现去除繁琐的if else

使用工厂策略模式实现去除繁琐的if else 在中间有一个mapstruct的bug&#xff0c;即在修改实体类中的类型时&#xff0c;或者修改属性名字&#xff0c;mapstruct都无法进行转换&#xff0c;会报错&#xff0c;此时需要maven cleanmaven compile即可 前言 在这次的开发中&#…...

Dubbo3入门项目搭建

开发环境&#xff1a;jdk8、dubbo3.2.9、nacos2.3.0、springboot2.7.17、dubbo-admin0.6.0。 Dubbo 是一个高性能的 Java RPC&#xff08;远程调用&#xff09;框架&#xff0c;最初由阿里巴巴开发并开源&#xff0c;主要用于构建 SOA 架构下的分布式应用系统( soa简单理解就是…...

形象地理解UE4中的数据结构 TLinkedListBase

大家都熟知链表&#xff0c;但不一定能快速看懂UE4中的数据结构。 TLinkedListBase表示“链接”中的一个结点&#xff0c;有三个成员&#xff1a; 一、ElementType Element; 表示具体的业务&#xff0c;例如int链条中的一个整数。 二、NextLink 表示 “下一个Node”&#…...

Python自然语言处理利器:SnowNLP模块深度解析、安装指南与实战案例

Python自然语言处理之SnowNLP模块介绍、安装与常见操作案例 一、SnowNLP模块介绍 SnowNLP是一个专为中文文本设计的Python库&#xff0c;它基于自然语言处理技术&#xff0c;提供了多种功能&#xff0c;包括分词、词性标注、情感分析、文本转换&#xff08;简繁转换&#xff…...

Llama系列关键知识总结

系列文章目录 第一章&#xff1a;LoRA微调系列笔记 第二章&#xff1a;Llama系列关键知识总结 第三章&#xff1a;LLaVA模型讲解与总结 文章目录 系列文章目录Llama: Open and Efficient Foundation Language Models关键要点LLaMa模型架构&#xff1a;Llama2分组查询注意力 (G…...

【开源】创建自动签到系统—QD框架

1. 介绍 QD是一个 基于 HAR 编辑器和 Tornado 服务端的 HTTP 定时任务自动执行 Web 框架。 主要通过抓包获取到HAR来制作任务模板&#xff0c;从而实现异步响应和发起HTTP请求 2. 需要环境 2.1 硬件需求 CPU&#xff1a;至少1核 内存&#xff1a;推荐 ≥ 1G 硬盘&#xff1a;推…...

​​​​​​​CDP集群安全指南系列文章导读

[一]大数据安全综述 1-认证 身份验证是任何计算环境的基本安全要求。简单来说&#xff0c;用户和服务必须在使用系统功能并获得授权之前&#xff0c;向系统证明其身份&#xff08;进行身份验证&#xff09;。身份验证与授权紧密配合&#xff0c;共同保护系统资源。大多数 CDH …...

MT8788安卓核心板_MTK8788核心板参数_联发科模块定制开发

MT8788安卓核心板是一款尺寸为52.5mm x 38.5mm x 2.95mm的高集成度电路板&#xff0c;专为各种智能设备应用而设计。该板卡整合了处理器、图形处理单元(GPU)、LPDDR3内存、eMMC存储及电源管理模块&#xff0c;具备出色的性能与低功耗特性。 这款核心板搭载了联发科的MT8788处理…...

【微软,模型规模】模型参数规模泄露:理解大型语言模型的参数量级

模型参数规模泄露&#xff1a;理解大型语言模型的参数量级 关键词&#xff1a; #大型语言模型 Large Language Model #参数规模 Parameter Scale #GPT-4o #GPT-4o-mini #Claude 3.5 Sonnet 具体实例与推演 近日&#xff0c;微软在一篇医学相关论文中意外泄露了OpenAI及Claud…...

深入理解并发原子性、可见性、有序性与JMM内存模型

1. 并发三大特性 并发编程Bug的源头&#xff1a;原子性、可见性和有序性问题 1.1 原子性 一个或多个操作&#xff0c;要么全部执行且在执行过程中不被任何因素打断&#xff0c;要么全部不执行。在 Java 中&#xff0c;对基本数据类型的变量的读取和赋值操作是原子性操作&…...

电商项目-数据同步解决方案(四)商品下架同步更新ES索引库数据

商品下架索引库删除数据 一、 需求分析和业务逻辑 商品下架后将商品从索引库中移除。 主要应用技术有&#xff1a; 消息队列-RabbitMQ &#xff0c;分布式搜索引擎-ElasticSearch&#xff0c;Eureka&#xff0c;Canal&#xff0c;Feign远程调用 &#xff08;1&#xff09;在…...

vue学习第一阶段

vue 什么是Vue? 概念:Vue是一个构建用户页面的渐进式框架 Vue的两种使用方式 Vue的核心开发 场景: 局部 {\color{red}局部} 局部模块改造Vue核心包& Vue插件 工程化开发场景: 整站 {\color{red}整站} 整站开发Vue2官网 https://v2.cn.vuejs.org/ 资料存放地址 D:\Baidu…...

React虚拟DOM:理解和应用

写在前面 在现代前端开发中&#xff0c;React 是一个非常流行的 JavaScript 库&#xff0c;用于构建用户界面。它引入了一个名为“虚拟 DOM”&#xff08;Virtual DOM&#xff09;的概念&#xff0c;这个概念对于 React 的高效性能和易用性至关重要。本文将深入探讨 React Vir…...

用python编写一个放烟花的小程序

import pygame import random # 代码解释及使用说明&#xff1a; # 首先&#xff0c;导入 pygame 和 random 库。pygame 用于创建游戏窗口和图形绘制&#xff0c;random 用于生成随机数。 # 初始化 pygame&#xff0c;并设置屏幕尺寸为 800x600 像素&#xff0c;设置窗口标题为…...

Git 仓库与文件管理笔记

Git 的三种仓库概念 本地仓库 (Local Repository) 位于本地 .git 文件夹中通过 git init 或 git clone 创建存储完整的项目历史和分支信息 远程仓库 (Remote Repository) 位于 GitHub、GitLab 等平台服务器使用 git remote -v 查看所有远程仓库默认远程仓库名通常为 origin 工…...

2024 年 docker 提示index.docker.io

发现 docker 提示以下错误&#xff1a; Error response from daemon: Get "https://index.docker.io/v1/search?qnginx&n25": dialing index.docker.io:443 container via direct connection because has no HTTPS proxy: connecting to index.docker.io:443:…...

TCP粘/拆包----自定义消息协议

今天是2024年12月31日&#xff0c;今年的最后一天&#xff0c;希望所有的努力在新的一年会有回报。❀ 无路可退&#xff0c;放弃很难&#xff0c;坚持很酷 TCP传输 是一种面向二进制的&#xff0c;流的传输。在传输过程中最大的问题是消息之间的边界不明确。而在服务端主要的…...

Modbus知识详解

Modbus知识详解 ## 1.什么是Modbus?**顾名思义**&#xff0c;它是一个Bus&#xff08;总线&#xff09;&#xff0c;即总线协议。比如串口协议、IIC协议、SPI都是通信协议。你接触到这种协议&#xff0c;相信你所处的行业是工业电子方面或者你的产品用于工业。好了&#xff0c…...