码迷,mamicode.com
首页 > 其他好文 > 详细

多渠道打包,生成不同包名的包

时间:2016-04-22 19:45:45      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:

来对多渠道打包,并生成不同的包名的知识点做个总结。需要生成不同包名的原因是为了运营的ASO。

方法:

1.直接建立渠道的文件夹,修改Manifest里面的包名

2.利用占位符

当然上面两种方法各有优劣,最后说一下他们的各自的一些特点。

首先来说第一种方法,步骤:

1.根据需要生成多少个包名的包建立和main同级的文件夹。

例如:我这里需要两个不同包名的包,那就需要建立两个不同渠道的文件夹。
技术分享

2.在文件夹里面新建Maifest文件

因为包名是在Manifest文件里面定义的,所以需要建立Manifest文件,当然这个Manifest文件里面拷贝过来,你可能会觉得太麻烦,我只是替换一个包名需要把整个Manifest都拷贝过来么,这也太坑了,其实没有这么严重,包名一般包括在用户手机桌面上面显示的名字,和你去应用程序管理器里面看到的名字,这两个名字是可以不同的。

在应用程序管理器里面显示的名字是由application节点的android:label属性决定的。
技术分享

用户手机桌面上面显示的名字是由应用程序的第一个Activity的android:label决定的,如果第一个Activity没有指定label属性的话,就是使用的Application的android:label的名字。
技术分享
顺便提一句,应用程序的第一个Activity是有下面的intent-filter的Activity。

<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

这里我们明白了,应用程序的两个包名,那么既然我们需要改变的只是包名而已,就只需要把application节点和第一个Activity在Manifest里面的配置拷贝过来就可以了
所以这里需要的两个Manifest文件分别是这样的:
先贴一下main渠道的主的Manifest文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.name.replace"
xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        ...
        其他配置
        ...
    </application>
</manifest>

app_name_1渠道:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.name.replace"
xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name_1"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:replace="android:label">
        <activity
            android:name=".MainActivity"
            android:label="@string/desk_name_1"
            tools:replace="android:label">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

app_name_2渠道:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.name.replace"
xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name_2"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:replace="android:label">
        <activity
            android:name=".MainActivity"
            android:label="@string/desk_name_2"
            tools:replace="android:label">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

这里可以看到app_name_1里面的Manifest和app_name_2里面的Manifest并没有太大的差别,只是包名改了一下而已。这两个文件没有什么可比较的价值。

着重看一下app_name_2渠道的Manifest和main里面的Manifest的差别,如果你说没有差别,那就比较尴尬了,妈蛋,我450度的眼镜都看出差别了。

两个差别:

(1).在app_name_2的渠道里面引入了新的tools命名空间。

xmlns:tools=”http://schemas.android.com/tools”
并且在application节点和第一个Activity节点添加了tools:replace=”android:label”语句。
如果没有添加Gradle在使用Manifest Merger Tool进行合并Manifest的时候出出问题。

(2).app_name_2渠道除了application节点和第一个Activity节点之外,没有其他的东西。

不需要main里面的其他的一些四大组件相关的一些东西。

3.在build.gradle里面配置渠道信息

    productFlavors {
        app_name_1 {}
        app_name_2 {}
        app_main {}
        }

这里的渠道名要和一开始建立的文件夹的名字一样,如果不一样,打出的包就是main里面的包。

4.打包即可




第二种方法,步骤:

得益于gradle对于占位符的支持,第二种方法远没有第一种方法那么麻烦。
关于占位符的用法有很多,比如可以动态的定义Activity的名字,Service的名字等。详细的可以自行Google。
关于gradle的清单合并可以看这一篇翻译的文章,讲解的非常详细:
清单合并:http://blog.csdn.net/maosidiaoxian/article/details/42671999

1.在Manifest里面配置占位符

由于不需要建立文件夹,这里说的Manifest就是main里面的Manifest。
当属性值包含一个占位符时,合并工具将把此占位符的值换成一个注入的值。注入的值是在build.gradle里面定义的。
占位符值的语法是 ${name},因为@符号已经预留给了链接。在最后的文件合并发生之后,并且生成合并后的 android 的清单文件输出之前,带有占位符的所有值将都会被替换为注入的值。如果变量名是未知的,将导致构建失败。
Manifest文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.name.replace"
xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="${app_name}"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <meta-data
            android:name="UMENG_CHANNEL"
            android:value="${umeng_channel}"/>
        <activity
            android:name=".MainActivity"
            android:label="${desk_name}">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

这里定义了三个占位符,app_name,desk_name,umeng_channel。
占位符可以替换的还有很多用处,想了解更多的可以自己查资料。

2.在build.gradle里面配置渠道信息

这里贴出整个Manifest文件,供大家更好的看清。

apply plugin: ‘com.android.application‘
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    defaultConfig {
        applicationId "com.name.replace"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        manifestPlaceholders = [
                app_name     : "@string/app_name",
                desk_name    : "@string/app_name",
                umeng_channel: "测试版"
        ]
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
        }
    }
    productFlavors {
//        app_name_1 {}
//        app_name_2 {}
//        app_main {}
        app_qq {
            manifestPlaceholders = [
                    app_name     : "@string/app_name_1",
                    desk_name    : "@string/desk_name_1",
                    umeng_channel: "应用宝"
            ]
        }
        app_pp {
            manifestPlaceholders = [
                    app_name     : "@string/app_name_2",
                    desk_name    : "@string/desk_name_2",
                    umeng_channel: "pp助手"
            ]
        }
    }
}
dependencies {
    compile fileTree(dir: ‘libs‘, include: [‘*.jar‘])
    testCompile ‘junit:junit:4.12‘
    compile ‘com.android.support:appcompat-v7:23.3.0‘
}

可以看到我们对Manifest里面定义的三个占位符做了替换。
这里我们既在defaultConfig里面定义了,又在不同的渠道里面做了再次定义,最后渠道里面的优先级会高。
其实如果一开始没有配置渠道信息,但是我们定义了占位符的话,是编译不过去的,必须在defaultConfig里面定义默认的一些属性。

3.打包即可

最开始的时候我们说了这两种方法各有优缺点,在以前的公司的时候采用的是第一种方案,原因有两点:
1.采用第一种方案,可以对每个渠道加上渠道的logo,比如360的渠道需要360的logo,百度的渠道需要百度的logo,那么采用第一种方法就很好实现了,把main里面的res/layout里面的启动界面拷贝一份到对应的渠道文件里面进行修改,替换logo。
第一种方法里面不止可以放置Manifest文件,还可以放置res目录。

2.当时的渠道包不需要我们技术人员去打,由运营去打,技术这边当时是开发了一个工具供运营那边打渠道包专用,技术这边只需要打好不同的包名的包即可。

所以第一种方法的优点是可以完成一些其余的特殊的操作,缺点是比较麻烦。第二种方法是实现比较简单,但是有些特殊的操作就不能行了。

Demo地址:http://download.csdn.net/detail/qy274770068/9498668

多渠道打包,生成不同包名的包

标签:

原文地址:http://blog.csdn.net/qy274770068/article/details/51213878

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!