php上傳apk后自動(dòng)提取apk包信息的使用(示例下載)
通過(guò)命令:java -jar AXMLPrinter2.jar AndroidManifest.xml > cmdAfter.xml
得到cmdAfter.xml文件,然后分析cmdAfter.xml文件獲取相關(guān)信息。
但是遺憾的是,從這文件中可以得到apk包名,但無(wú)法得到ico圖標(biāo)文件名及其它相關(guān)信息。如下圖所示

上圖中,比如label、icon等都是標(biāo)志值,無(wú)法直接得到需要的結(jié)果。曾經(jīng)分析該值與APK文件內(nèi)部文件的關(guān)系,但不同的APK構(gòu)造不同,實(shí)現(xiàn)過(guò)于麻煩。事實(shí)上,網(wǎng)上一些安桌市場(chǎng)等網(wǎng)站,當(dāng)你上傳APK時(shí),除了提取出APK包名外,還包括ICON圖標(biāo)、大小等信息。因此,即然別人可以實(shí)現(xiàn),我想肯定有辦法來(lái)解決這個(gè)事情。于是經(jīng)過(guò)研究,得到預(yù)期結(jié)果。在此將方法做個(gè)記錄,歡迎交流。
核心提取APK信息代碼/***
* 分析已上傳的APK文件,提取所需要的數(shù)據(jù)
*/
function upAPK(){
global $_config_product_apktool_count;//使用apktool.jar解壓的次數(shù),原因下面有說(shuō)明。
if($this->msg!='')return;//如果有錯(cuò)誤,返回
$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++){
//針對(duì)UC的APK包或其類似的APK包,解壓一次并不能完全得到strings.xml文件或相關(guān)文件。目前只有采用這個(gè)辦法了。
//在系統(tǒng)cmd下直接使用java -jar ...執(zhí)行解壓,有時(shí)可以得到strings.xml文件,有時(shí)也得不到,不知道是不是jar包的問(wèn)題。
exec('java -jar ../apktool.jar d -f '.$this->tmpFile.' '.$dir.'package');//注釋:解壓完畢再往下執(zhí)行
$stringsXML_exists=file_exists($dir.'package/res/values/strings.xml');
}
//檢查AndroidManifest.xml文件是否存在,如果不存在,則不是合法的APK文件
if(!file_exists($dir.'package/AndroidManifest.xml')){$this->msg='不是合法的APK文件,請(qǐng)重新上傳!';return;}
$AndroidManifestXML=file_get_contents($dir.'package/AndroidManifest.xml');//讀取AndroidManifest.xml
if(preg_match('/package=\"([^\"]*)\"/i',$AndroidManifestXML,$package))$returnVal['package']=$package[1];//如果有包名,返回到數(shù)組
//增加versionCode
if(preg_match('/versionCode=\"([^\"]*)\"/i',$AndroidManifestXML,$versionCode))$returnVal['versionCode']=$versionCode[1];//如果有版本代碼,返回到數(shù)組
//檢測(cè)到包名后判斷數(shù)據(jù)庫(kù)中是否已經(jīng)存在。
if($this->id==0){//添加新產(chǎn)品時(shí)檢測(cè),修改產(chǎn)品不檢測(cè)
if($returnVal['package']!=''){
$sql='select id from product where package='.SqlEncode($package[1]);
$result=mysql_query($sql);
if(mysql_num_rows($result)>0){
$this->msg='該APK已經(jīng)存在,請(qǐng)更換!';
return;
}
}else{
$this->msg='系統(tǒng)無(wú)法檢測(cè)該APK信息,請(qǐng)聯(lián)系管理員!';
return;
}
}
if($stringsXML_exists)$stringXML=file_get_contents($dir.'package/res/values/strings.xml');//如果有strings.xml則讀取strings.xml文件
if(preg_match('/versionName=\"([^\"]*)\"/i',$AndroidManifestXML,$ver))$returnVal['ver']=$ver[1];//如果有版本號(hào),返回到數(shù)組
//版本號(hào)的情況目前發(fā)現(xiàn)有兩種:1、版本號(hào)在AndroidManifest.xml中直接列出;通過(guò)以上正則即可提取
//2、版本號(hào)同label一樣,放到strings.xml文件中
//2011-11-23 add
if($stringXML!='' && strstr($ver[1],'@')){
if(preg_match('/^@string\/(.*)/i',$ver[1],$findVer)){
if(preg_match('/<string name=\"'.$findVer[1].'\">([^<]*)<\/string>/',$stringXML,$a))$returnVal['ver']=$a[1];
}
}
////////////////////////////////////////////
if(preg_match('/<application[\s\S]*? android:icon="@drawable\/([^"]*)"/i',$AndroidManifestXML,$icon))$returnVal['thumbimg']=$icon[1];//如果有圖標(biāo),返回到數(shù)組
if($stringsXML_exists && preg_match('/<application[\s\S]*? android:label="@string\/([^"]*)"/i',$AndroidManifestXML,$label)){
if(preg_match('/<string name=\"'.$label[1].'\">([^<]*)<\/string>/',$stringXML,$name)){
$returnVal['name']=$name[1];//如果有產(chǎn)品名稱,返回到數(shù)組
/**
百度:strings.xml
特殊情況1:<string name="app_name">" 掌上百度 "</string>
*/
$returnVal['name']=preg_replace('/\s|"/','',$returnVal['name']);
}
}
//$this->msg=$returnVal['package'].'--'.$returnVal['ver'].'--'.$returnVal['thumbimg'].'--'.$returnVal['name'];
if($this->oldAPK!=''){//重新上傳則刪除原apk文件和icon.png圖片
unlink($dir.$this->oldAPK);
unlink($dir.$this->oldAPK.'.png');
}
//遍歷package/res目錄下的目錄[drawable|drawable-hdpi|drawable-nodpi|drawable-ldpi|drawable-mdpi]
//系統(tǒng)取icon尺寸最大的圖標(biāo)
$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);
if(rename($dir.'package/res/'.$tmpArr[2].'/'.$returnVal['thumbimg'].'.png',$dir.$this->iframe_key.'.apk.png')){//找到目錄并成功移動(dòng)
$returnVal['thumbimg']=$this->iframe_key.'.apk.png';
}
if(!move_uploaded_file($this->tmpFile,$dir.$this->iframe_key.'.apk')){$this->msg='上傳失??!';return;}//轉(zhuǎn)移apk文件
$returnVal['filename']=$this->iframe_key.'.apk';
$returnVal['size']=$this->size;
$this->result=$returnVal;
}
提取信息流程
1、首先,通過(guò)apktool.jar命令提取apk文件中package/res/values/string.xml文件。不知為什么原因,釋放apk文件時(shí),有時(shí)并不一定得到string.xml文件。所以,后臺(tái)增加:$_config_product_apktool_count參數(shù),來(lái)控制釋放的最大次數(shù)。
2、讀取釋放根目錄下的AndroidManifest.xml文件。從該文件中可以獲取到APK包名、版本信息。
3、檢測(cè),如果是新上傳的APK,則其包名在數(shù)據(jù)庫(kù)中是否存在。就是禁止上傳相同包名的APK。修改時(shí)不檢測(cè)。
4、通過(guò)正則獲取所需要的信息。
這里為什么要提取string.xml文件?
因?yàn)椴⒉皇撬行畔?,都在AndroidManifest.xml中。有的信息在AndroidManifest.xml中只是做為一個(gè)“引用”,真實(shí)記錄是在string.xml中的。比如
AndroidManifest.xml中關(guān)于Label和icon的值。

上圖中:label="@string/app_name" 表明在string.xml中string的name屬性為app_name的值,即為該APK的“軟件名稱”,這里是“Market市場(chǎng)”,如下圖所示:

@drawable/quickflick_icon,表示quickflick_icon為ICON的文件名。
由于特殊需要,我需要找到最大的ICON圖標(biāo),見(jiàn)下面代碼:
//遍歷package/res目錄下的目錄[drawable|drawable-hdpi|drawable-nodpi|drawable-ldpi|drawable-mdpi]
//系統(tǒng)取icon尺寸最大的圖標(biāo)
$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);
經(jīng)過(guò)分析,一般APK中存放ICON圖標(biāo)在以下幾個(gè)目錄:drawable|drawable-hdpi|drawable-nodpi|drawable-ldpi|drawable-mdpi,通過(guò)遍歷比較的方式獲取最大ICON圖標(biāo),并移到臨時(shí)目錄。
將所有需要提取的信息,存到一個(gè)數(shù)組中,并通過(guò)javascript寫到表單中。如下圖所示:

提取APK信息總結(jié)
上面的代碼,目前為止,在提取上傳的APK中,能能正常提取信息,未發(fā)現(xiàn)錯(cuò)誤。在上面代碼的注釋中也看到,關(guān)于“掌上百度”這款A(yù)PK,提取不了信息,是由于他的特殊處理方式,即:<string name="app_name">" 掌上百度 "</string>,他在名稱中加上了雙引號(hào),這算是一個(gè)特例了吧。更多的特例我目前還未發(fā)現(xiàn),所以,有可能會(huì)有特例出現(xiàn),這需要分析APK的數(shù)據(jù),并在程序中做特殊處理。
在實(shí)現(xiàn)這個(gè)APK提取功能中,關(guān)鍵是要找到APK包的組織規(guī)律,只有找到規(guī)律,程序?qū)崿F(xiàn)就是在自然不過(guò)的事。
釋放APK文件注意內(nèi)容
exec('java -jar ../apktool.jar d -f '.$this->tmpFile.' '.$dir.'package');
能順利執(zhí)行上面的語(yǔ)句,要符合下面條件:
1、安裝java包,對(duì)java目錄,users用戶組的權(quán)限有:讀取和運(yùn)行、列出文件夾目錄、讀取
2、cmd.exe文件,users用戶組的權(quán)限有:讀取和運(yùn)行、讀取
3、PHP允許調(diào)用exec
4、上傳目錄要確保有寫入文件的權(quán)限
如果有更好的提取方式,歡迎交流,相互學(xué)習(xí)。
PHP提取APK信息DEMO演示下載
下載地址:http://xiazai.jb51.net/201304/yuanma/php_apk_jb51net.rar
- PHP中ajax無(wú)刷新上傳圖片與圖片下載功能
- php+ajax實(shí)現(xiàn)帶進(jìn)度條的上傳圖片功能【附demo源碼下載】
- PHP SFTP實(shí)現(xiàn)上傳下載功能
- php使用ftp實(shí)現(xiàn)文件上傳與下載功能
- PHP實(shí)現(xiàn)文件上傳下載實(shí)例
- PHP操作FTP類 (上傳、下載、移動(dòng)、創(chuàng)建等)
- PHP實(shí)現(xiàn)文件上傳與下載實(shí)例與總結(jié)
- php多文件上傳下載示例分享
- php下連接ftp實(shí)現(xiàn)文件的上傳、下載、刪除文件實(shí)例代碼
- 詳解PHP素材圖片上傳、下載功能
相關(guān)文章
Symfony頁(yè)面的基本創(chuàng)建實(shí)例詳解
這篇文章主要介紹了Symfony頁(yè)面的基本創(chuàng)建實(shí)例詳解,詳細(xì)分析了Symfony頁(yè)面的具體創(chuàng)建流程與注意事項(xiàng),需要的朋友可以參考下2015-01-01
PHP本地進(jìn)行API接口測(cè)試的實(shí)例
下面小編就為大家分享一篇PHP本地進(jìn)行API接口測(cè)試的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
PHP上傳目錄禁止執(zhí)行php文件實(shí)例講解
這篇文章主要介紹了PHP上傳目錄禁止執(zhí)行php文件實(shí)例講解,這個(gè)是比較實(shí)用的防止惡意攻擊的方法,有需要的同學(xué)可以學(xué)習(xí)下2021-03-03
淺談PHP調(diào)用Webservice思路及源碼分享
NuSoap是PHP環(huán)境下的WebService編程工具,用于創(chuàng)建或調(diào)用WebService。它是一個(gè)開(kāi)源軟件,是完全采用PHP語(yǔ)言編寫的、通過(guò)HTTP收發(fā)SOAP消息的一系列PHP類。NuSOAP的一個(gè)優(yōu)勢(shì)是不需要擴(kuò)展庫(kù)的支持,這種特性使得NuSoap可以用于所有的PHP環(huán)境,不受服務(wù)器安全設(shè)置的影響?!?/div> 2014-06-06
PHP使用PDO連接ACCESS數(shù)據(jù)庫(kù)
本文給大家分享的是一個(gè)簡(jiǎn)單的php使用pdo方式連接access數(shù)據(jù)庫(kù)的方法,有需要的小伙伴可以參考下。2015-03-03最新評(píng)論

