Android 安卓&x2013;同一应用程序的多个自定义版本
部署多个定制版本的Android应用程序的最佳方式是什么 目前,我有一个脚本来交换资源文件夹,以获得我的应用程序的自定义版本。它工作得很好,但是所有自定义版本在AndroidManifest.xml中仍然具有相同的包名。因此,不可能同时安装两个自定义版本的应用程序 你能想出一个更简单的解决方案,或者如何将其构建到SKcript中Android 安卓&x2013;同一应用程序的多个自定义版本,android,automation,Android,Automation,部署多个定制版本的Android应用程序的最佳方式是什么 目前,我有一个脚本来交换资源文件夹,以获得我的应用程序的自定义版本。它工作得很好,但是所有自定义版本在AndroidManifest.xml中仍然具有相同的包名。因此,不可能同时安装两个自定义版本的应用程序 你能想出一个更简单的解决方案,或者如何将其构建到SKcript中 (顺便说一句:它不适用于色情/垃圾邮件/任何应用程序,甚至不适用于付费应用程序)链接到解决方案不必手动完成。请记住,元素中的package属性不必位于代码所在的位置,
(顺便说一句:它不适用于色情/垃圾邮件/任何应用程序,甚至不适用于付费应用程序)链接到解决方案不必手动完成。请记住,
元素中的package
属性不必位于代码所在的位置,只要您在清单中的其他位置拼写出完全限定的类(例如,activity android:name=“com.commonware.android.MyActivity”
而不是activity android:name=“.MyActivity”
)。编写清单更改脚本并使用Ant构建新的APK。好的,那应该行。对于类似的事情,我所做的只是使用一个antlib任务,然后遍历所有java和xml文件,将旧的包字符串替换为新的包字符串。根据包,文件是否不在正确的src路径中并不重要。只要对所有的文件做一个正则表达式替换就足够让它工作了
例如,要在src目录下的所有java文件中替换它:
<replaceregexp flags="g" byline="false">
<regexp pattern="old.package.string" />
<substitution expression="new.package.string" />
<fileset dir="src" includes="**/*.java" />
</replaceregexp>
我要实现这一点。为生成的源目标指定一个AndroidManifest.xml,为最终apk目标指定另一个AndroidManifest.xml。这样,在生成R类和构建阶段,源代码项目将保留实际的源代码包名称,而适应市场的清单包名称位于最终apk文件中包含的第二个AndroidManifest.xml中。支持多个合作伙伴
准备config.xml
为不同的合作伙伴构建项目
<!--partner.dir, pkg.name, ver.code, ver.name are input from command line when execute 'ant' -->
<!-- set global properties for this build -->
<property name="build.bin" location="bin"/>
<property name="build.gen" location="gen"/>
<property name="src" location="src"/>
<property name="res" location="res"/>
<target name="preparefiles" description="Prepare files for different partner" >
<delete dir="${build.bin}" />
<delete dir="${build.gen}" />
<copy todir="${res}" overwrite="true" />
<fileset dir="${partner.dir}/res" />
</copy>
<!-- change the import in all Java source files -->
<replaceregexp file="AndroidManifest.xml"
match='android.versionCode="(.*)"'
replace='android.versionCode="${ver.code}"'
byline="false">
<replaceregexp file="AndroidManifest.xml"
match='android.versionName="(.*)"'
replace='android.versionName="${ver.name}"'
byline="false">
<replaceregexp file="AndroidManifest.xml"
match='package="(.*)"'
replace='package="${pkg.name}"'
byline="false">
<!-- change the package name in AndroidManifest -->
<replaceregexp flags="g" byline="false">
<regexp pattern="import(.*)com.myproject.com.R;" />
<substitution expression="import com.${pkg.name}.R;" />
<fileset dir="${src}" includes="**/*.java" />
</replaceregexp>
<replaceregexp flags="g" byline="false">
<regexp pattern="(package com.myproject.com;)" />
<substitution expression="\1 import com.${pkg.name}.R;" />
<fileset dir="${src}" includes="**/*.java" />
</replaceregexp>
</target>
准备文件
$ant-f config.xml-Dpartner.dir=“xxx”-Dpkg.name=“xxx”-Dver.code=“xxx”-Dver.name=“xxx”准备文件
创建build.xml
建造
$ant调试
或
$ant版本也许在最初发布文章时,内置的Android“库”概念还没有完全成熟,但从2011年起,它可能是首选的方法。对于ant构建,请遵循以下步骤: 从一个工作应用程序(我们称之为目录“myOrigApp”,package com.foo.myapp)开始,只需将这一行添加到“default.properties”以使其成为一个库:
android.library=true
现在,以您喜欢的任何方式在同级目录中创建一个新应用程序(让我们称之为目录“sibling”,package com.foo.myVariant)。例如,使用Intellij Idea,“从头开始”创建一个包含目录“sibling”的项目,它将创建您通常需要的所有文件/目录
在新的同级目录中,编辑“default.properties”以添加依赖项:
android.library.reference.1=../myOrigApp
从原始目录复制清单:
cd sibling
cp ../myOrigApp/AndroidManifest.xml ../myOrigApp/local.properties ../myOrigApp/build.properties .
编辑复制的清单文件,将其包名更改为新变量“com.foo.myVarient”;这是唯一的改变
如果您只是运行ant构建脚本,您可能已经完成了。(我只需要设置签名密钥。)
如果要设置类似IDE的IDE,使库项目作为变体项目的从属项目,请按照以下步骤将库项目添加到变体项目中(假设已经为这两个项目设置了项目):
- 打开原始项目,打开项目设置,选择您的方面,选中“是库项目”并保存
- 打开变体项目,调出项目设置,选择模块
- 添加模块
- 选择“导入现有模块”
- 浏览到原始目录(myOrigApp)并选择其.iml文件(IntelliJ项目源文件)
- 单击“完成”。(库项目作为模块添加到变体项目中。)
- 在模块列表中,单击变体项目以将其选中
- 在右侧选择“依赖项”选项卡
- 单击“添加…”
- 选择“Module dependency…”(应显示一个列表,其中包括您先前添加到项目中的模块/库的名称——可能是列表中唯一的条目)李>
- 选择添加的库项目,然后按“确定”。(它将被添加到项目的依赖项列表中。)
- 按“确定”完成项目的配置。(您应该看到两个模块,其中库的资源和类在变体项目中可用并得到认可。)
# In the file 'fname',
# find the text matching "before oldtext after" (all occurrences) and
# replace 'oldtext' with 'newtext' (all occurrences).
# If 'mandatory' is true, raise an exception if no replacements were made.
def fileReplace(fname,before,newtext,after,mandatory=True):
with open(fname, 'r+') as f:
read_data = f.read()
pattern = r"("+re.escape(before)+r")\w+("+re.escape(after)+r")"
replacement = r"\1"+newtext+r"\2"
new_data,replacements_made = re.subn(pattern,replacement,read_data,flags=re.MULTILINE)
if replacements_made and really:
f.seek(0)
f.truncate()
f.write(new_data)
if verbose:
print "patching ",fname," (",replacements_made," occurrence", "s" if 1!=replacements_made else "",")"
elif replacements_made:
print fname,":"
print new_data
elif mandatory:
raise Exception("cannot patch the file: "+fname)
您可能会发现以下用途之一:
# Change the application resource package name everywhere in the src/ tree.
# Yes, this changes the java files. We hope that if something goes wrong,
# the version control will save us.
def patchResourcePackageNameInSrc(pname):
for root, dirs, files in os.walk('src'):
if '.svn' in dirs:
dirs.remove('.svn')
for fname in files:
fileReplace(os.path.join(root,fname),"import com.xyz.",pname,".R;",mandatory=False)
还有一个函数可以将资产从x-assets-cfgname
复制到assets
(之前的结果表明,对于我来说,在assets
中有一个子目录更方便)
好吧,你明白了。现在您可以编写自己的脚本了。我认为最好的方法是创建一个新项目并复制内容。步骤, -创建没有类的新android项目 -创建包(包名应与清单文件中的包名相对应),或仅将包名复制到“gen”文件夹中 -复制java文件 -复制可绘制文件夹 -复制布局文件 -复制您的项目中使用的任何其他文件 -复制清单文件的数据 <
def copyAssets(vname,force=False):
assets_source = "x-assets-"+vname+"/xxx"
assets_target = "assets/xxx"
if not os.path.exists(assets_source):
raise Exception("Invalid variant name: "+vname+" (the assets directory "+assets_source+" does not exist)")
if os.path.exists(assets_target+"/.svn"):
raise Exception("The assets directory must not be under version control! "+assets_target+"/.svn exists!")
if os.path.exists(assets_target):
shutil.rmtree(assets_target)
shutil.copytree(assets_source, assets_target, ignore=shutil.ignore_patterns('.svn'))