The author | | https://juejin.cn/post/6844903715342663687 Hsusue sources
preface
Each update of the project requires more than a dozen packages. Guangfa said that the automatic package script inherited from it suddenly did not work, and now every package upload has to be done until midnight, so it will be better to change the name to Dilute hair. Watching him grow bald, I couldn’t hide my fatherly love and had to share it with him (forced, of course).
In this project, there are more than ten packages with different ICONS and App names. Manual packaging is not only slow, but also the error probability of repetitive boring work increases exponentially. So if your project is going to have to pack several packages, it’s worth taking the time to learn how to auto-pack. If you pack only one bag, the automatic packing time is faster, but the learning cost is still there, depending on your opinion.
The key is to use re-signature to modify custom images, App names, etc., without repeated compilation, can greatly reduce the packaging time.
Certificate of knowledge
Online certificate configuration is no lack of good articles, a lot of search, but most did not introduce what are used.
• CSR:Certificate Singing Request file
Contains information about the computer. So you don’t need to fill in any information about publishing.
• Certificates: Publisher Certificates. Apple Develop ID a certificate of authorization for a computer.
After the computer has this certificate, it has the right to test, package and publish all apps under the Apple Developer ID. Notice that there is no App specified, in other words, nothing to do with App.
Contains information about the computer and information about Apple Developer.
• Links between CSR and Certificates
As mentioned above, Certificates contain information about computers, which comes from the CSR. So when you create Certificates, you need to submit a CSR.
• Certificates Exports P12 files
It says you have the license to do those things. If another computer wants to publish, it also needs a certificate. Creating a new certificate also works, but it is usually enough to create a distribution certificate for a developer account, and Apple has a limit on the number of certificates. Exporting the P12 file in this case is equivalent to copying a certificate (within the limit set by Apple). Once installed on another computer, the other computer has the right.
So far, the author is confused that the CSR contains the information of the computer, and then can be copied to other computers for use, what is the use. I hope the big man can explain it.
What is mentioned above is not directly related to App. The following links are established with App.
• App IDs
Register your App under the Apple Developer. Name and Bundle ID are required here. The Bundle ID here will match the certificate in Xcode.
I heard from Li Dasen before that if you create a new project and change it to the Bundle ID in the company’s project, the App can also be tested on the real machine because the Bundle ID is matched.
• Provisioning Profiles: PP files. Mobileprovision suffix.
Includes appID, developer certificate.
When created, there is a difference between development and release. The former to choose equipment, the latter not.
Once the download is created, Xcode will automatically match it, or you can manually match it.
• When working on a project that you are not responsible for, you will often be sent.p12 and.mobileprovision files. The former grants your computer Apple Developer ID privileges, the latter grants App privileges.
Automatic packaging
This article uses XcodeBuild.
Automatic packing is a pain in the head. Always had a fear of the command line, just one step at a time. Learn about command-line commands first, and then create a new project to familiarize yourself with them.
Xcodebuild profile
Xcodebuild is a command provided by Xcode to package a project or project.
To view the document, type man xcodeBuild.
Here’s the big guy’s summary.
Type xcodebuild -h to see help.
Usage: xcodebuild [-project <projectname>] [[-target <targetname>]...|-alltargets] [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings] [<buildsetting>=<value>]... [<buildaction>]... xcodebuild [-project <projectname>] -scheme <schemeName> [-destination <destinationspecifier>]... [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings] [<buildsetting>=<value>]... [<buildaction>]... xcodebuild -workspace <workspacename> -scheme <schemeName> [-destination <destinationspecifier>]... [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [-showBuildSettings] [<buildsetting>=<value>]... [<buildaction>]... xcodebuild -version [-sdk [<sdkfullpath>|<sdkname>] [<infoitem>] ] xcodebuild -list [[-project <projectname>]|[-workspace <workspacename>]] [-json] xcodebuild -showsdks xcodebuild -exportArchive -archivePath <xcarchivepath> -exportPath <destinationpath> -exportOptionsPlist <plistpath> xcodebuild -exportLocalizations -localizationPath <path> -project <projectname> [-exportLanguage <targetlanguage>...] xcodebuild -importLocalizations -localizationPath <path> -project <projectname>
Copy the code
Xcodebuild try
You can create a new project, Test. Then in Xcode, copy the Bundle Identifier for the company project (which has the certificate), and you’ll see that the certificate matches. (If you don’t have a certificate, look back at the certificate knowledge and read on.) With this project, you can feel the commands.
Packing Method 1
I don’t think it’s as good as method 2, and Apple scrapped one of the tools.
So we compile.app, and then we convert it to.IPA.
Once the terminal is in the project folder, try the first build command.
xcodebuild -project Test.xcodeproj -target Test -configuration Release
Copy the code
Unsurprisingly, the above text will be printed, including the signature identity and configuration file. Test/build/ release-iphoneOS/test.app.dsym.
Xcrun is deprecated in Xcode8.3. If you need to use xcrun: error: Unable to find Utility “PackageApplication”, not a developer tool or in PATH [1])
After processing, execute the following command to convert to IPA.
xcrun -sdk iphoneos PackageApplication build/Release-iphoneos/Test.app -o ~/Desktop/Test.ipa
Copy the code
Packing Method 2
Use Archive first, then exprotArchive, similar to the interface step of manual packaging.
(Run xcodebuild-list first, remember Scheme)
Xcodebuild archive-scheme Test -archivePath ~/Desktop/ test. xcarchive after the terminal goes to the project folder, run xcodebuild archive-scheme Test -archivePath ~/Desktop/ test. xcarchive.
My guess is that the above and Xcode packaging correspond to this interface.
As you can see from the above figure, exportoptions.plist should be configured separately because of different publishing channels. Xcodebuild-exportarchive-archivepath-exportpath-exportoptionsplist (xcodebuild-exportarchive-Archivepath-exportOptionSplist) There are two path configurations.
• Copy past through manual packaging.
• Create a new plist file and add key pairs. (Assuming you know how to add).
The exportoptions. plist file contains the following fields and their configurations are as follows: Method: indicates the packaging type. The value can be app-Store, ad-hoc, Enterprise, or development. ProvisioningProfiles: dictionary, required by Xcode9, key-value pair is {bundleID: description file name}, preferably use the UUID corresponding to the description file name. SigningCertificate: indicates the certificate type. The development environment is iPhone Developer, and the production environment is iPhone Distribution. SigningStyle: "Manual" or "automatic". Enter "manual". StripSwiftSymbols: Enter YES. TeamID: indicates the ID of the open team, which can be viewed by clicking the certificate details in the keystring. UploadBitcode: YES UploadSymbols: is YES.
Copy the code
I still recommend manual packaging, copy the past and make changes (in the future, other projects can be used only with minor changes, do not need to manually package and copy again). Through the graphical interface, you can better understand the meaning of these fields and the corresponding operations.
I took a screenshot from the Enterprise. Other because the author does not have a certificate, relied on everybody to try.
And then it goes on in the terminal
xcodebuild -exportArchive -archivePath ~/Desktop/Test.xcarchive -exportPath ~/Desktop/Test.api -exportOptionsPlist ./ExportOptions.plist
Copy the code
Xcodebuild will be packaged, other methods are not commonly used, there are few online learning resources, I do not want to explore. Let’s go to the packaging script.
Automatic packaging script
The author referred to the summary of iOS batch packaging in the article of my brother @tsui_Yuenhong [2], and set up a script by myself, using the new method suggested by Apple and supplementing some shortcomings of my brother’s script.
First, the author’s sad story. I’ve uploaded a package to the App Store before, and the whole process is hilarious. But this project, a total of more than 20 packages, update a version often hit more than 10 packages. Knock it down and it’s gone. Because the code is basically the same, re-signing can greatly reduce the packaging time.
The author’s project packaging has the following requirements
To put it simply, it is to customize corresponding ICONS and functions for different users.
• Bundle information can be replaced
• Replace audio image resources
• Can execute different code
• Generate the corresponding PLIST file
• Upload to dandelion distribution platform
Train of thought
• Compile.app files first.
, use the command defaults write to modify the project file, to modify bundleName/bundleDisplayName key-value pairs, implement a custom App name, display name, and
• Generate the corresponding PLIST file.
• Use the cp command to replace the image resource.
• Re-sign.
• Export ipA.
I have a problem
Toggle icon pits
Check out the official recommended icon sizes. Of course, other sizes will also be accepted by the App icon and automatically adapt.
Plan 1 (Unsolved)
The author tries to use this scheme. The principle is to use the same picture to cover the picture in the package, re-signature, to achieve the purpose of modifying ICONS. However, after the package image is overwritten, the Icon does not change when installed (Icon files in info.plist (iOS 5) may need to be modified. I don’t know what else the underlying configuration is), so I won’t try.
Scheme 2
• This method places ICONS in projects, not Xcassets.
• AppIcon’s name must correspond! It is difficult to predict what will happen because the cp command line should be replaced completely, as shown in the following figure. (In my project, the only graphs are 60@2x and 60@3x.)
• When packaged, the AppIcon icon is in the.app file directory, not in BundleResources.
You can execute different code
Heavy signature
I suggest you read this article first. Re-signed (packaged) iOS applications [3]
Come out entitlements. Plist, re-signature is used.
digression
The author still encountered a pit when re-signing. The progress bar of the packaged software download turned round, but it could not be finished. Checked a period of time, just know the reason is re signature is not successful. So the script must be terminated if it fails to re-sign.
With an iTunes downgrade article, PP assistant seems not updated or what, can only use the old version of iTunes to debug it, really tired ah. Install iTunes drop back 12.6.3 downloadable application package version tutorial [Windows | Mac] [4]
The script
My brother’s script 1 (256s running time) is faster than my script 2 (306s running time).
But script 1 uses apple’s deprecated methods, so try Script 2 when things go wrong.
The difference between the two scripts is that the.app script comes out first, and the.ipa script comes out later. The Archive package contains.app and.ipa.
• a script
Ready Entitlements. Plist (this article has access to tutorial, Cmd+ F search “re signature to use “). And make sure this function runs xcrun (deprecated in Xcode8.3).
The IPA is exported using xcRun after compilation and finally re-signed.
The script is posted in the summary [5] of Shi’s article about iOS bulk packaging.
The author encountered the icon replacement failure problem when using this script. It has nothing to do with the script, but related to the project configuration. See the solution above.
But I think there are some problems with this script. For example, the script was not terminated after the operation such as re-signing failed, which caused the author to be confused when he uploaded the script to Dandelion and failed to download it. This is a serious problem. However, with proper judgment, an exit should solve the problem.
Second, the script
Prepared Entitlements. Plist (this article has access to tutorial, Cmd+ F search “re signature to use “) and ExportOptions. Plistist ‘ ‘(this article has access to tutorial, Cmd+ F search” there are two ways to configure “).
Use Archive first, then exprotArchive (similar to the manual packaging process), and finally re-sign.
The script is posted below. Note that the author uses Project instead of Project in many places.
ProjectDir =" your project path "# package build path suggested desktop ipaPath="ipa build path "# iconPath need to change iconPath=" iconPath "# The following files are used to re-sign to generate ipA, Need to modify Entitlements = $ipaPath/Entitlements. PlistExportOptions = $ipaPath/ExportOptions plist# bundleVersion = "2.0.0 version # choose package number If multiple options are selected, separate them with Spaces. For example, ("1" "2" "3")appPackNum=("1" "2")# Dandelion distribution Parameter No distribution Ignorable Default no distribution The following two KEY corresponding KEYISUPLOAD = 0 is the default test url userkey = "XXX" APIKEY = "XXX" # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- an optional If you need to replace the app icon -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - # # configuration App information array format: "AppName (appInfo and engineering. The Plist)" "icon" "in the Url AppName" (AppName into Chinese because it is over, Access access: access access: access access: access access: access access: access: access: access: access: access: access: access: access: access: access: access: access: access: access: access: access: access: access -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - # # AppPackNum =${#appPackNum[*]}appInfos=("app1" "app1Icon" "app1UrlName" "app2" "app2Icon" "app2UrlName" "app3" AppInfosLength =${#appInfos[*]}# Scheme NameschemeName="xx"# beginTime= 'date +%s' # generated ${ipaPath}/Payloadrm -rf ${ipaPath}/Payload/*buildDir="${ipaPath}/Payload Xcarchivexcodebuild archive -workspace ${projectDir}/ youxiaoyun. xcworkspace -scheme ${schemeName} -archivepath ${buildDir}/Project.xcarchive#if [[ $? = 0 ]]; then # $? Represents the return value of the previous command. If the previous command executed successfully, 0 is returned, Echo "\033[31m compiled successfully \n \033[0m"else echo "\033[31m compiled failed \n \033[0m" exit 0fi# create package directory mkdir ${ipaPath}/ allpackage # ---- ----#for ((I =0; I <appInfosLength; I +=3)); allIPAPackPath="${ipaPath}/allPack" Do# 2. - custom packaging - for ((j = 0; j < $appPackNumLength; j++)); do i=`expr ${appPackNum[$j]} - 1` i=`expr $i \* 3`# App Bundle Name (CFBundleName)appName=${appInfos[${i}]}# App DisPlay NameappDisplayName=${appInfos[${i}]}# App Icon NameappIconName=${appInfos[$i+1]}# App Download NameappDownloadName=${appInfos[$I +2]}# create different app ipA directory mkdir $allIPAPackPath/$appNamerm -rf $allIPAPackPath/$appName/*echo "\033[31m appName:$appName appIconName:$appIconName appDownloadName:$appDownloadName\n \033[0m"# cp -rf $iconPath/$appName/* ${buildDir}/Project.xcarchive/Products/Applications/Project.appif [[ $? = 0 ]]; Then echo "\033[31m $appName change icon succeeded \033[0m"else echo "\033[31m $appName change icon failed \033[0m" exit 0fi# change Plistdefaults write $ipaPath/Payload/xx.app/info.plist "CFBundleName" $appNamedefaults write $ipaPath/Payload/xx.app/info.plist "CFBundleDisplayName" $appDisplayNameif [[ $? = 0 ]]; Then echo "\033[31m $appName successful \033[0m"else echo "\033[31m $appName failed \033[0m" exit 0fi# re-sign xattr-cr ${buildDir}/Project.xcarchive/Products/Applications/Project.appcodesign -f -s "xx co., LTD" --entitlements $Entitlements ${buildDir}/Project.xcarchive/Products/Applications/Project.appif [[ $? = 0 ]]; Then echo "\033[31m $appName failed \n \033[0m"else echo "\033[31m $appName failed \n \033[0m" exit 0fi# Generate ipaxcodeBuild -exportArchive -archivePath $ipaPath/Payload/Project.xcarchive -exportPath ${ipaPath}/$appDownloadName.ipa -exportOptionsPlist $ExportOptionsif [[ $? = 0 ]]; Then echo "\033[31m \n $appName failed to generate IPA \n\n\n\n\033[0m"else echo "\033[31m \n $appName failed to generate IPA \n\n\n\n\033[0m" exit 0fi# create Plistplist_path=$allIPAPackPath/$appName/$appdownloadName. plistcat << EOF > $plist_path <? XML version = "1.0" encoding = "utf-8"? > <! DOCTYPE plist PUBLIC "- / / / / DTD plist Apple / 1.0 / EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" > < plist Version ="1.0"><dict> <key>items</key> <array> <dict> <key> Assets </key> <array> <dict> <key>kind</key> <string>software-package</string> <key>url</key> <string>https://xxxxxxxxxxxx/$appDownloadName.ipa</string> </dict> <dict> <key>kind</key> <string>display-image</string> <key>url</key> <string>https://xxxxxxxxxxxx/${appIconName}.png</string> </dict> <dict> <key>kind</key> <string>full-size-image</string> <key>url</key> <string>https://xxxxxxxxxxxx/${appIconName}.png</string> </dict> </array> <key>metadata</key> <dict> <key>bundle-identifier</key> <string> your bundid</string> <key> bundleVersion</string> <key>kind</key> <string>software</string> <key>title</key> <string>$appDownloadName</string> </dict> </dict> </array></dict></plist>EOF# move mv ${ipaPath}/$appdownloadname. ipa ${allIPAPackPath}/$appNamedone# $ISUPLOAD = 1 ]]; Then the echo "started uploading dandelion... \ n \ n" curl -f "file = @ $$appName AllIPAPackPath / / $appDownloadName. Ipa/Project. Ipa" \ - F "UKey = $USERKEY \" -f "_api_key = $APIKEY" judging \ http://www.pgyer.com/apiv1/app/upload # upload results if [[$? = 0]]; Then the echo "\ n ~ ~ ~ ~ ~ ~ ~ \ ^ o ^ / ~ ~ ~ ~ upload dandelion success ~ ~ ~ ~ \ ^ o ^ / ~ ~ ~ \ n" else echo "\ n ~ ~ ~ ~ ~ \ (╯ - ╰) / ~ ~ ~ ~ ~ ~ ~ upload dandelion failure ~ ~ ~ ~ ~ \ (╯ - ╰) / ~ ~ ~ ~ ~ \ n" Rm -rf $ipaPath/Payload# endTime endTime= 'date +%s' echo -e "endTime $[endTime - beginTime] seconds"
Copy the code
reference
[1]https://blog.csdn.net/itiapp_home/article/details/70241011 [2]https://www.jianshu.com/p/4cf4e45a4411 [3]https://blog.csdn.net/skylin19840101/article/details/60583893 [4]https://mp.weixin.qq.com/s/WIvJyRNwxofMq1XYcotKpQ
Talk about AppDelegate decoupling
How do iOS native apps deselectRow
Make a simple iOS dynamic executor
IOS traffic monitoring analysis