php上传apk后自动提取apk包信息的使用(示例下载)_php实例
进入公司第一个项目就是做market市场。所以后台要上传APK软件之类。为了方便,上传APK后由系统自动提取APK文件的相关信息,比如:apk包名、产品名称、版本信息、APK Code、程序大小、ICON等。起初处理方式
通过命令:java -jar AXMLPrinter2.jar AndroidManifest.xml > cmdAfter.xml
得到cmdAfter.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 //针对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(preg_match('/versionCode=\"([^\"]*)\"/i',$AndroidManifestXML,$versionCode))$returnVal['versionCode']=$versionCode[1];//如果有版本代码,返回到数组
//检测到包名后判断数据库中是否已经存在。
if($this->id==0){//添加新产品时检测,修改产品不检测
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已经存在,请更换!';
return;
}
}else{
$this->msg='系统无法检测该APK信息,请联系管理员!';
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];//如果有版本号,返回到数组
//版本号的情况目前发现有两种:1、版本号在AndroidManifest.xml中直接列出;通过以上正则即可提取
//2、版本号同label一样,放到strings.xml文件中
//2011-11-23 add
if($stringXML!='' && strstr($ver[1],'@')){
if(preg_match('/^@string\/(.*)/i',$ver[1],$findVer)){
if(preg_match('/
}
}
////////////////////////////////////////////
if(preg_match('/
$returnVal['name']=$name[1];//如果有产品名称,返回到数组
/**
百度:strings.xml
特殊情况1:
*/
$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]
//系统取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);
if(rename($dir.'package/res/'.$tmpArr[2].'/'.$returnVal['thumbimg'].'.png',$dir.$this->iframe_key.'.apk.png')){//找到目录并成功移动
$returnVal['thumbimg']=$this->iframe_key.'.apk.png';
}
if(!move_uploaded_file($this->tmpFile,$dir.$this->iframe_key.'.apk')){$this->msg='上传失败!';return;}//转移apk文件
$returnVal['filename']=$this->iframe_key.'.apk';
$returnVal['size']=$this->size;
$this->result=$returnVal;
}
提取信息流程
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,提取不了信息,是由于他的特殊处理方式,即:
在实现这个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.php.net/201304/yuanma/php_apk_phpnet.rar

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Alipay PHP ...

세션 납치는 다음 단계를 통해 달성 할 수 있습니다. 1. 세션 ID를 얻으십시오. 2. 세션 ID 사용, 3. 세션을 활성 상태로 유지하십시오. PHP에서 세션 납치를 방지하는 방법에는 다음이 포함됩니다. 1. 세션 _regenerate_id () 함수를 사용하여 세션 ID를 재생산합니다. 2. 데이터베이스를 통해 세션 데이터를 저장하십시오.

JWT는 주로 신분증 인증 및 정보 교환을 위해 당사자간에 정보를 안전하게 전송하는 데 사용되는 JSON을 기반으로 한 개방형 표준입니다. 1. JWT는 헤더, 페이로드 및 서명의 세 부분으로 구성됩니다. 2. JWT의 작업 원칙에는 세 가지 단계가 포함됩니다. JWT 생성, JWT 확인 및 Parsing Payload. 3. PHP에서 인증에 JWT를 사용하면 JWT를 생성하고 확인할 수 있으며 사용자 역할 및 권한 정보가 고급 사용에 포함될 수 있습니다. 4. 일반적인 오류에는 서명 검증 실패, 토큰 만료 및 대형 페이로드가 포함됩니다. 디버깅 기술에는 디버깅 도구 및 로깅 사용이 포함됩니다. 5. 성능 최적화 및 모범 사례에는 적절한 시그니처 알고리즘 사용, 타당성 기간 설정 합리적,

PHP 개발에서 견고한 원칙의 적용에는 다음이 포함됩니다. 1. 단일 책임 원칙 (SRP) : 각 클래스는 하나의 기능 만 담당합니다. 2. Open and Close Principle (OCP) : 변경은 수정보다는 확장을 통해 달성됩니다. 3. Lisch의 대체 원칙 (LSP) : 서브 클래스는 프로그램 정확도에 영향을 미치지 않고 기본 클래스를 대체 할 수 있습니다. 4. 인터페이스 격리 원리 (ISP) : 의존성 및 사용되지 않은 방법을 피하기 위해 세밀한 인터페이스를 사용하십시오. 5. 의존성 반전 원리 (DIP) : 높고 낮은 수준의 모듈은 추상화에 의존하며 종속성 주입을 통해 구현됩니다.

시스템이 다시 시작된 후 UnixSocket의 권한을 자동으로 설정하는 방법. 시스템이 다시 시작될 때마다 UnixSocket의 권한을 수정하려면 다음 명령을 실행해야합니다.

phpstorm에서 CLI 모드를 디버그하는 방법은 무엇입니까? PHPStorm으로 개발할 때 때때로 CLI (Command Line Interface) 모드에서 PHP를 디버그해야합니다 ...

정적 바인딩 (정적 : :)는 PHP에서 늦은 정적 바인딩 (LSB)을 구현하여 클래스를 정의하는 대신 정적 컨텍스트에서 호출 클래스를 참조 할 수 있습니다. 1) 구문 분석 프로세스는 런타임에 수행됩니다. 2) 상속 관계에서 통화 클래스를 찾아보십시오. 3) 성능 오버 헤드를 가져올 수 있습니다.

PHP 개발에서 PHP의 CURL 라이브러리를 사용하여 JSON 데이터를 보내면 종종 외부 API와 상호 작용해야합니다. 일반적인 방법 중 하나는 컬 라이브러리를 사용하여 게시물을 보내는 것입니다 ...
