您的位置:首页 > 编程语言 > C#

C#实现APK自动打包

2013-11-22 13:50 441 查看


C#实现APK自动打包

最近做了一个安卓项目,其中有一个自动打包的功能,要把供应商id写入APK后打包。


一、思路

在AndroidMinifest.xml中加入一个标识字段,如下配置
<meta-dataandroid:name="Vendorid"android:value="xx"/>,把每个供应商的Id值写到android:value这里,然后用命令行打包。




二、准备工作

用到的工具有AndroidSDK,Apache-Ant,JDK1.7。

1,安装JDK1.7(默认安装在C:\ProgramFiles\Java)。安装完成后,添加环境变量JAVA_HOME,值就是Java\jdk1.7.0_25\的实际路径(如果是默认安装的话,那就是C:\ProgramFiles\Java\jdk1.7.0_25\)。

2,建一个文件夹(本文中是建在D盘,D:\apktools),然后把AndroidSDK目录下的platforms、platform-tools、tools这三个文件夹,以及解压后的Apacheant拷贝到D:\apktools。

3,APK源代码我是放在D:\src目录下。


三、测试-用命令行打包

做这一步是为了测试之前的准备工作是否做对了。

1,cd/dD:\src,cd到源代码的文件夹

2,D:\apktools\tools\android.batupdateproject-nButtonDemo-tandroid-17-pd:\src,这个批处理可以生成一个工程,工程里配置build.xml脚本。其中,-nButtonDemo:项目名称、-tandroid-17:我这里使用android-17这个版本、-p
d:\src:输出到代码目录下。

3,D:\apktools\apache-ant-1.9.1\bin\ant.batdebug
4,D:\apktools\apache-ant-1.9.1\bin\ant.batrelease,编译成功后命令行会显示BUILDSUCCESSFUL。




四、代码实现

最初的代码如下:



privatevoidPackage()

{

Processpcmd=newProcess();

pcmd.StartInfo.FileName="cmd.exe";

pcmd.StartInfo.UseShellExecute=false;

pcmd.StartInfo.RedirectStandardInput=true;

pcmd.StartInfo.RedirectStandardOutput=true;

pcmd.StartInfo.CreateNoWindow=true;

pcmd.Start();

pcmd.StandardInput.Write("cd/dD:\src");

pcmd.StandardInput.WriteLine("");

pcmd.StandardInput.Write("D:\apktools\tools\android.batupdateproject-nButtonDemo-tandroid-17-pd:\src");

pcmd.StandardInput.WriteLine("");

pcmd.StandardInput.Write("D:\apktools\apache-ant-1.9.1\bin\ant.batdebug");

pcmd.StandardInput.WriteLine("");

pcmd.StandardInput.Write("D:\apktools\apache-ant-1.9.1\bin\ant.batrelease");

pcmd.StandardInput.WriteLine("");

pcmd.StandardInput.WriteLine("exit");

stringstroutput=pcmd.StandardOutput.ReadToEnd();

}

调试时发现,ant.batdebug这一步出错,说是JAVA_HOME配置的不对,提示的路径和我实际配置的不一样。必应了一把,看到这篇和这篇,大致上就是说UseShellExecute=false方式启动的进程不能访问环境变量,要改成UseShellExecute=true,但是在true的时候,不能重定向输入输出异常这几个了(RedirectStandardInput、RedirectStandardOutput、RedirectStandardError),原先启动cmd.exe,然后输入命令行的方式就行不通了。

调整了下思路,把这几个命令写成一个批处理,然后Process执行这个批处理就可以了。



cd/dD:\src

callD:\apktools\tools\android.batupdateproject-nButtonDemo-tandroid-17-p
d:\src>{log}

callD:\apktools\apache-ant-1.9.1\bin\ant.bat
debug>>{log}

callD:\apktools\apache-ant-1.9.1\bin\ant.batrelease>>{log}

由于不能用RedirectStandardOutput=true来获取输出信息,所以这里我用了dos命令>>{log}来输出。

最终的打包代码如下:



privateboolPackage()

{

//先删除编译后的文件,执行完批处理后,通过判断文件存在与否来确定打包是否成功

stringreleaseFile="d:\src\ButtonDemo-release.apk";

if(File.Exists(releaseFile))

{

File.Delete(releaseFile);

}

//生成批处理命令D:\package.bat

CreateBatFile();

ProcessStartInfopi=newProcessStartInfo();

pi.FileName="D:\package.bat";

pi.UseShellExecute=true;

pi.CreateNoWindow=true;

Processpcmd=Process.Start(pi);

//等待进程结束

while(pcmd.HasExited==false)

{

pcmd.WaitForExit(1000);

}

pcmd.Close();

pcmd.Dispose();

if(!File.Exists(releaseFile))

{

//打包失败

returnfalse;

}

//打包成功

returntrue;

}

AndroidManifest.xml中添加meta-data节点的代码



privatevoidInsertVendorXmlElememnt()

{

List<string>androidnames=newList<string>();

stringxmlfile=@"AndroidManifest.xml";

XmlDocumentxmldoc=newXmlDocument();

xmldoc.Load(_androidSourcePath+xmlfile);

XmlNodexmlApp=xmldoc.SelectSingleNode("//application");

XmlNodeListxmlnodes=xmlApp.SelectNodes("//meta-data");

foreach(XmlNodeiteminxmlnodes)

{

if(!androidnames.Contains(item.Attributes["android:name"].Value))

{

androidnames.Add(item.Attributes["android:name"].Value);

}

}

if(!androidnames.Contains("vendorid"))

{

XmlElementxmlelemember=xmldoc.CreateElement("meta-data");

XmlAttributememAttr=xmldoc.CreateAttribute("android","name","http://schemas.android.com/apk/res/android");

memAttr.Value="vendorid";

xmlelemember.SetAttributeNode(memAttr);

XmlAttributememValue=xmldoc.CreateAttribute("android","value","http://schemas.android.com/apk/res/android");

memValue.Value="";

xmlelemember.SetAttributeNode(memValue);

xmlApp.AppendChild(xmlelemember);

}

xmldoc.Save("d:\src\AndroidManifest.xml");

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: