The original address of my blog

As we all know, channel package is a common distribution method in the Domestic Android application market. The channel package will contain different channel information, so that we can make follow-up statistics on the downloads, users and retention rate of the App in various distribution channels, and adjust the application content or promotion plan accordingly. As it is more and more difficult for iOS apps to be launched in China, many enterprise packages have been derived. In order to facilitate data collection, multi-channel schemes are also used.

In addition, during the progress of the project, there may be some demands for temporary new channels, and it will be time-consuming to go back to the project to repackage. Is there any way to speed up the packaging? Some of the options are shared below.

IOS multi-channel packaging solution

At present, there are only two ways of iOS channel package, one is through multiple targets, the other is to modify the plist file.

Multiple target way

Click Target in the project and right-click Duplicate. You can modify the target name, PList name, and Scheme name in the red box.

You can determine the current target by adding a macro definition by going to the Preprocessor Macros in Build Settings and filling in the macro definition name.

The code looks like this:

#ifdef  TARGET1MACROS
    // target1
#elif defined TARGET2MACROS
    // target2
#endif
Copy the code

Specific package script is not introduced, readers can search online, the disadvantage of this way is a channel to play once, low efficiency. The following focuses on changing the batch packaging mode of PList.

Change the PLIST mode

Here’s a simple Demo:

Step 1: Create a project named MultiChannelDemo and create a channel. plist file in the project. Set the Channel field to channel01. Then set a label label on the page to display the current channel name, which can be obtained using the following code:

NSDictionary *channelDic = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Channel" ofType:@"plist"]];
NSString *channel = channelDic[@"Channel"];
Copy the code

Step 2: Create a parent package for this project with the available certificate. Unzip the ipA package and you can get a folder named Payload.

├ ─ ─ Base. Lproj ├ ─ ─ Channel. The plist ├ ─ ─ the Info. The plist ├ ─ ─ MultiChannelDemo ├ ─ ─ PkgInfo ├ ─ ─ _CodeSignature └ ─ ─ embedded.mobileprovisionCopy the code

As you can see, channel. plist is the plist that stores the Channel information created in the previous project. We will modify the Channel to generate a new Channel package.

Step 3: Extract the description file for re-signing. The folder Payload in the previous step contains the Embedded. Mobileprovision file.

Step 4: Create a new plain text and enter the channel number you want to add, such as:

Step 5: Create a script file, channelpackage. sh, that reads as follows:

#! /bin/bash
Enter the package name

name="MultiChannelDemo"

echo "------SDK channel package ----------"

appName="${name}.app"

plistBuddy="/usr/libexec/PlistBuddy"

configName="Payload/${appName}/Channel.plist"

ipa="${name}.ipa"

The name of the folder in which the new package is exported

outUpdateAppDir="ChannelPackages"

# entitlements. Plist path

entitlementsDir="entitlements.plist"

Switch to the current directory

currDir=${PWD}

cd ${currDir}

echo "-- -- -- -- --${currDir}"

rm -rf Payload

-o: overwrites the file. -q: does not show the decompression process

unzip -o -q ${ipa}

Delete the old folder and rebuild it

rm -rf ${outUpdateAppDir}

mkdir ${outUpdateAppDir}

# delete old entitlements. Plist, re generated

rm -rf ${entitlementsDir}

/usr/libexec/PlistBuddy -x -c "print :Entitlements " /dev/stdin <<< $(security cms -D -i Payload/${appName}/embedded.mobileprovision) > entitlements.plist

echo "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- start packing process -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --"

# Channel list file start packing

for line in $(cat ChannelList.txt)

# loop array, modify channel information

do

# change Channel in plist

$plistBuddy -c "Set :Channel $line" ${configName}

# app re-sign

rm -rf Payload/${appName}/_CodeSignature

cp embedded.mobileprovision "Payload/${appName}/embedded.mobileprovision"

Enter an available certificate ID

codesign -f -s "iPhone Distribution: XXXXXX." Payload/${appName}  --entitlements ${entitlementsDir}

# if the output content/MultiChannelDemo. App: replacing existing signature shows heavy signature

-r: indicates that all files and subdirectories in the specified directory are processed at the same time. -q: indicates that the processing process is not displayed

zip -rq "${outUpdateAppDir}/$line.ipa" Payload

echo "... channel${line}Packing is complete."

done
Copy the code

Please modify the information in the script according to your actual situation. All the preparations have been completed and the required documents are as follows:

├── Bass Exercises ── Bass Exercises ── bass Exercises ── bass Exercises ── Bass ExercisesCopy the code

Step 6: Execute the script file in the current directory:

sh ChannelPackage.sh
Copy the code

The generated ChannelPackages folder after the package is completed is the channel package we need:

├ ─ ─ ChannelList. TXT ├ ─ ─ ChannelPackage. Sh ├ ─ ─ ChannelPackages │ ├ ─ ─ channel02. Ipa │ ├ ─ ─ channel03. Ipa │ └ ─ ─ ├── Heavy Bass Exercises ── Heavy Bass Exercises ── Heavy Bass Exercises ── entitlements.plistCopy the code

This way of automatic packaging can avoid part of Xcode packaging compilation time, fast package out.

Android multi-channel packaging solution

The following is an open source Walle from Meituan Technology team. It has Gradle plug-in and command line. The former can be integrated quickly, and the latter can meet the needs of customization.

Gladle plug-in mode

To configure the build. Gradle

Add the Walle plugin dependency to the build.gradle file in the project root directory:

buildscript {
    dependencies {
        classpath 'com. At meituan. Android. Walle: plugin: 1.1.6'}}Copy the code

Build. Gradle file in app directory:

apply plugin: 'walle'

dependencies {
    compile 'com. At meituan. Android. Walle: library: 1.1.6'
}
Copy the code

Configure the plug-in

Configure channels in build.gradle file in app directory:

walle {
    // Specify the output path of the channel package
    apkOutputFolder = new File("${project.buildDir}/outputs/channels");
    // The APK file name of the custom channel package
    apkFileNameFormat = '${appName}_v${versionName}_${channel}.apk';
    // Channel configuration file
    channelFile = new File("${project.getProjectDir()}/channel")}Copy the code

For details about the format of a channel profile, see Channel Profile Example.

How to obtain channel information

Quote this code where you need to fill in channel information:

String channel = WalleChannelReader.getChannel(this.getApplicationContext());
Copy the code

How to generate channel packages

Export the APK package with the Assemble ${variantName}Channels directive.

Command-line mode

From the command line, you can export the APK of the new channel without opening the IDE. The steps are as follows:

First, create a folder, grab one of the APK packages exported in the previous steps, and then download Walle-cli-all.jar, both placed in this folder directory.

Then, execute the command under the folder directory:

java -jar walle-cli-all.jar put -c ${channelName} ${apkName}.apk
Copy the code

If the preceding command is executed successfully, a new channel package named ${apkName}_${channelName}.apk is generated in the current directory

If you want to write channels in batches, separate them with commas:

java -jar walle-cli-all.jar batch -c ${channelName0}.${channelName1}.${channelName2} ${apkName}.apk
Copy the code

Or specify a channel profile:

java -jar walle-cli-all.jar batch -c ${channelFile} ${apkName}.apk
Copy the code

For additional information, refer to the official documentation.

To check/display channels, the command is:

java -jar walle-cli-all.jar show ${apkName}.apk
Copy the code

Walle can now meet the security requirements of the new application signature scheme, and also meet the requirements of channel package packaging time. If you need it, you can try it.