Warning: Redis::connect(): connect() failed: Connection refused in /var/www/admclub.com/wp-content/object-cache.php on line 418
使用php取得android APK文件信息和图标 | _站长俱乐部站长俱乐部

使用php取得android APK文件信息和图标

虽然php不能直接获取android APK软件包的信息,但是可以通过调用google发行的android-apktool来取得文件信息的,需要exec支持。

首先需要安装android-apktool:

wget http://android-apktool.googlecode.com/files/apktool-install-linux-2.2_r01-1.tar.bz2
tar -jxvf apktool-install-linux-2.2_r01-1.tar.bz2

mv aapt /usr/bin
mv apktool /usr/bin
chmod 0755 /usr/bin/aapt
chmod 0755 /usr/bin/apktool

以下是从我写的一个类中提取出的一个方法,这个方法可以把APK文件信息取出到一个数组中,还可以从APK文件中提取出ICON图标!

    /**
     *
     * 需要exec支持
     * @var $apk_file APK文件路径,可以是HTTP形式
     * @var $get_icon 是否提取APK文件中的ICON图标,默认不提取
     * @author admclub.com
     */
	public function readApkInfoFromFile($apk_file,$get_icon=flase){
		$aapt = '/usr/bin/aapt';
		if(substr($apk_file, 0,7)=='http://'){
			$tmp_apk = "/tmp/".md5(microtime()).".apk";

			exec('/usr/bin/wget '.$apk_file.' -O '.$tmp_apk." -t 1",$_out,$_return);

			if(filesize($tmp_apk)>0){
				$apk_file = $tmp_apk;
			}
		}

	   exec("{$aapt} d badging {$apk_file}",$out,$return);

	   if($return==0){
	   		$str_out = implode("\n", $out);
	   		$out = null;

	  		#icon
	   		if($get_icon){
		        $pattern_icon = "/icon='(.+)'/isU";
		   		preg_match($pattern_icon, $str_out,$m);
		   		$info['icon']= $m[1];
		   		if($info['icon']){

		   			if($tmp_apk){
		   				$command = "unzip {$tmp_apk} {$info['icon']} -d /tmp";
		   			}
		   			else{
			   			$command = "unzip {$apk_file} {$info['icon']} -d /tmp";
		   			}

		   			mkdirs("/tmp/".$info['icon'],true);
			   		exec($command);

		   		}
	   		}

	   		#对外显示名称
	   		$pattern_name = "/application: label='(.*)'/isU";
	   		preg_match($pattern_name, $str_out,$m);
	        $info['lable']=$m[1];

	        #内部名称,软件唯一的
	        $pattern_sys_name = "/package: name='(.*)'/isU";
	   		preg_match($pattern_sys_name, $str_out,$m);
	        $info['sys_name']=$m[1];

	        #内部版本名称,用于检查升级
	        $pattern_version_code = "/versionCode='(.*)'/isU";
	   		preg_match($pattern_version_code, $str_out,$m);
	        $info['version_code']=$m[1];

	        #对外显示的版本名称
	        $pattern_version = "/versionName='(.*)'/isU";
	   		preg_match($pattern_version, $str_out,$m);
	        $info['version']=$m[1];

	        #系统
	        $pattern_sdk = "/sdkVersion:'(.*)'/isU";
	   		preg_match($pattern_sdk, $str_out,$m);
	        $info['sdk_version']=$m[1];
	        if($info['sdk_version']){
	        	$sdk_names = array(3=>"1.5",4=>"1.6",7=>"2.1",8=>"2.2",10=>'2.3.3',11=>"3.0",12=>"3.1",13=>"3.2",14=>"4.0");
	        	if($sdk_names[$info['sdk_version']]){
	        		$info['os_req'] = "Android {$sdk_names[$info['sdk_version']]}";
	        	}
	        }

	         #权限
	        $pattern_perm = "/uses-permission:'(.*)'/isU";
	   		preg_match_all($pattern_perm, $str_out,$m);
	   		if($m){
	   			$cnt = count($m[1]);
	   			for($i=0;$i<$cnt;$i++){
	        		$info['permissions'] .= $info['permissions']?"\n".$m[1][$i]:$m[1][$i];
	   			}
	   		}

	   		#需要的功能(硬件支持)
	        $pattern_features = "/uses-feature:'(.*)'/isU";
	   		preg_match_all($pattern_features, $str_out,$m);
	   		if($m){
	   			$cnt = count($m[1]);
	   			for($i=0;$i<$cnt;$i++){
	        		$info['features'] .= $info['features']?"\n".$m[1][$i]:$m[1][$i];
	   			}
	   		}

	   		$info['apk_info'] = $str_out;

	    	if($tmp_apk){unlink($tmp_apk);}

	        return $info;
	    }

		if($tmp_apk){unlink($tmp_apk);}
	}

希望对一些朋友有用。

发表评论?

17 条评论。

  1. 信息很多,可以略去一部门由开发者填写内容 😛

  2. 您好,我迫切的需要用到这个功能,但我按照你的方法,返回 NULL ,请问能给个联系方式,我想请教一下您,真诚的感谢。

  3. 你好,你确认已经正确安装了android-apktool并且你的PHP环境支持exec()了吗?

    • 现在可以了,我找了很久才找到问题,原来你代码的第 40 行的 mkdirs 写错了,应该是 mkdir ,现在可以了,很谢谢你。

      • 哦,mkdirs是我的一个自定义函数,代码如下:

        function mkdirs($path, $lastoneisfile = false, $rights = 0777) {
        	if (trim ( $path ) == '')
        	return;
        	if (! $lastoneisfile && substr ( $path, - 1 ) != '/') {
        		$path = $path . "/";
        	}
        	if (is_dir ( $path )) {
        		return true;
        	} //found it!
        	$path = str_replace ( "\\", "/", $path );
        	$path = preg_replace ( '/\/+/i', '/', $path );
        	$pathes = explode ( '/', $path );
        	$cnt = count ( $pathes ) - 1;
        	$dir = current ( $pathes ) . "/";
        	if (! is_dir ( $dir . "/" )) {
        		mkdir ( $dir );
        	}
        	for($i = 0; $i < $cnt; $i ++) {
        		if (! is_dir ( $dir . "/" )) {
        			@mkdir ( $dir );
        			@chmod ( $dir, $rights );
        		}
        		$dir .= next ( $pathes ) . "/";
        	}
        }
        
        • 现在可以使用的,还有一点我想请教您一下,os_req 是指应该最低能适应的OS版本吗?如果是这样,为什么有些应用获取不到?还有这个 os_req 和sdk_version 是什么关系,再次感谢。

  4. APK包中的sdk_version是最低能适应的Android版本。
    APK包中是没有os_req这个字段的,os_req是我加上去的,就是为了直观地查看sdk_version的版本。os_req=Android 2.2这样看会直观很多。
    随着以后新版本的增加,你应该相应添加新的版本到os_req中。或者你可以不用这个信息而使用官方的sdk_version。

  5. 想请教一下您,我想获取apk中的个联盟的sdk信息,怎么做到呢 🙂

    • 你好,这个就是APK软件要求的SDK版本信息
      #系统
      $pattern_sdk = “/sdkVersion:'(.*)’/isU”;
      preg_match($pattern_sdk, $str_out,$m);
      $info[‘sdk_version’]=$m[1];
      if($info[‘sdk_version’]){
      $sdk_names = array(3=>”1.5″,4=>”1.6″,7=>”2.1″,8=>”2.2″,10=>’2.3.3′,11=>”3.0″,12=>”3.1″,13=>”3.2″,14=>”4.0″);
      if($sdk_names[$info[‘sdk_version’]]){
      $info[‘os_req’] = “Android {$sdk_names[$info[‘sdk_version’]]}”;
      }
      }

  6. 如果是Windows 下 用php 可以获得到吗?

  7. 哥们你的方法很不错,但是如何避免exec支持带来的安全隐患,希望你能给个方案,在此等待…

    • 最好在自己的VPS或者服务器上运行。
      其它方案的话,可考虑CRON

      • 可以说得更详细一些吗
        用CRON方案

        • 因为android-apktool是SHELL上可以运行的程序,那么就可以通过CRONT来运行它.
          基本原理是:
          由WEB程序生成一个需要获取APK文件信息的任务列表,可是TXT或是数据库表,
          然后再写一个SHELL脚本,功能是读取这个列表,一个个地去处理列表里的APK文件.并把处理结果按一个规定来放好图片和其它信息等.SHELL脚本里最后还可以调用一次PHP程序,把这个APK的信息标识或者存放目录传给PHP,PHP程序就可以使用android-apktool输出的结果处理一些如入库,清理等操作.这样PHP就不会用到EXEC了.
          假调你的WEB用户是www.那么su www进去,crontab -e添加一个CRONT任务,就是定期运行上面说的SHELL.

          只是个大概想法.希望能给你一些启法.

  8. 正要用这东西, 感谢分享!

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>