php上传apk后自动提取apk包信息的使用(示例下载) |
本文标签:提取apk 进入公司第一个项目就是做market市场 。所以后台要上传APK软件之类 。为了方便,上传APK后由系统自动提取APK文件的相关信息,比如:apk包名、产品名称、版本信息、APK Code、程序大小、ICON等 。起初处理方式 通过命令:java -jar AXMLPrinter2.jar AndroidManifest.xml > cmdAfter.xml 但是遗憾的是,从这文件中可以得到apk包名,但无法得到ico图标文件名及其它相关信息 。如下图所示 上图中,比如label、icon等都是标志值,无法直接得到需要的结果 。曾经分析该值与APK文件内部文件的关系,但不同的APK构造不同,实现过于麻烦 。事实上,网上一些安桌市场等网站,当你上传APK时,除了提取出APK包名外,还包括ICON图标、大小等信息 。因此,即然别人可以实现,我想肯定有办法来解决这个事情 。于是经过研究,得到预期结果 。在此将方法做个记录,欢迎交流 。 核心提取APK信息代码复制代码 代码如下: /*** * 分析已上传的APK文件,提取所需要的数据 */ function upAPK(){ global $_config_product_apktool_count;//使用apktool.jar解压的次数,原因下面有说明 。 if($this->msg!=)return;//如果有错误,返回 $dir=$this->upload_path;//上传路径 $stringsXML_exists=false; if(file_exists($dir.package/res/values/strings.xml))unlink($dir.package/res/values/strings.xml); for($i=0;$i<$_config_product_apktool_count && !$stringsXML_exists;$i++){ //针对UC的APK包或其类似的APK包,解压一次并不能完全得到strings.xml文件或相关文件 。目前只有采用这个办法了 。 //在系统cmd下直接使用java -jar ...执行解压,有时可以得到strings.xml文件,有时也得不到,不知道是不是jar包的问题 。 exec(java -jar ../apktool.jar d -f .$this->tmpFile. .$dir.package);//注释:解压完毕再往下执行 $stringsXML_exists=file_exists($dir.package/res/values/strings.xml); } //检查AndroidManifest.xml文件是否存在,如果不存在,则不是合法的APK文件 if(!file_exists($dir.package/AndroidManifest.xml)){$this->msg=不是合法的APK文件,请重新上传!;return;} $AndroidManifestXML=file_get_contents($dir.package/AndroidManifest.xml);//读取AndroidManifest.xml if(preg_match(/package=\"([^\"]*)\"/i,$AndroidManifestXML,$package))$returnVal[package]=$package[1];//如果有包名,返回到数组 //增加versionCode //检测到包名后判断数据库中是否已经存在 。 if($stringsXML_exists)$stringXML=file_get_contents($dir.package/res/values/strings.xml);//如果有strings.xml则读取strings.xml文件 提取信息流程 1、首先,通过apktool.jar命令提取apk文件中package/res/values/string.xml文件 。不知为什么原因,释放apk文件时,有时并不一定得到string.xml文件 。所以,后台增加:$_config_product_apktool_count参数,来控制释放的最大次数 。 2、读取释放根目录下的AndroidManifest.xml文件 。从该文件中可以获取到APK包名、版本信息 。 3、检测,如果是新上传的APK,则其包名在数据库中是否存在 。就是禁止上传相同包名的APK 。修改时不检测 。 4、通过正则获取所需要的信息 。 这里为什么要提取string.xml文件? 因为并不是所有信息,都在AndroidManifest.xml中 。有的信息在AndroidManifest.xml中只是做为一个“引用”,真实记录是在string.xml中的 。比如 AndroidManifest.xml中关于Label和icon的值 。 上图中:label="@string/app_name" 表明在string.xml中string的name属性为app_name的值,即为该APK的“软件名称”,这里是“Market市场”,如下图所示: @drawable/quickflick_icon,表示quickflick_icon为ICON的文件名 。 由于特殊需要,我需要找到最大的ICON图标,见下面代码: 复制代码 代码如下: //遍历package/res目录下的目录[drawable|drawable-hdpi|drawable-nodpi|drawable-ldpi|drawable-mdpi] //系统取icon尺寸最大的图标 $tmpArr[0]=0;$tmpArr[1]=0;$tmpArr[2]=drawable; $dirs=opendir($dir.package/res); while(($file=readdir($dirs))){ preg_match(/(drawable(-.*?dpi)?)/i,$file,$drawable_folder); $iconPath=$dir.package/res/.$drawable_folder[1]./.$returnVal[thumbimg]..png; if(file_exists($iconPath)){ $iconInfo=getimagesize($iconPath); if($iconInfo[0]>$tmpArr[0] && $iconInfo[1]>$tmpArr[1]){ $tmpArr[0]=$iconInfo[0];$tmpArr[1]=$iconInfo[1];$tmpArr[2]=$drawable_folder[1]; } } } //$this->msg=$iconInfo[0].---.$iconInfo[1]; closedir($dirs); 经过分析,一般APK中存放ICON图标在以下几个目录:drawable|drawable-hdpi|drawable-nodpi|drawable-ldpi|drawable-mdpi,通过遍历比较的方式获取最大ICON图标,并移到临时目录 。 将所有需要提取的信息,存到一个数组中,并通过javascript写到表单中 。如下图所示: 提取APK信息总结 上面的代码,目前为止,在提取上传的APK中,能能正常提取信息,未发现错误 。在上面代码的注释中也看到,关于“掌上百度”这款APK,提取不了信息,是由于他的特殊处理方式,即:<string name="app_name">" 掌上百度 "</string>,他在名称中加上了双引号,这算是一个特例了吧 。更多的特例我目前还未发现,所以,有可能会有特例出现,这需要分析APK的数据,并在程序中做特殊处理 。 在实现这个APK提取功能中,关键是要找到APK包的组织规律,只有找到规律,程序实现就是在自然不过的事 。 释放APK文件注意内容 exec(java -jar ../apktool.jar d -f .$this->tmpFile. .$dir.package); 能顺利执行上面的语句,要符合下面条件: 1、安装java包,对java目录,users用户组的权限有:读取和运行、列出文件夹目录、读取 2、cmd.exe文件,users用户组的权限有:读取和运行、读取 3、PHP允许调用exec 4、上传目录要确保有写入文件的权限 如果有更好的提取方式,欢迎交流,相互学习 。 PHP提取APK信息DEMO演示下载 下载地址:http://xiazai.jb51.net/201304/yuanma/php_apk_jb51net.rar |