kotlin制作图形验证码
Kotlin Multiplatform is a great technology in the maturing period, which means that it's not always possible to find what you need for your project and you must craft it yourself. Are you ready for a challenge?
Kotlin Multiplatform在成熟期是一项伟大的技术,这意味着并非总能找到您需要的项目,而您必须自己制作 。 您准备好挑战了吗?
In this article, I'll share a step-by-step guide of creating and publishing of KMP library for JVM, Android and iOS targets. Target, if simply put, is just a type of device where you want your library to work.
在本文中,我将分享为JVM , Android和iOS目标创建和发布KMP库的分步指南 。 简而言之,Target只是您希望库工作的一种设备。
先决条件 (Prerequisites)
Codeforces WatchR is an open-source mobile client for Codeforces platform, where thousands of programmers compete in weekly algorithmic challenges. There are both, iOS and Android apps, which are available in stores.
Codeforces WatchR是Codeforces平台的开源移动客户端,成千上万的程序员在每周的算法挑战中竞争。 商店中有iOS和Android应用程序。
![Image for post](https://miro.medium.com/max/9999/0*CnzZHOsAeDk_cCJV.png)
Recently we've migrated both apps to Kotlin Multiplatform. In the process, we've just copy/pasted ReKotlin source code (doesn't support KMP at the moment) to KMP common module, which was the short-term solution.
最近,我们已经将这两个应用程序都迁移到了Kotlin Multiplatform 。 在此过程中,我们只是将 ReKotlin源代码(目前不支持KMP) 复制/粘贴到KMP通用模块中,这是短期解决方案 。
But then we needed ReKotlin in another KMP project, so we decided to publish it as KMP library to Bintray. Now it can be included as a dependency in build.gradle
file. Other developers can also benefit from our work.
但是后来我们在另一个KMP项目中需要ReKotlin ,因此我们决定将其作为KMP库发布到Bintray。 现在,它可以作为依赖项包含在build.gradle
文件中。 其他开发商 也 可以 受益于我们的工作。
源代码 (Source code)
All source code can be found in the official ReKamp (this is how we called the library) repo on GitHub. As you can see, all classes are located under src/commonMain
folder, which means ReKotlin was 99% ready for KMP.
所有源代码都可以在GitHub上的官方ReKamp (我们称之为库) 仓库中 找到 。 如您所见,所有类都位于src/commonMain
文件夹下,这意味着ReKotlin 已经为KMP 准备了99% 。
There is no platform dependent code and our changes are limited to a few tiny tweaks related to how Kotlin/Native compiler transforms Kotlin into Obj-C:
没有依赖平台的代码,我们的更改仅限于与Kotlin / Native编译器如何将Kotlin转换为Obj-C有关的一些细微调整:
For some reason
===
didn't work as expected within Kotlin/Native, even though printed addressed were the same. Changed them to==
.由于某些原因
===
在Kotlin / Native中无法按预期工作,即使打印的地址相同。 将它们更改为==
。All classes should extend other classes or
Any
. Otherwise you will have messed up generics, which are limited even without this problem.所有类都应扩展其他类或
Any
。 否则,您将搞砸泛型,即使没有此问题,泛型也受到限制。All methods, which begins with
new
orinit
are prefixed withdo
. ChangednewState
toonNewState
to stay consistent between platforms.所有以
new
或init
开头的方法都以do
为前缀。 将newState
更改为onNewState
以在平台之间保持一致。
汇编 (Compilation)
Configuration of your build happens in kotlin
block where you specify your source sets and targets. jvm
corresponds to any JVM-powered target and gives you an access to different Java-related APIs. android
is subset of jvm
, but allows you access Android-specific APIs.
构建的配置在kotlin
块中进行,您可以在其中指定源集和目标 。 jvm
对应于任何基于JVM的目标,并允许您访问不同的Java相关API。 android
是jvm
子集,但允许您访问特定于Android的API。
It’s much more complicated for ios
target. In many libraries listed in https://github.com/AAkira/Kotlin-Multiplatform-Libraries I've seen a shortcut for ios()
preset of targets, which works good until you try to archive the iOS app, which uses the library, in XCode.
对于ios
目标而言,它要复杂得多。 在https://github.com/AAkira/Kotlin-Multiplatform-Libraries中列出的许多库中,我已经看到了ios()
目标预设的快捷方式,在您尝试存档使用该库的iOS应用程序之前 ,该方法非常有用,在XCode中。
建筑学 (Architectures)
If you inspect the default Valid Architectures
field in your XCode project, you will see that it contains both arm32
(armv7, armv7s) and arm64
(arm64, arm64e) architectures.
如果检查XCode项目中的默认Valid Architectures
字段,您将看到它包含arm32
(armv7,armv7s)和arm64
(arm64,arm64e)体系结构。
But for some reason shortcut for ios()
in KMP contains only x64
(simulator) and arm64
(devices) architectures. And when you try to archive the project, you will see following errors:
但是出于某种原因, KMP中的ios()
快捷方式仅包含x64
(模拟器)和arm64
(设备)体系结构。 当您尝试归档项目时,您将看到以下错误 :
![Image for post](https://miro.medium.com/max/9999/1*VNnTcmW6k79GRFiy5HtDOA.png)
One of the solutions is getting rid of arm32
architectures in both your common KMP module and XCode project, but I'm not sure about implications of this choice. Comment if it's safe, please.
解决方案之一是在常见的KMP模块和XCode项目中都摆脱 arm32
体系结构,但是我不确定这种选择的含义。 请评论是否安全。
We've chosen another, more robust solution and decided to support iosArm32
in ReKamp. It can be done by explicitly including iosArm32
, iosArm64
and iosX64
targets in the build.gradle
. Just make sure that their corresponding source sets depends on nativeMain
.
我们选择了另一个更强大的解决方案,并决定在iosArm32
中支持iosArm32。 可以通过在iosArm32
显式包含iosArm32
, iosArm64
和iosX64
目标来完成此build.gradle
。 只需确保其相应的源集取决于nativeMain
。
元数据 (Metadata)
When you do ./gradlew build
, outputs for each target are created. These are jar
files for JVM targets and klib
for Native ones. So far, so good.
当您执行./gradlew build
,将创建每个目标的输出。 这些是JVM目标的jar
文件,本机目标的klib
是。 到目前为止,一切都很好。
The problem is that there is no target for common
source set, so no outputs are generated. But Android Studio needs jar
file, which is named your-library.jar
to support highlighting in your common KMP module.
问题在于common
源集没有目标,因此不会生成任何输出。 但是Android Studio需要jar
文件,该文件名为your-library.jar
以支持在常见的KMP模块中 突出显示 。
The solution is simple, you need to rename your-library-metadata.jar
(and other metadata outputs) to your-library.jar
. Here is the code, which makes exactly that + makes sure that other outputs are named properly.
解决方案很简单,您需要将your-library-metadata.jar
(和其他元数据输出)重命名为your-library.jar
。 这是代码,这使得+可以确保正确命名其他输出。
出版 (Publishing)
We've used com.jfrog.bintray
plugin, which provides convenient methods for uploading your outputs and metadata to Bintray repository. To make sure that all outputs are correctly uploaded, we've added them to publications:
我们使用了com.jfrog.bintray
插件,该插件提供了方便的方法来将您的输出和元数据上传到Bintray存储库。 为了确保所有输出均正确上传,我们已将它们添加到出版物中 :
publish.gradle
provides the most important information to publishing plugin: repository url, group, artifact and version.
publish.gradle
为发布插件提供了最 重要的 信息 :存储库URL,组,工件和版本。
pom.gradle
is just another Gradle script, which is used to provide additional information about library' license, developer, etc in POM format.
pom.gradle
只是另一个Gradle脚本,用于以POM格式提供有关库许可,开发人员等的其他 信息 。
All the values you see in Gradle files are gathered in gradle.properties
:
您在Gradle文件中看到的所有值都收集在gradle.properties
:
Another 2 values are located in local.properties
, which are private: bintrayUser
and bintrayApiKey
, which you can get by registering at https://bintray.com/ for free.
另外两个值位于local.properties
,它们是私有的 : bintrayUser
和bintrayApiKey
,可以通过在https://bintray.com/ 免费注册获得。
At this moment, you should be able to publish your library with ./gradlew bintrayUpload
. You should see about 20 lines of Uploaded to ...
此时,您应该可以使用./gradlew bintrayUpload
发布库。 您应该会看到大约20行Uploaded to ...
![Image for post](https://miro.medium.com/max/9999/1*7ZerRjo8VPKgtlggOQM0MQ.png)
用法 (Usage)
First of all, check that you have all outputs successfully uploaded to Bintray: Repository -> Package -> Files. You should see a few folders (common, mavenProject + one per target).
首先,检查是否所有输出都已成功上传到Bintray:存储库->包->文件。 您应该看到一些文件夹(常见的,mavenProject +每个目标一个)。
![Image for post](https://miro.medium.com/max/9999/1*3fzB4KPAD6G5mXgB905TzQ.png)
Now you can include these dependencies for targets you need like this:
现在,您可以像这样将这些依赖项包含在所需的目标中:
Gradle缓存 (Gradle cache)
Half of the time I've spent fighting with Gradle cache, which was super persistent about keeping old versions of my library after changes without changing the version.
我花了一半时间与Gradle cache战斗 ,这对于在更改后保留我的库的旧版本而不更改版本是超级持久的。
Here are a few advices on how to overcome caching mechanism:
以下是一些有关如何克服缓存机制的建议:
update version of your library after every single change
每次更改后更新库的版本
remove all obsolete versions of library from local Gradle cache (Project view -> External libraries -> your-library.jar (and all targets).
从本地Gradle缓存中删除所有过时的库版本 (项目视图->外部库-> your-library.jar(以及所有目标)。
once done remove all obsolete versions of library from Bintray
完成后,从Bintray中删除 所有 过时的库版本
![Image for post](https://miro.medium.com/max/9999/1*sKVjjnlABHR8Gytutsx8Cw.jpeg)
底线 (Bottom line)
Creating and publishing Kotlin Multiplatform library was super challenging for the first time. It took me almost 2 weeks to get all things right in several rounds and a few broken projects.
创建和发布Kotlin多库超 具有挑战性的第一次。 我花了将近2个星期的时间,才完成了几轮和一些破烂的项目,使所有事情都变得正确。
I hope that this kind of step-by-step guide with working examples will help other developers to get their library published and working much faster.
我希望这种带有工作示例的循序渐进指南将帮助其他开发人员发布其库并使其工作更快。
Good luck!
祝好运!
资料来源 (Sources)
kotlin制作图形验证码