精华内容
下载资源
问答
  • Java上传apk文件获取版本号 记录一个小优化。 之前做的apk版本更新,是在网页后台中上传apk文件,然后手动输入apk版本号以及更新内容。虽然在填写版本号时做了验证,只能输入数字和小数点,并且第一位不能为小数点...

    Java上传apk文件获取版本号

    记录一个小优化。

    之前做的apk版本更新,是在网页后台中上传apk文件,然后手动输入apk版本号以及更新内容。虽然在填写版本号时做了验证,只能输入数字和小数点,并且第一位不能为小数点等等限制,同时还有一个判断,查询数据库中是否有相同版本的apk。
    在这里插入图片描述
    虽然看起来差不多,该限制的都限制的,该判断的也判断了,但是总觉得好像不太妥。如果我上传的apk版本是1.5,而我在上传手动输入版本号时记错了,写了个1.6。那么用户更新的是名为1.6版本的apk,安装时却发现应用版本是1.5的。虽然听起来没什么太大的影响,但这确实是个隐患。

    那么,我们是否能在上传apk的时候就获取到apk的版本信息呢。做过Android开发的小伙伴应该知道,apk在打包前,版本等信息是写在AndroidManifest.xml中的,那么我们只需要将apk解压,然后找到这个文件,就可以读取到里面的字段和属性了。

    接下来就要请出我们今天的贵宾了:AXMLPrinter2

    AXMLPrinter2.jar官方介绍: AXMLPrinter2.jar apk分析APK文件,取得APK文件中的 包名、版本号及图标,很强大的工具,再一次感受到了批处理的牛逼。可以将android安卓编译过的二进制XML文件(binary xml file)反编译明文输出保存。是APK反编译修改的必备工具之一。例如需要查看apk安装包的权限、名称等,可以用AXMLPrinter2对androidmanifest.xml反编译进行明文查看。反编译速度非常快、好用,可以顺利编译出.XML文件。

    在文章末尾我会附上AXMLPrinter2下载地址
    在这里插入图片描述

    下载完成之后,将jar包添加到项目中去

    之后创建一个ApkUtil工具类,将方法代码写在里面,首先我们要将apk解压,然后找到里面的AndroidManifest.xml文件

    /**
         * 获取apk信息
         *
         * @param apkPath
         * @return
         */
        public static String[] getApkInfo(String apkPath) throws Exception {
            // apk信息的返回结果
            final String[] apkResult = new String[3];
            ZipFile zipFile = null;
            try {
                // 获得一个解压文件对象
                zipFile = new ZipFile(apkPath);
                // 将解压文件对象转列举对象
                final Enumeration enumeration = zipFile.entries();
                ZipEntry zipEntry = null;
                // 遍历列举对象元素
                while (enumeration.hasMoreElements()) {
                    // 获得一个解压条目对象
                    zipEntry = (ZipEntry) enumeration.nextElement();
                    if (zipEntry.isDirectory()) {
     
                    } else {
                        // 获得名为AndroidManifest.xml的文件
                        if ("AndroidManifest.xml".equalsIgnoreCase(zipEntry.getName())) {
    

    找到这个文件之后,遍历里面的内容,找到版本号等相关信息

     // 遍历文件里的内容
      while (true) {
          final int type = parser.next();
          if (type == XmlPullParser.END_DOCUMENT) {
              break;
          }
          switch (type) {
              // 满足条件开始遍历内容提取需要的信息
              case XmlPullParser.START_TAG: {
                  for (int i = 0; i != parser.getAttributeCount(); ++i) {
                      if ("package".equals(parser.getAttributeName(i))) {//包名
                          apkResult[0] = ApkUtil.getAttributeValue(parser, i);
                      } else if ("versionCode".equals(parser.getAttributeName(i))) {//版本码
                          apkResult[1] = ApkUtil.getAttributeValue(parser, i);
                      } else if ("versionName".equals(parser.getAttributeName(i))) {//版本号
                          apkResult[2] = ApkUtil.getAttributeValue(parser, i);
                      }
    
                  }
              }
    

    这样就得到的apk的版本号相关信息了

    下面附上完整的ApkUtil:

    import android.content.res.AXmlResourceParser;
    import android.util.TypedValue;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.xmlpull.v1.XmlPullParser;
     
    import java.io.IOException;
    import java.util.Enumeration;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;
    
    
    public class ApkUtil {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(ApkUtil.class);
     
        private static final float RADIX_MULTS[] = {0.00390625F, 3.051758E-005F, 1.192093E-007F, 4.656613E-010F};
     
        private static final String DIMENSION_UNITS[] = {"px", "dip", "sp", "pt", "in", "mm", "", ""};
     
        private static final String FRACTION_UNITS[] = {"%", "%p", "", "", "", "", "", ""};
     
        /**
         * 获取apk信息
         *
         * @param apkPath
         * @return
         */
        public static String[] getApkInfo(String apkPath) throws Exception {
            // apk信息的返回结果
            final String[] apkResult = new String[3];
            ZipFile zipFile = null;
            try {
                // 获得一个解压文件对象
                zipFile = new ZipFile(apkPath);
                // 将解压文件对象转列举对象
                final Enumeration enumeration = zipFile.entries();
                ZipEntry zipEntry = null;
                // 遍历列举对象元素
                while (enumeration.hasMoreElements()) {
                    // 获得一个解压条目对象
                    zipEntry = (ZipEntry) enumeration.nextElement();
                    if (zipEntry.isDirectory()) {
     
                    } else {
                        // 获得名为AndroidManifest.xml的文件
                        if ("AndroidManifest.xml".equalsIgnoreCase(zipEntry.getName())) {
                            final AXmlResourceParser parser = new AXmlResourceParser();
                            parser.open(zipFile.getInputStream(zipEntry));
                            // 遍历文件里的内容
                            while (true) {
                                final int type = parser.next();
                                if (type == XmlPullParser.END_DOCUMENT) {
                                    break;
                                }
                                switch (type) {
                                    // 满足条件开始遍历内容提取需要的信息
                                    case XmlPullParser.START_TAG: {
                                        for (int i = 0; i != parser.getAttributeCount(); ++i) {
                                            if ("package".equals(parser.getAttributeName(i))) {
                                                apkResult[0] = ApkUtil.getAttributeValue(parser, i);
                                            } else if ("versionCode".equals(parser.getAttributeName(i))) {
                                                apkResult[1] = ApkUtil.getAttributeValue(parser, i);
                                            } else if ("versionName".equals(parser.getAttributeName(i))) {
                                                apkResult[2] = ApkUtil.getAttributeValue(parser, i);
                                            }
     
                                        }
                                    }
                                }
                            }
                        }
     
                    }
                }
            } finally {
                if (zipFile != null) {
                    try {
                        zipFile.close();
                    } catch (final IOException e) {
                        LOGGER.error("Zipfile close fail.", e);
                    }
                }
            }
     
            return apkResult;
        }
     
        private static String getAttributeValue(AXmlResourceParser parser, int index) {
            final int type = parser.getAttributeValueType(index);
            final int data = parser.getAttributeValueData(index);
            if (type == TypedValue.TYPE_STRING) {
                return parser.getAttributeValue(index);
            }
            if (type == TypedValue.TYPE_ATTRIBUTE) {
                return String.format("?%s%08X", ApkUtil.getPackage(data), data);
            }
            if (type == TypedValue.TYPE_REFERENCE) {
                return String.format("@%s%08X", ApkUtil.getPackage(data), data);
            }
            if (type == TypedValue.TYPE_FLOAT) {
                return String.valueOf(Float.intBitsToFloat(data));
            }
            if (type == TypedValue.TYPE_INT_HEX) {
                return String.format("0x%08X", data);
            }
            if (type == TypedValue.TYPE_INT_BOOLEAN) {
                return data != 0 ? "true" : "false";
            }
            if (type == TypedValue.TYPE_DIMENSION) {
                return Float.toString(ApkUtil.complexToFloat(data))
                        + ApkUtil.DIMENSION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
            }
            if (type == TypedValue.TYPE_FRACTION) {
                return Float.toString(ApkUtil.complexToFloat(data))
                        + ApkUtil.FRACTION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
            }
            if (type >= TypedValue.TYPE_FIRST_COLOR_INT && type <= TypedValue.TYPE_LAST_COLOR_INT) {
                return String.format("#%08X", data);
            }
            if (type >= TypedValue.TYPE_FIRST_INT && type <= TypedValue.TYPE_LAST_INT) {
                return String.valueOf(data);
            }
            return String.format("<0x%X, type 0x%02X>", data, type);
        }
     
        private static String getPackage(int id) {
            if (id >>> 24 == 1) {
                return "android:";
            }
            return "";
        }
     
        public static float complexToFloat(int complex) {
            return (complex & 0xFFFFFF00) * ApkUtil.RADIX_MULTS[complex >> 4 & 3];
        }
    }
    
    

    给大佬们呈上AXMLPrinter2.jar 下载地址

    最后感谢 Mr_EvanChen大佬 写的 ApkUtil,我只是个代码搬运渣渣

    大佬的 原文链接

    展开全文
  • java 如何根据别人提供的util工具类,点击上传apk文件时,版本号就自动显示出来 ,不需要再手动输入,如何写
  • java文件上传

    2018-03-27 14:23:08
    java 使用 spring 实现文件上传,包括图片、APK文件
  • java通过上传文件的方式,根据文件APK来获取应用apk的包名,版本号等信息。全部封闭成名,操作起来非常的方便,如有疑问可以在下面留言!
  • 在做一个Java项目,要上传APK文件,哪位大神知道那种可以自动解析APK文件的上传控件啊?
  • 完整版java读取apk、ipa包名、版本名、版本号等信息

    万次阅读 热门讨论 2016-05-06 11:14:28
    有时候,我们上传apk或者是ipa文件的时候,是需要读取到里面的一些信息的,比如软件的包名,以及其版本信息等。在网上搜索了一下资料 , 找了很多版本,对于apk文件的版本号,一直读取不到,在这里,笔者自己总结了...

    有时候,我们上传apk或者是ipa文件的时候,是需要读取到里面的一些信息的,比如软件的包名,以及其版本信息等。在网上搜索了一下资料 , 找了很多版本,对于apk文件的版本号,一直读取不到,在这里,笔者自己总结了,读取apk、ipa文件的一些代码,大家可以参考下,去其糟粕,取其精华。以便适用于自己的需求。

    如果大家希望解析到图标的话,可以看我后面写的博文
    博文地址请戳 :

    Java解析apk、ipa图标,包名,应用名称,版本号

    下面会提供源码给大家,我用的开发工具是eclipse,直接导入就可以,jar包也是我已经下载好的,大家可以免积分拿去。本来里面是有2个apk、2个ipa文件提供测试的,但是由于文件太大,上传不了源码,所以就删除了一个最大的ipa包

    apk jar包地址:java解析apk所需jar包下载
    ipa jar包地址:java解析ipa所需jar包下载

    首先看一下我的项目目录
    这里写图片描述

    下面请看代码

    package com.zsl.cn;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;
    import java.util.zip.ZipInputStream;
    
    import org.apkinfo.api.util.AXmlResourceParser;
    import org.apkinfo.api.util.TypedValue;
    import org.apkinfo.api.util.XmlPullParser;
    
    import com.dd.plist.NSDictionary;
    import com.dd.plist.NSString;
    import com.dd.plist.PropertyListParser;
    /**
     * 
     * @author ZSL
     *
     */
    public final class ReadUtil {
    	/**
    	 * 读取apk
    	 * @param apkUrl
    	 * @return
    	 */
    	public static Map<String,Object> readAPK(String apkUrl){
    		ZipFile zipFile;
    		Map<String,Object> map = new HashMap<String, Object>();
    		try {
    			zipFile = new ZipFile(apkUrl);
    			Enumeration<?> enumeration = zipFile.entries();
    			ZipEntry zipEntry = null;
    			while (enumeration.hasMoreElements()) {
    				zipEntry = (ZipEntry) enumeration.nextElement();
    				if (zipEntry.isDirectory()) {
    
    				} else {
    					if ("androidmanifest.xml".equals(zipEntry.getName().toLowerCase())) {
    						AXmlResourceParser parser = new AXmlResourceParser();
    						parser.open(zipFile.getInputStream(zipEntry));
    						while (true) {
    							int type = parser.next();
    							if (type == XmlPullParser.END_DOCUMENT) {
    								break;
    							}
    							String name = parser.getName();
    							if(null != name && name.toLowerCase().equals("manifest")){
    								for (int i = 0; i != parser.getAttributeCount(); i++) {
    									if ("versionName".equals(parser.getAttributeName(i))) {
    										String versionName = getAttributeValue(parser, i);
    										if(null == versionName){
    											versionName = "";
    										}
    										map.put("versionName", versionName);
    									} else if ("package".equals(parser.getAttributeName(i))) {
    										String packageName = getAttributeValue(parser, i);
    										if(null == packageName){
    											packageName = "";
    										}
    										map.put("package", packageName);
    									} else if("versionCode".equals(parser.getAttributeName(i))){
    										String versionCode = getAttributeValue(parser, i);
    										if(null == versionCode){
    											versionCode = "";
    										}
    										map.put("versionCode", versionCode);
    									}
    								}
    								break;
    							}
    						}
    					}
    					
    				}
    			}
    			zipFile.close();
    		} catch (Exception e) {
    			map.put("code", "fail");
    			map.put("error","读取apk失败");
    		}
    		return map;
    	}
    	
    	private static String getAttributeValue(AXmlResourceParser parser, int index) {
    		int type = parser.getAttributeValueType(index);
    		int data = parser.getAttributeValueData(index);
    		if (type == TypedValue.TYPE_STRING) {
    			return parser.getAttributeValue(index);
    		}
    		if (type == TypedValue.TYPE_ATTRIBUTE) {
    			return String.format("?%s%08X", getPackage(data), data);
    		}
    		if (type == TypedValue.TYPE_REFERENCE) {
    			return String.format("@%s%08X", getPackage(data), data);
    		}
    		if (type == TypedValue.TYPE_FLOAT) {
    			return String.valueOf(Float.intBitsToFloat(data));
    		}
    		if (type == TypedValue.TYPE_INT_HEX) {
    			return String.format("0x%08X", data);
    		}
    		if (type == TypedValue.TYPE_INT_BOOLEAN) {
    			return data != 0 ? "true" : "false";
    		}
    		if (type == TypedValue.TYPE_DIMENSION) {
    			return Float.toString(complexToFloat(data)) + DIMENSION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
    		}
    		if (type == TypedValue.TYPE_FRACTION) {
    			return Float.toString(complexToFloat(data)) + FRACTION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
    		}
    		if (type >= TypedValue.TYPE_FIRST_COLOR_INT && type <= TypedValue.TYPE_LAST_COLOR_INT) {
    			return String.format("#%08X", data);
    		}
    		if (type >= TypedValue.TYPE_FIRST_INT && type <= TypedValue.TYPE_LAST_INT) {
    			return String.valueOf(data);
    		}
    		return String.format("<0x%X, type 0x%02X>", data, type);
    	}
    
    	private static String getPackage(int id) {
    		if (id >>> 24 == 1) {
    			return "android:";
    		}
    		return "";
    	}
    
    	// / ILLEGAL STUFF, DONT LOOK :)
    	public static float complexToFloat(int complex) {
    		return (float) (complex & 0xFFFFFF00) * RADIX_MULTS[(complex >> 4) & 3];
    	}
    
    	private static final float RADIX_MULTS[] = 
    	{
    		 0.00390625F, 3.051758E-005F, 
    		 1.192093E-007F, 4.656613E-010F 
    	 };
    	private static final String DIMENSION_UNITS[] = { "px", "dip", "sp", "pt", "in", "mm", "", "" };
    	private static final String FRACTION_UNITS[] = { "%", "%p", "", "", "", "", "", "" };
    	
    	/**
    	 * 读取ipa
    	 */
    	public static Map<String,Object> readIPA(String ipaURL){
    		Map<String,Object> map = new HashMap<String,Object>();
    		try {
    			File file = new File(ipaURL);
                InputStream is = new FileInputStream(file);
                InputStream is2 = new FileInputStream(file);
                ZipInputStream zipIns = new ZipInputStream(is);
                ZipInputStream zipIns2 = new ZipInputStream(is2);
                ZipEntry ze;
                ZipEntry ze2;
                InputStream infoIs = null;
                NSDictionary rootDict = null;
                String icon = null;
                while ((ze = zipIns.getNextEntry()) != null) {
                    if (!ze.isDirectory()) {
                        String name = ze.getName();
                        if (null != name &&
                         name.toLowerCase().contains(".app/info.plist")) {
                            ByteArrayOutputStream _copy = new 
    			                        ByteArrayOutputStream();
                            int chunk = 0;
                            byte[] data = new byte[1024];
                            while(-1!=(chunk=zipIns.read(data))){
                                _copy.write(data, 0, chunk);
                            }
                            infoIs = new ByteArrayInputStream(_copy.toByteArray());
                            rootDict = (NSDictionary) PropertyListParser.parse(infoIs);
                            
                            //我们可以根据info.plist结构获取任意我们需要的东西
                            //比如下面我获取图标名称,图标的目录结构请下面图片
                            //获取图标名称
                            NSDictionary iconDict = (NSDictionary) rootDict.get("CFBundleIcons");
                             
                            while (null != iconDict) {
                				if(iconDict.containsKey("CFBundlePrimaryIcon")){
    			            	NSDictionary CFBundlePrimaryIcon = (NSDictionary)iconDict.get("CFBundlePrimaryIcon"); 
                					if(CFBundlePrimaryIcon.containsKey("CFBundleIconFiles")){
    	            				NSArray CFBundleIconFiles =(NSArray)CFBundlePrimaryIcon.get("CFBundleIconFiles"); 
                					icon = CFBundleIconFiles.getArray()[0].toString();
                						if(icon.contains(".png")){
                							icon = icon.replace(".png", "");
                						}
                						System.out.println("获取icon名称:" + icon);
                						break;
                					}
                				}
                			}
                            break;
                        }
                    }
                }
               
               //根据图标名称下载图标文件到指定位置
                while ((ze2 = zipIns2.getNextEntry()) != null) {
                    if (!ze2.isDirectory()) {
                        String name = ze2.getName();
                        System.out.println(name);
                        if(name.contains(icon.trim())){
                        	System.out.println(11111);
                        	FileOutputStream fos = new FileOutputStream(new File("E:\\python\\img\\icon.png"));
    	                       int chunk = 0;
    	                       byte[] data = new byte[1024];
    	                       while(-1!=(chunk=zipIns2.read(data))){
    	                    	   fos.write(data, 0, chunk);
    	                       }
    	                       fos.close();
                        	break;
                        }
                    }
                }
    	         
                
                //如果想要查看有哪些key ,可以把下面注释放开
    //            for (String keyName : rootDict.allKeys()) {
    //				System.out.println(keyName + ":" + rootDict.get(keyName).toString());
    //			  }
               
               
                // 应用包名
        		NSString parameters = (NSString) rootDict.get("CFBundleIdentifier");
        		map.put("package", parameters.toString());
        		// 应用版本名
        		parameters = (NSString) rootDict.objectForKey("CFBundleShortVersionString");
        		map.put("versionName", parameters.toString());
        		//应用版本号
        		parameters = (NSString) rootDict.get("CFBundleVersion");
        		map.put("versionCode", parameters.toString());
        		
                /
    			infoIs.close();
    	        is.close();
                zipIns.close();
                
            } catch (Exception e) {
            	map.put("code", "fail");
                map.put("error","读取ipa文件失败");
            }
            return map;
    	}
    	
    	
    	public static void main(String[] args) {
    		System.out.println("======apk=========");
    		String apkUrl = "src/shenmiaotaowang_966.apk";
    		Map<String,Object> mapApk = ReadUtil.readAPK(apkUrl);
    		for (String key : mapApk.keySet()) {
    			System.out.println(key + ":" + mapApk.get(key));
    		}
    		System.out.println("======ipa==========");
    		String ipaUrl = "src/IM.ipa";
    		Map<String,Object> mapIpa = ReadUtil.readIPA(ipaUrl);
    		for (String key : mapIpa.keySet()) {
    			System.out.println(key + ":" + mapIpa.get(key));
    		}
    	}
    }
    
    

    这里写图片描述

    下面附上源码一份:java读取apk、ipa源码完整版

    总结:对于ipa文件的解析,我们可以根据info.plist文件结构进行解析,获取我们需要的值,如果我们key对应的是dict ,那么我们就用NSDictionary来获取,如果是key下面是array,那么我们就用NSArray来获取,这时获取到的是一个数组。
    这里写图片描述
    这里写图片描述
    这里写图片描述




    我们可以看到上面解析到的图片是黑色的,这个确实是这样子的,在window或者linux下都是黑色的,只有在mac下才是正常的,应该是ios开发者压缩的结果。不过不要担心,可以看后面的文章,怎么把图片反编译成正常图片。




    补充:

    1. 2016-9-14补充获取ipa图标,并下载到指定位置

    如果大家希望解析到图标的话,可以看我后面写的博文
    博文地址请戳 :

    Java解析apk、ipa图标,包名,应用名称,版本号







    展开全文
  • java】项目读取APK文件和IPA文件的版本信息

    千次阅读 热门讨论 2018-04-29 20:04:45
    在公司项目中,在做版本管理的时候,遇到了需要识别被管理的APK(安卓应用包)和IPA(苹果应用包)的情况,需要在上传的时候识别并导入包的一些信息到数据库中,并作出管理。 一、如何识别信息 在我开始研究这个的解决...

            在公司项目中,在做版本管理的时候,遇到了需要识别被管理的APK(安卓应用包)和IPA(苹果应用包)的情况,需要在上传的时候识别并导入包的一些信息到数据库中,并作出管理。

     

    一、如何识别信息


            在我开始研究这个的解决方法的时候,同事告诉我,网上有现成的工具类,可以直接读取各种安装包的信息。于是上网搜索了一下,果然解决方案很多,先不说优劣,从解决的思路上来,可以发现,他们的解决方法都是千篇一律的。

            和众多的项目一样,在苹果和安卓的项目中,也有很多的版本信息,那么这些都存储在哪里了呢?在每个我们打好的包里面,其实都有一个专门标注版本信息和版权,描述的文件,如果我们用winrar或者其他解压缩软件把安装包解压缩之后,我们可以得到里面的很多信息,然后一般我们都会在软件的最外层发现一个.xml的文件来看到我们的版本信息(一般都有加密)。

            所以我们获得版本信息的来源就是要从安装包中提取xml的文件,然后通过解析xml文件中的特殊节点来获得我们所需要的信息。具体思路就是  解包(类似zip)->读取文件->把信息放入构造的实体中->从实体中获得数据

            因为各种版本的安卓应用所用的AndroidStudio和SDK都是不同的,所以我们在解析的时候也会有稍许的不同,好在有兼容的存在,还有对于各种版本的识别网上都有处理。


    二、开始动手


            我们在开始之前首先需要引入两个jar包,分别是dd-plist-1.16.jar(ios的识别)和apk-parser-2.5.3.jar(安卓的识别)

    下载地址:https://download.csdn.net/download/tr1912/10383172

    我们在引入jar包的时候直接放入lib文件夹中就可以了。maven的话需要先上传到中央仓库去才能挂载。

    然后新建一个工具类叫APKUtil,然后粘入如下代码:

    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    
    import net.dongliu.apk.parser.ApkFile;
    import net.dongliu.apk.parser.bean.ApkMeta;
    import net.dongliu.apk.parser.bean.UseFeature;
      
    public class APKUtil {
        public static void main(String[] arg){
    	String filePath = "D:\\apk\\farmClient.apk";
    
            try (ApkFile apkFile = new ApkFile(new File(filePath))) {
                ApkMeta apkMeta = apkFile.getApkMeta();
                System.out.println(apkMeta.getName());
                System.out.println(apkMeta.getPackageName());
                System.out.println(apkMeta.getVersionCode());
                System.out.println(apkMeta.getVersionName());
                for (UseFeature feature : apkMeta.getUsesFeatures()) {
                    System.out.println(feature.getName());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }                       
        }
    	
        /**
        * 获取APK信息-王啸-2018年4月18日13:05:52
        * @param apkUrl
        * @return
        */
        public static Map<String,Object> readApk(String apkUrl){
    	Map<String,Object> resMap=new HashMap<String,Object>();
    	try (ApkFile apkFile = new ApkFile(new File(apkUrl))) {
                ApkMeta apkMeta = apkFile.getApkMeta();
                resMap.put("versionCode", apkMeta.getVersionCode());
                resMap.put("versionName", apkMeta.getVersionName());      
                for (UseFeature feature : apkMeta.getUsesFeatures()) {
                    System.out.println(feature.getName());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return resMap;
        }
    }

    其中filePath为我们放apk文件的路径,然后直接运行,我们就可以看到我们想要看的版本信息:

    上图是我识别了一个qq的安装apk的样子。

    ipa文件同理,也是引入jar包后,写入如下代码:

    /**
     * 读取ipa
     */
    public static Map<String,Object> readIPA(String ipaURL){
        Map<String,Object> map = new HashMap<String,Object>();
        try {
            File file = new File(ipaURL);
            InputStream is = new FileInputStream(file);
            InputStream is2 = new FileInputStream(file);
            ZipInputStream zipIns = new ZipInputStream(is);
            ZipInputStream zipIns2 = new ZipInputStream(is2);
            ZipEntry ze;
            ZipEntry ze2;
            InputStream infoIs = null;
            NSDictionary rootDict = null;
            String icon = null;
            while ((ze = zipIns.getNextEntry()) != null) {
                if (!ze.isDirectory()) {
                    String name = ze.getName();
                    if (null != name &&
                     name.toLowerCase().contains(".app/info.plist")) {
                        ByteArrayOutputStream _copy = new 
                                    ByteArrayOutputStream();
                        int chunk = 0;
                        byte[] data = new byte[1024];
                        while(-1!=(chunk=zipIns.read(data))){
                            _copy.write(data, 0, chunk);
                        }
                        infoIs = new ByteArrayInputStream(_copy.toByteArray());
                        rootDict = (NSDictionary) PropertyListParser.parse(infoIs);
    
                        //我们可以根据info.plist结构获取任意我们需要的东西
                        //比如下面我获取图标名称,图标的目录结构请下面图片
                        //获取图标名称
                        NSDictionary iconDict = (NSDictionary) rootDict.get("CFBundleIcons");
    
                        while (null != iconDict) {
                            if(iconDict.containsKey("CFBundlePrimaryIcon")){
                            NSDictionary CFBundlePrimaryIcon = (NSDictionary)iconDict.get("CFBundlePrimaryIcon"); 
                                if(CFBundlePrimaryIcon.containsKey("CFBundleIconFiles")){
                                NSArray CFBundleIconFiles =(NSArray)CFBundlePrimaryIcon.get("CFBundleIconFiles"); 
                                icon = CFBundleIconFiles.getArray()[0].toString();
                                    if(icon.contains(".png")){
                                        icon = icon.replace(".png", "");
                                    }
                                    System.out.println("获取icon名称:" + icon);
                                    break;
                                }
                            }
                        }
                        break;
                    }
                }
            }
    
           //根据图标名称下载图标文件到指定位置
            while ((ze2 = zipIns2.getNextEntry()) != null) {
                if (!ze2.isDirectory()) {
                    String name = ze2.getName();
                    System.out.println(name);
                    if(name.contains(icon.trim())){
                        System.out.println(11111);
                        FileOutputStream fos = new FileOutputStream(new File("E:\\img\\icon.png"));
                           int chunk = 0;
                           byte[] data = new byte[1024];
                           while(-1!=(chunk=zipIns2.read(data))){
                               fos.write(data, 0, chunk);
                           }
                           fos.close();
                        break;
                    }
                }
            }
    
            
            //如果想要查看有哪些key ,可以把下面注释放开
    //      for (String keyName : rootDict.allKeys()) {
    //          System.out.println(keyName + ":" + rootDict.get(keyName).toString());
    //      }
    
    
            // 应用包名
            NSString parameters = (NSString) rootDict.get("CFBundleIdentifier");
            map.put("package", parameters.toString());
            // 应用版本名
            parameters = (NSString) rootDict.objectForKey("CFBundleShortVersionString");
            map.put("versionName", parameters.toString());
            //应用版本号
            parameters = (NSString) rootDict.get("CFBundleVersion");
            map.put("versionCode", parameters.toString());
    
            /
            infoIs.close();
            is.close();
            zipIns.close();
    
        } catch (Exception e) {
            map.put("code", "fail");
            map.put("error","读取ipa文件失败");
        }
        return map;
    }

    main中的测试代码:

    System.out.println("======ipa==========");
    String ipaUrl = "D:\\apk\\PastureRecreation.ipa";
    Map<String,Object> mapIpa = APKUtil.readIPA(ipaUrl);
    for (String key : mapIpa.keySet()) {
        System.out.println(key + ":" + mapIpa.get(key));
    }

    ipa的文件比较复杂,但是也能解析出来很多信息的,由于信息差不多,所以不再演示,自己体会去吧。

    另外ios的包能解析出来应用的图标,大家可以尝试一下。

    展开全文
  • 解析apk方法 1、apktool cmd解析 2、解压apk,...本示例是上传时,把APK解压,遍历文件,如果是AndroidManifest.xml文件就取里面的值 参考这这里,源码和jar可以从这里下载https://chensl.iteye.com/blog/217429...

    解析apk方法
    1、apktool cmd解析
    2、解压apk,读取AndroidManifest.xml获取版本信息
    因为第一种太麻烦了,要部署到docker麻烦,选用了第二种

    本示例是上传时,把APK解压,遍历文件,如果是AndroidManifest.xml文件就取里面的值

     

    参考这这里,源码和jar可以从这里下载
    https://chensl.iteye.com/blog/2174290

     

     public String savePackage(CommonsMultipartFile file, Long pkVersion) throws Exception {
            if (file == null) {
                throw new RuntimeException("上传的文件为空,请重新上传!");
            }
            byte[] uploadBytes = file.getBytes();
    
            // 获取包信息apk信息的返回结果
            String[] apkResult = new String[3];
            ZipInputStream zs = new ZipInputStream(file.getInputStream());
            BufferedInputStream bs = new BufferedInputStream(zs);
            ZipEntry zipEntry;
            while ((zipEntry = zs.getNextEntry()) != null) {
                if (zipEntry.isDirectory()) {
                    continue;
                }
                byte[] bytes = null;
                if ("androidmanifest.xml".equals(zipEntry.getName().toLowerCase())) {
                    bytes = new byte[(int) zipEntry.getSize()];
                    bs.read(bytes, 0, (int) zipEntry.getSize());
                    InputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
                    apkResult = AXMLPrinter.getApkInfo(byteArrayInputStream);
    
                }
    
            }
    
            bs.close();
            zs.close();
            if (StringUtils.isBlank(apkResult[0])) {
                throw new RuntimeException("未获取包名,请检测包");
            }
    
            //end包
            //get包名
            String pkPackage=apkResult[0];
            String fileName = file.getOriginalFilename();
            String fileSuffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
            PackageVer fileInfoModel = new PackageVer();
            fileInfoModel.setPkName(fileName);
            fileInfoModel.setPkSize(file.getSize());
            fileInfoModel.setPkVersion(pkVersion);
            fileInfoModel.setPkPackage(pkPackage);
    
    
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] digest = md5.digest(uploadBytes);
            String hashString = new BigInteger(1, digest).toString(16);
            fileInfoModel.setPkMd5(hashString);
            String fileId = fastDfsService.uploadPicFile(uploadBytes, fileSuffix);
            logger.info("uploadPicFile result={}", fileId);
    
            fileInfoModel.setPkUrl(fileUrlPrefix + "/" + fileId);
            fileInfoModel.setFileid(fileId);
            packageVerBiz.add(fileInfoModel);
            return "SUCCESS";
    
        }

     

     public static String[] getApkInfo(InputStream fileInputStream) throws Exception {
    
            final String[] apkResult = new String[3];
    
                AXmlResourceParser parser = new AXmlResourceParser();
                parser.open(fileInputStream);
                while (true) {
                    int type = parser.next();
                    if (type == XmlPullParser.END_DOCUMENT) {
                        break;
                    }
                    switch (type) {
    
                        case XmlPullParser.START_TAG: {
                            for (int i = 0; i != parser.getAttributeCount(); ++i) {
                                if ("package".equals(parser.getAttributeName(i))) {
                                    apkResult[0] = getAttributeValue(parser, i);
                                } else if ("versionCode".equals(parser.getAttributeName(i))) {
                                    apkResult[1] = getAttributeValue(parser, i);
                                } else if ("versionName".equals(parser.getAttributeName(i))) {
                                    apkResult[2] = getAttributeValue(parser, i);
                                }
                            }
                            break;
                        }
                        default:
                    }
    
                }
    
            return apkResult;
    
        }

     

    转载于:https://www.cnblogs.com/Guroer/p/11134583.html

    展开全文
  • java语言写的android照相机,有wifi实时传输功能,内含源代码以及apk文件.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • PHP上传apk后自动提取apk包的信息

    千次阅读 2013-11-21 15:40:28
    为了方便,上传APK后由系统自动提取APK文件的相关信息,比如:apk包名、产品名称、版本信息、APK Code、程序大小、ICON等。 起初处理方式 通过命令:java -jar AXMLPrinter2.jar AndroidManifest.xml > cmdAfter....
  • 为了方便,上传APK后由系统自动提取APK文件的相关信息,比如:apk包名、产品名称、版本信息、APK Code、程序大小、ICON等。起初处理方式 通过命令:java -jar AXMLPrinter2.jar AndroidManifest.xml > cmdAfter.xml...
  • 3. Java 解析 apk 文件 (Android 应用包) 4. 自己上传 app 到服务器,模拟蒲公英的效果 关于蒲公英的思考蒲公英的作用(在工作中) 在我的实际工作中,蒲公英主要用于企业包(In-House证书打的包)的分发,方便 QA
  • package com.ztj.common; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration;
  • 为了方便,上传APK后由系统自动提取APK文件的相关信息,比如:apk包名、产品名称、版本信息、APK Code、程序大小、ICON等。 起初处理方式 通过命令:java -jar AXMLPrinter2.jar AndroidManifest.xml > cmdAfter...
  • package com.ztj.common; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import
  • Android APK文件结构

    2014-05-29 17:29:13
    APK文件结构说明 AndroidManifest.xml  该文件是每个应用都必须定义和包含的,它描述了应用的名字、版本、权限、引用的库文件等等信息,如要把apk上传到Google Market上,也要对这个xml做一些配置。在apk中的...
  • 当我们上传apk或者ipa文件的时候是要读取到里面的一些信息的,而对于未知的apk或者ipa,我们无法直接获取其中的包名、应用名、图标等,这时候通过工具类来获取信息就很有必要了。在这里,我总结了一下读取apk,ipa...
  • 当我们上传apk或者ipa文件的时候是要读取到里面的一些信息的,而对于未知的apk或者ipa,我们无法直接获取其中的包名、应用名、图标等,这时候通过工具类来获取信息就很有必要了。在这里,我总结了一下读取apk,ipa...
  • 运行环境: 1、安装JDK 2、安装Android SDK 建议:添加JDK、SDK的环境变量,...(判断JDK是否安装好,请输入java -version,如果能返回java的版本信息,则安装成功) (判断Android是否安装好,请输入An...
  • 文件上传的方式有很多种,我自己常用的就是用流来上传,下面的例子是上传安卓打包的apk文件,有要采用该方法的小伙伴可以根据自己的业务逻辑去操作修改。 以前一直是在使用,这次顺了一下思路,记录下来,以后长...
  • Java中实现文件的跨服务器上传

    万次阅读 2017-04-10 15:37:32
    显然,把大到几百M的apk文件存到数据库不现实,查了半天,在两端建立ftp服务器传文件是最快的方法。 具体流程是,用户登录外网客户端,上传文件到外网的服务器硬盘上,在此同时,文件通过外网服务器访问内网管理员...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 160
精华内容 64
关键字:

java上传apk文件

java 订阅