美团多渠道打包之实现篇

  在这个一搜一大把解决方案的年代,我们有时候可以多去学习下人家的技术和方案,写这篇文章的时候,只是想把好早前就跟着玩了一把多渠道快速打包的方法实现总结下,方便以后万一在什么场景需要用的时候拿出来看看。至于原文,有好多资源,大家可以搜一下,我这里暂时参考了这篇文章点击打开链接。我只是代码搬运工大笑

  首先,新建一个空项目,很简单,编辑activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.jianzou.thread.MainActivity">


    <Button
        android:id="@+id/btn_01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"/>
</RelativeLayout>
很简单,然后再MainActivity中引用下:

public class MainActivity extends AppCompatActivity
{

    Button btn_01;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_01 = (Button) findViewById(R.id.btn_01);
        btn_01.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent i = new Intent(MainActivity.this,OtherActivity.class);
                startActivity(i);
            }
        });
    }

创建OtherActivity:

package com.jianzou.thread;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.widget.Button;

/**
 * Created by JianZou on 2016/12/5.
 */

public class OtherActivity extends AppCompatActivity
{
    Button btn_01;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_01 = (Button) findViewById(R.id.btn_01);
        String channel = MutiChannelConfig.getChannel(this);
        btn_01.setText(channel );
    }
}

package com.jianzou.thread;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.util.Log;

import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * Created by JianZou on 2016/12/5.
 */

public class MutiChannelConfig
{
    public static final String Version = "version";

    public static final String Channel = "channel";

    public static final String DEFAULT_CHANNEL = "netease";

    public static final String Channel_File = "channel";

    public static String getChannelFromMeta(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("META-INF") && entryName.contains("channel_"))
                {
                    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 DEFAULT_CHANNEL;
        }
    }

    /**
     * 得到渠道名
     *
     * @param mContext
     * @return
     */
    public static String getChannel(Context mContext)
    {
        String channel = "";
        if (isNewVersion(mContext))
        {//是新版本
            Log.e("isNewVersion  %s", "isNewVersion");
            saveChannel(mContext);//保存当前版本
            channel = getChannelFromMeta(mContext);
        } else
        {
            channel = getCachChannel(mContext);
        }
        return channel;
    }

    /**
     * 保存当前的版本号和渠道名
     *
     * @param mContext
     */
    public static void saveChannel(Context mContext)
    {
        SharedPreferences mSettinsSP = mContext.getSharedPreferences(Channel_File, Activity.MODE_PRIVATE);
        SharedPreferences.Editor mSettinsEd = mSettinsSP.edit();
        mSettinsEd.putString(Version, APPUtils.getAppVersion(mContext));
        mSettinsEd.putString(Channel, getChannelFromMeta(mContext));
        //提交保存
        mSettinsEd.commit();
    }

    private static boolean isNewVersion(Context mContext)
    {
        SharedPreferences mSettinsSP = mContext.getSharedPreferences(Channel_File, Activity.MODE_PRIVATE);
        String version = APPUtils.getAppVersion(mContext);
        Log.e("version%s", version);
        return !mSettinsSP.getString(Version, "").equals(version);
    }

    private static String getCachChannel(Context mContext)
    {
        SharedPreferences mSettinsSP = mContext.getSharedPreferences(Channel_File, Activity.MODE_PRIVATE);
        return mSettinsSP.getString(Channel, DEFAULT_CHANNEL);
    }
}

记得在AndroidManifest.xml中注册OtherActivity,好,看到MutiChannelConfig这个类,这个也是打包提供的类,在getChannel(Context mContext)这个方法这里,我之前的猜测是:如果我的包在用此脚本打包后,对应的渠道名就应该会从这个方法返回,如果返回了,我就显示在这个button上,否则,button显示为NETEASE。为了验证这个猜想,开始着手实验看看呗!

APP工程很简单,写完了,自己申请个key,这个不多说了,搞过Android开发的老司机们都很熟的。将上面的项目用自己的key先打包,

下载安装python环境:点击打开链接

下载python脚本:点击打开链接

Python环境的安装,很简单,此处略过,环境安装好后,看下载的Python脚本:


操作步骤:将上面打好的apk放在PythonTool文件夹下面,和MultiChannelBuildTool.py同级,看图:

注意:MultiChannelBuildTool.py这个文件请选择打开方式是Python,看前面的小图标(还有一种打开方法:直接命令行执行)。直接双击运行MultiChannelBuildTool.py这个脚本,真的是一眨眼功夫,包就出来了:


打出的apk包全部在output_app-release文件夹下面。在写下文之前,这里还是提一下,这个多渠道打包默认的渠道名是在info这个文件夹下面的channel.txt中,我这里面的内容是这样的:


按照这个格式,任意写需要打包的渠道名即可。回到output_app-release文件夹,对应打出的包:

最后拿出手机来测试下我上面所说的猜想:如果我现在安装91com的包,按道理来说,OtherActivity中的button就应该显示91com,安装xiaomi的包,OtherActivity中的button就应该显示xiaomi,以此类推。好,看下效果吧。

 

后面也试了一下其他apk,都是准确的把对应的渠道名显示出来了。OK!到此,基本就是这样了,也就是说,channel.txt中对应的渠道名打到包里面了。在实际项目中,可以用这里拿到的渠道去做更多的事情,这个就自由发挥了。谢谢大家能看到这里!也谢谢能将技术分享出来的大神们,我只是你们的代码搬运工。还有,写到这,再啰嗦几句:不管是什么知识,看到和知道并不一定你就得到,想得到很简单,动手实现试试就行,很多知识只有亲自做一遍才有底,实践出真知!谢谢大家!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值