アメリカのAndroid自動化の旅-チャネルパッケージの生成

6275 ワード

概要
新しいバージョンがリリースされるたびに、美団団体購入Androidクライアントは、エンドウ莢、360携帯電話アシスタントなど、さまざまなアプリケーション市場に配布されます.これらの市場の効果(アクティブ数,下単数など)を統計するためには,それらを一意に識別する方法が必要である.
団体購入クライアントは現在、チャネル番号(channel)によって異なる市場を区別しており、コードにはConfig.channel変数を使用してチャネル番号を記録している.例えば、エンドウ莢市場の中米団応用チャネル番号はwandoujia360携帯電話アシスタント中米団応用チャネル番号はqihu360である.クライアントがAPIにアクセスすると、要求パラメータにチャネル番号が付けられ、バックグラウンドで異なるチャネルの効果が計算されます.
リリースのたびに、市場部はチャネルリストを提供し、Android RDはこれらのチャネルに応じて等量のチャネルパッケージを生成します.チャネルがますます多くなるにつれて(本稿を書くまでに900以上のチャネルがある)、クライアントがチャネルパッケージを打つ方法も進化してきた.本稿では、美団アプリケーションのパッケージ化の旅を詳しく紹介する.
Maven
Mavenはソフトウェアプロジェクト管理と自動構築ツールで、android-maven-pluginプラグインとmaven-resources-pluginプラグインを組み合わせてチャネルパッケージを簡単に生成できます.以下、パッケージ化の手順を簡単に説明します.Mavenおよびプラグインの使用方法については、関連ドキュメントを参照してください.
まず、チャネルのソースを定義するために、AndroidManifest.xmlノードに次の要素を追加する.


チャネルソースを定義すると、プログラムの起動時にチャネル番号を読み込むことができます.
private String getChannel(Context context) {
        try {
            PackageManager pm = context.getPackageManager();
            ApplicationInfo appInfo = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
            return appInfo.metaData.getString("channel");
        } catch (PackageManager.NameNotFoundException ignored) {
        }
        return "";

    }
AndroidManifest.xmlファイルで定義されたチャネル番号を置き換えるには、pom.xmlファイルでResourcesプラグインを構成する必要があります.
           
    
        ${project.basedir}
        true
        ${project.build.directory}/filtered-manifest
        
            AndroidManifest.xml
        
    

準備は完了しましたが、今必要なのは実際のチャネル番号です.次のスクリプトは、チャネルリストを巡回し、1つずつ置き換えてパッケージ化します.
#!/bin/bash

package(){
    while read line
    do
        mvn clean
        mvn  -Dchannel=$line package
    done < $1
}

package $1
前期のチャネルが少ない場合、この方法は受け入れられるが、チャネルが少し増えると、この方法は適用されなくなる.なぜなら、パケットを1つ打つたびに構築プロセスを実行しなければならないため、効率が低すぎるからだ.
apktool
apktoolは逆方向エンジニアリングツールであり、apk内のリソースを復号して変更することができます.次にapktoolを使用してチャネルパッケージを生成する方法について詳しく説明します.
前期の作業はMavenでパッケージ化するのと同様に、AndroidManifest.xmlファイルに要素を定義し、アプリケーションが起動したときにリストファイルのチャネル番号を読み込む必要があります.具体的には上のコードを参照してください.
Mavenとは異なり、パッケージ化のたびにプロジェクトを再構築する必要はありません.パッケージ化する場合は、apkを生成し、そのapkに基づいて他のチャネルパッケージを生成するだけでよい.
まず、apktool decodeアプリケーションを使用して、端末に次のコマンドを入力します.
apktool d your_original_apk build
上記のコマンドはbuildディレクトリにdecodeアプリケーションファイルがあり、decodeが完了したディレクトリは次のとおりです.
次に、AndroidManifest.xmlファイルで定義されているチャネル番号を置き換えます.以下はpythonスクリプトです.
import re

def replace_channel(channel, manifest):
    pattern = r'()'
    replacement = r"\g<1>{channel}\g<3>".format(channel=channel)
    return re.sub(pattern, replacement, manifest)
次に、apktoolを使用して署名されていないapkを構築します.
apktool b build your_unsigned_apk
最後にjarsignerを使用してapkに再署名します.
jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore your_keystore_path -storepass your_storepass -signedjar your_signed_apk, your_unsigned_apk, your_alias
以上,apktoolを用いてパッケージ化する方法であり,スクリプトを用いてチャネルパッケージを一括生成することができる.Mavenとは異なり、パッケージを1つ打つたびに構築プロセスを実行する必要があります.この方法は1回構築するだけで、時間を大幅に節約できます.
しかし、好景は長くなく、私たちのチャネルパッケージはますます多くなり、現在900近くのチャネルがあり、すべてのチャネルパッケージを完了するには3時間近くかかります.もっと早い梱包方法はありませんか?次の節を見よう.
META-INF
apkのチャネル番号を直接変更でき、再署名を必要とせずにパッケージの時間を節約できます.幸いなことに私たちはこの方法を見つけた.直接apkを解凍すると、解凍後のルートディレクトリにはMETA-INFディレクトリがあります.次の図に示します.META-INFディレクトリに空のファイルを追加する場合は、アプリケーションに再署名する必要はありません.したがって、異なるチャネルのアプリケーションに異なる空のファイルを追加することで、チャネルを一意に識別することができます.
次のpythonコードはapkに空のチャネルファイルを追加するために使用され、チャネル名のプレフィックスはmtchannel_です.
import zipfile
zipped = zipfile.ZipFile(your_apk, 'a', zipfile.ZIP_DEFLATED) 
empty_channel_file = "META-INF/mtchannel_{channel}".format(channel=your_channel)
zipped.write(your_empty_file, empty_channel_file)
空のチャネルファイルを追加したディレクトリは、META-INFOディレクトリにmtchannel_meituanという空のファイルが追加されました.
次に、Javaコードから空のチャネルファイル名を読み込むことができます.
public static String getChannel(Context context) {
        ApplicationInfo appinfo = context.getApplicationInfo();
        String sourceDir = appinfo.sourceDir;
        String ret = "";
        ZipFile zipfile = null;
        try {
            zipfile = new ZipFile(sourceDir);
            Enumeration> entries = zipfile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = ((ZipEntry) entries.nextElement());
                String entryName = entry.getName();
                if (entryName.startsWith("mtchannel")) {
                    ret = entryName;
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (zipfile != null) {
                try {
                    zipfile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        String[] split = ret.split("_");
        if (split != null && split.length >= 2) {
            return ret.substring(split[0].length() + 1);

        } else {
            return "";
        }
    }
これにより、チャネルパケットを1つ打つたびにapkをコピーし、META-INFにチャネル番号で命名された空のファイルを追加するだけでよい.この梱包方式は非常に速く、900以上のルートが1分もしないうちに終わる.
まとめ
全部で3種類のチャネルパッケージの作り方を紹介しました.現在、Androidチームのパッケージは基本的に3つ目の方法を使用しており、パッケージの自動化を完了し、エンジニアの生産性を解放し、善哉善哉です.
パッケージ化の問題は解決しましたが、異なるチャネルに異なるAPKをカスタマイズする必要がある場合があります.次はAndroidビルダーGradleとGradleカスタムチャネルパッケージの使い方についてご紹介しますので、ご期待ください.
文章に誤りがあり、内容に疑問があることを発見したら、美団評価技術チームの微信公衆番号(meituantech)に注目し、楽屋で私たちにメッセージを送ることができます.私たちは毎週熱心な仲間を選んで、美しい贈り物をします.早くコードをスキャンして私たちに注目してください.