加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

操作XML以及签名实例

发布时间:2020-12-16 05:25:52 所属栏目:百科 来源:网络整理
导读:http://blog.csdn.net/tibib/article/details/8811759 前几天接到个需求,如何根据一个基础的Android App来生成100个或更多的App,要求App icon和App name都不一样(可能还会有配置文件)。这个有点类似于为App贴上自己的标签,但具体功能由别人提供,有点类

http://blog.csdn.net/tibib/article/details/8811759


前几天接到个需求,如何根据一个基础的Android App来生成100个或更多的App,要求App icon和App name都不一样(可能还会有配置文件)。这个有点类似于为App贴上自己的标签,但具体功能由别人提供,有点类似于OEM,下面来分析下如何实现

仔细想一下其实这个就是apk的编译和反编译的应用,再加上个签名(不签名的话无法使用)。只不过是用代码实现罢了

准备工作

1、配置好Java开发环境
2、下载google提供的apk编译和反编译工具 (包含apktool.jar、apktool.bat、aapt.exe三个文件)
3、下载google提供的签名工具(包含sign.bat、signapk.jar两个文件)

icon覆盖和strings文件修改


我们都知道,在Android应用中应用的icon和应用的名称是在AndroidManifest.xml中指定的,应用名称的话有可能直接写死,但多数是这种情况
[html] view plain copy
  1. android:icon="@drawable/ic_launcher"
  2. ndroid:label="@string/app_name"

我们只要覆盖drawable-*下对应名字的icon图片和修改values-*路径下strings.xml中对应名字的属性值就行了,为了简单起见在这里以drawable-hdpi和values-zh-rCN路径来介绍

AndroidManifest.xml解析


通过上面的介绍,我们需要从AndroidManifest.xml获取icon和label两个属性的值,下面是一个简单的解析类,该注意的地方都有注释

[java] copy
    /**
  1. *@authorTibib
  2. *
  3. */
  4. publicclassAndroidManifestParser{
  5. publicStringNS="http://schemas.android.com/apk/res/android";
  6. publicAppInfoparse(InputStreamin)throwsException{
  7. try{
  8. //使用pull解析库
  9. XmlPullParserparser=XmlPullParserFactory.newInstance().newPullParser();
  10. NS=parser.getNamespace();
  11. //设置使用namespaces特性
  12. parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,true);
  13. parser.setInput(in,"UTF-8");
  14. parser.nextTag();
  15. returnreadAppInfo(parser);
  16. }catch(Exceptione){
  17. e.printStackTrace();
  18. throwe;
  19. }finally{
  20. in.close();
  21. }
  22. }
  23. privateAppInforeadAppInfo(XmlPullParserparser)throwsException{
  24. AppInfoappInfo=newAppInfo();
  25. while(parser.next()!=XmlPullParser.END_TAG){
  26. if(parser.getEventType()!=XmlPullParser.START_TAG){
  27. continue;
  28. Stringname=parser.getName();
  29. //StartsbylookingfortheGeneraltag
  30. if("application".equals(name)){
  31. StringattrLabelValue=parser.getAttributeValue(NS,"label");
  32. StringattrIconValue=parser.getAttributeValue(NS,"icon");
  33. appInfo.setAppName(attrLabelValue.split("/")[1]);
  34. appInfo.setIconName(attrIconValue.split("/")[1]);
  35. else{
  36. skip(parser);
  37. returnappInfo;
  38. //Skipstagstheparserisn'tinterestedin.Usesdepthtohandlenestedtags.i.e.,
  39. //ifthenexttagafteraSTART_TAGisn'tamatchingEND_TAG,itkeepsgoinguntilit
  40. //findsthematchingEND_TAG(asindicatedbythevalueof"depth"being0).
  41. privatevoidskip(XmlPullParserparser)throwsXmlPullParserException,IOException{
  42. thrownewIllegalStateException();
  43. intdepth=1;
  44. while(depth!=0){
  45. switch(parser.next()){
  46. caseXmlPullParser.END_TAG:
  47. depth--;
  48. break;
  49. caseXmlPullParser.START_TAG:
  50. depth++;
  51. break;
  52. }

修改strings.xml中name属性为app_name(具体名称看配置)的值

copy
    classXmlModifyUtil{
  1. /**
  2. *使用的是jdom库
  3. staticvoidmodifyXML(FilemodifyXmlFile,StringappNameAttrValue,
  4. StringappNameText){
  5. OutputStreamWriterbos=null;
  6. try{
  7. SAXBuilderbuilder=newSAXBuilder();
  8. if(modifyXmlFile.exists()){
  9. Documentdocument=(Document)builder.build(modifyXmlFile);
  10. Elementroot=document.getRootElement();
  11. List<Element>stringChildList=root.getChildren("string");
  12. for(Elementelement:stringChildList){
  13. StringnameAttrValue=element.getAttribute("name")
  14. .getValue();
  15. if(nameAttrValue.equals(appNameAttrValue)){
  16. element.setText(appNameText);
  17. StringxmlFileData=newXMLOutputter().outputString(document);
  18. //strings.xml默认是UTF-8格式
  19. bos=newOutputStreamWriter(
  20. newFileOutputStream(modifyXmlFile),"UTF-8");
  21. bos.write(xmlFileData);
  22. bos.flush();
  23. System.out.println("Filedoesnotexist");
  24. catch(Exceptionex){
  25. ex.printStackTrace();
  26. finally{
  27. if(bos!=null){
  28. bos.close();
  29. catch(IOExceptione){
  30. }

执行编译和签名命令


我把反编译和签名工具都放在了同一目录,并且事先把基础apk反编译好,现在只需要用代码来执行编译和签名命令就行了。在Java中可以通过 Runtime类来执行DOS命令
copy
    voidcreateApk(StringapkName)throwsIOException,InterruptedException{
  1. Filedir=newFile(wpPath);
  2. //编译命令,其中azbz是基础apk反编译后的文件夹
  3. StringbackCommand="cmd/capktool.batbazbz"+apkName+".apk";
  4. //签名命令
  5. StringsignCommand="cmd/cjava-jarsignapk.jarplatform.x509.pemplatform.pk8"+apkName+".apk"+apkName+"_signed.apk";
  6. //这个命令执行完成会生成一个未签名的apk
  7. RuntimebackR=Runtime.getRuntime();
  8. ProcessbackP=backR.exec(backCommand,153); background-color:inherit; font-weight:bold">null,dir);
  9. //等待执行完再往下执行
  10. backP.waitFor();
  11. //签名apk,这里使用的google提供的证书
  12. RuntimesignR=Runtime.getRuntime();
  13. ProcesssignP=signR.exec(signCommand,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> signP.waitFor();

下面是随手写的一个生成两个icon和名称不同的Apk例子
copy
    classExecDosCommand{
  1. staticStringwpPath_app="E:"+File.separator+"decodeapk"+File.separator+"azbz"+File.separator;
  2. staticStringiconPath=wpPath_app+"res"+File.separator+"drawable-hdpi"+File.separator;
  3. staticStringstringPath=wpPath_app+"res"+File.separator+"values-zh-rCN"+File.separator+"strings.xml";
  4. staticStringmanifestPath=wpPath_app+"AndroidManifest.xml";
  5. staticStringwpPath="E:"+File.separator+"decodeapk"+File.separator;
  6. voidmain(String[]args) AndroidManifestParserparser=newAndroidManifestParser();
  7. AppInfoappInfo=parser.parse(newFileInputStream(manifestPath));
  8. for(inti=0;i<2;i++){
  9. coverIcon(appInfo,i);
  10. modifyAppName(appInfo,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> createApk("修改"+(i+1));
  11. voidmodifyAppName(AppInfoappInfo,inti){
  12. XmlModifyUtil.modifyXML(newFile(stringPath),
  13. appInfo.getAppName(),"修改"+(i+1));
  14. voidcoverIcon(AppInfoappInfo,153); background-color:inherit; font-weight:bold">inti)
  15. throwsFileNotFoundException,IOException{
  16. BufferedOutputStreambos=newBufferedOutputStream(
  17. newFileOutputStream(iconPath+appInfo.getIconName()+".png"));
  18. BufferedInputStreambis=newBufferedInputStream(
  19. newFileInputStream(wpPath+File.separator+"image"+File.separator+"icon"+(i+1)+".png"));
  20. byte[]buffer=newbyte[1024];
  21. inttemp=0;
  22. while((temp=bis.read(buffer))!=-1){
  23. bos.write(buffer,0,temp);
  24. bos.close();
  25. bis.close();
  26. //编译命令
  27. signP.waitFor();
  28. }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读