lk-php

解析apk除了可以使用Apkparser外获取

1、安装aapt

aapt包含在android sdk中的build-tools文件夹,可以把这个文件拷到服务器上单独使用,大小仅1.2M,不需要安装android环境;需要注意的一点是,该程序是32位环境的程序,64位系统运行可能需要安装大概三个扩展包(如果本身没有的话)。

那么在64位操作系统下去执行aapt命令的话会报一下错误:

 

-bash: /usr/bin/aapt: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory

 

原因在于:64位系统中安装了32位程序。 apktool是32位

 

那么为了解决以上问题,我们需要安装:glibc.i686,zlib.i686,libstdc++.i686

 

如果你是云主机,那么很可能执行以下明步骤的时候会提示你:

 

No package glibc.i686 available

 

No package zlib.i686 available.

 

No package libstdc.i686 available.

 

原因是云主机一般配置的都是纯净64位系统

 

到这个步骤的时候,我们就要去修改yum 配置文件了,如下:

在/etc/yum.conf里面有
exclude选项,把这行删掉就可以了

 

现在去执行以下三步操作,那么appt命令就可以正常执行了

 

1.yum install glibc.i686
之后发现如下错误error while loading shared libraries: libz.so.1,ok继续安装libz
2.sudo yum install zlib.i686
之后发现error while loading shared libraries: libstdc++.so.6,执行
3.sudo yum install libstdc++.i686

 

安装 libstdc++.i686 报错:

Error: Protected multilib versions: libstdc++-4.4.7-11.el6.i686 != libstdc++-4.4.6-4.el6.x86_64

解决方法:

更新: yum update  libstdc++-4.4.6-4.el6.x86_64

然后在安装: sudo yum install  libstdc++-4.4.7-11.el6.i686

2、 用aapt读取包信息

aapt dump badging ./xxx.apk

 

该命令执行很快,瞬间. PHP实时返回数据没问题

这里返回的信息中就已经包含了包名\APP名称 及应用图标在apk包中的位置(类似res/drawable-mdpi/icon.png).

命令行返回的信息是纯文本,PHP不能直接用,我下面的PHP源码中会将其转为数组,以方便使用

3、 用unzip直接提取需要的图标文件

#解压apk包中指定图片
unzip ./xxx.apk res/drawable-mdpi/icon.png -d /tmp

#将解压出来的图片移到我们需要的位置
mv /tmp/res/drawable-mdpi/icon.png /tmp/temp.png

因为apk本身就是zip文件重命名而已,所以无需改名,可以直接解压. 另unzip可以指定只解压压缩包中某文件,也省了很多资源.

4、最后就是在PHP中用exec执行这些命令行了,参见下面源码

 

<?php
/**
 * Android包处理程序
 * Class Service_Android
 * 
 * @author:wangshuai
 * @website:www.enjoyphp.com
 */
class Service_Android {

  /**
  * 获取Apk包信息
  *
  * 需要/usr/bin/aapt
  *
  * @param $apkFile
  * @return array
  */
  public function getApkInfo($apkFile){
    try{
    exec(\'/usr/bin/aapt dump badging \'.$apkFile,$out , $return);
    $apkInfo = array();
    foreach($out as $line){
      $lineana = array();
      $a = explode(":",$line);
      $key = trim($a[0]);
      $value = trim($a[1]);

      preg_match_all(\'/((?P<key>\S+)=)?\\'(?P<value>.*?)\\'/\',$value,$matches,PREG_SET_ORDER);

      foreach($matches as $match){
        if($match[\'key\']){
        $lineana[$match[\'key\']] = $match[\'value\'];
        }else{
        $lineana[] = $match[\'value\'];
        }
      }


      $apkInfo[$key][] = $lineana;
    }
    //checkRet会把上面读出来的配置整理一下
    $ret = $this->checkRet($apkInfo);
    }catch (Exception $e){
    echo $e->getMessage();
    $ret=array();
    }
    return $ret;




  }

  /**
  * 从Apk包中提取指定文件,并移到$toFile
  *
  * @param $apkFile apk文件
  * @param $sourceFile apk文件中相应文件路径
  * @param $toFile 输出文件
  * @return bool
  */
  function getFileFromApk($apkFile,$sourceFile,$toFile){
    exec(\'unzip \'.$apkFile.\' $sourceFile -d /tmp\',$out , $return);

    if(rename("/tmp/".$sourceFile,$toFile)){
    return true;
    }else{
    return false;
    }

  }


  /**
  * 辅助函数,处理Apk信息数组
  *
  * @param $info
  * @return mixed
  */
  function checkRet($info){
    foreach($info as $key=>$lineana){
    if(is_array($lineana)){
      $info[$key] = $this->checkRet($lineana);
      if(count($info[$key]) == 1){
        $info[$key] = current($info[$key]);
      }

    }else{

    }
    }
    return $info;
  }

}

 

一段使用示例:

<?php
$apk = "/tmp/wht.apk";
$iconFile = \'/tmp/a.png\';

/** @var Service_Android $android */
$android = new Service_Android();
$res = $android->getApkInfo($apk);
var_dump($res);

$packageName = $res[\'package\'][\'name\'];
$appName = $res[\'application-label\'];
$android->getFileFromApk($apk,$res[\'application\'][\'icon\'],$iconFile);

注意事项:1 运行该程序需要PHP有exec权限 
2 获取的apk包信息中,APP名称可能会有多国语言名称,ICON会有多种尺寸; 如果有需要,请自行根据需要修改,上面只介绍了使用默认信息.

 

 

 

 

 

分类:

技术点:

相关文章: