PHP读取APK的包信息,包括包名,应用名,权限,LOGO等

在服务器上安装android-apktool,我们服务器是CentOS5.5,所以我选择的包是:apktool-install-linux-2.2_r01-1.tar.bz2 。再执行安装(参考安装说明)

#linux
    1. cd /usr/local/bin
    2. curl -O https://connortumbleson.com/apktool/googlecode/apktool-install-linux-2.2_r01-1.tar.bz2 下载apktool
    3. sudo tar jxvf apktool-install-linux-2.2_r01-1.tar.bz2  解压(这里解压需要有root权限)

利用PHP的函数exec去执行aapt命令。
一般PHP环境,默认是不允许exec,shell_exec等shell命令函数的。所以我们得更改php.ini配置文件。请注意:开启exec函数功能,可能会对服务器安全有比较大的隐患,所以请自行决定是否可行。

#Linux
测试aapt命令是否可用。执行命令:
$ aapt d badging test.apk
1. <?php
2. exec ( "/usr/bin/sudo /usr/local/bin/aapt d badging /var/www/test/test.apk>info.txt 2>&1" , $out , $return );
3. //用root 去执行aapt命令,把输出的信息写入info.txt文件,下面我们要用用正则取输出的相关数据
4. var_dump( $out );
5. var_dump( $return );
6. ?>

注意

在这里请一定注意三点:
1.你的WEB用户权限是否有执行aapt的权限,如果没有,请用visudo修改sudo的配置文件,在最后加入这样一行:
  www ALL=NOPASSWD:/usr/local/bin/aapt (让www用户以root权限来执行aapt,NOPASSWD代表 sudo 时候不用输入密码). vi /etc/sudoers (或在宝塔上改)
2.PHP脚本执行sudo时,可能会报出:sudo: sorry, you must have a tty to run sudo错误,提示需要一个终端才能执行sudo.此时解决办法,用visduo命令,找到Defaults    requiretty这行前面加#号它注解掉。
3.需要用来处理apk的图标
7z 解压(命令:yum install p7zip p7zip-plugins)

获取前端传过来的文件,判断安卓还是ios

public function upload()
    {
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method == "POST") {
            // 获取项目中uploads的地址
            $proPath = explode('DownDot/', __DIR__);
            $path = $proPath[0] . 'DownDot/uploads';
            // 配置相关的信息
            $config['upload_path'] = $path;
            $config['allowed_types'] = '*';
            $config['file_name'] = uniqid();
            $this->load->library('upload', $config);

            if (!$this->upload->do_upload('file')) {
                $error = array('error' => $this->upload->display_errors());
                echo $error['error'];
            } else {
                $data = $this->upload->data();
                $fileSize = filesize($data['full_path']);

                // 获取当前时间
                date_default_timezone_set('prc');
                $create_time = date('y-m-d H:i:s', time());
                $info = array();
                //安卓上传
                if ($data['file_ext'] == '.apk') {
                    $this->load->helper('apkinfo');
                    $info = PopApkInfo($data['full_path']);

                } elseif ($data['file_ext'] == '.ipa') {
                    $this->load->helper('ipainfo');
                    $info = ipaInfo($data);
                }
                // 上传文件到OSS

                $icon = $info['icon'];
                $name = $info['lable'];
                $pkg_name = $info['sys_name'];
                $version = $info['version'];
                $build_num = $info['version_code'];

            }

        }
    }

安卓(apk)解析


function PopApkInfo($apk_file)
{
//    $apk_file = '/www/wwwroot/www.***.top/public/uploads/demo.apk';
    // $_cmd = '/Users/mac/Library/Android/sdk/build-tools/29.0.2/aapt dump badging '.$apk_file.' ls 2>&1';

    $path = app()->getRootPath().'public/uploads';
    $_cmd = '/usr/bin/sudo /usr/local/bin/aapt d badging '.$apk_file;
    exec($_cmd,$out, $return);
    $temp_path = $path.'/icon/'.md5($apk_file).'/';
    $relative_path= 'uploads/icon/'.md5($apk_file);

    if($return == 0)
    {
        if (!file_exists($temp_path)) {
            mkdir($temp_path,0777,true);
        }

        $str_out = implode("\n", $out);
        $out = null;

        #icon
        $pattern_icon = "/icon='(.+)'/isU";
        preg_match($pattern_icon, $str_out, $m);
        $info['icon'] = $m[1];
        if($info['icon'])
        {
            $command = '/usr/bin/7z e '. $apk_file . ' -y -aos -o' . $temp_path . ' ' . $info['icon'];
            exec($command);
            $barPosition=strrpos($info['icon'],'/');
            if($barPosition != false) {
                $iconPath=substr($info['icon'], $barPosition);
            } else {
                $iconPath=$info['icon'];
            }
            $info['icon'] = $relative_path . $iconPath;
        }
        #对外显示名称
        $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];

        $info['apk_info'] = $str_out;

        $info['type'] = 'and';
        return $info;
    }
    return false;
}

ios 解析需要用到第三方工具 CFPropertyList

function ipaInfo($ipa_file) {
        //var_dump($ipa_file);
        // 获取文件地址
        $filePath= $ipa_file['full_path'];
        // 获取项目地址

        $filesPath = FCPATH.'uploads';
        // 解压文件
        $_cmd = 'unzip -u '.$filePath.' -d /tmp ';
        exec($_cmd,$output,$return_var);

        //查询文件.app并去掉后缀
        $fileName = scandir('/tmp/Payload');
        $newFileName = $fileName[2];
        $file_name = explode('.app',$newFileName);
        $newFile_name = $file_name[0];
        $_rename = 'mv /tmp/Payload/'.$newFileName.'  /tmp/Payload/'.$newFile_name;
        exec($_rename,$out,$return);

        // 加载插件
        $path = FCPATH.'application/';

        require_once($path.'third_party/CFPropertyList/CFType.php');
        require_once($path.'third_party/CFPropertyList/CFArray.php');
        require_once($path.'third_party/CFPropertyList/CFBoolean.php');
        require_once($path.'third_party/CFPropertyList/CFData.php');
        require_once($path.'third_party/CFPropertyList/CFDate.php');
        require_once($path.'third_party/CFPropertyList/CFDictionary.php');
        require_once($path.'third_party/CFPropertyList/CFNumber.php');
        require_once($path.'third_party/CFPropertyList/CFString.php');
        require_once($path.'third_party/CFPropertyList/CFTypeDetector.php');
        require_once($path.'third_party/CFPropertyList/CFUid.php');
        require_once($path.'third_party/CFPropertyList/IOException.php');
        require_once($path.'third_party/CFPropertyList/PListException.php');
        require_once($path.'third_party/CFPropertyList/CFBinaryPropertyList.php');
        require_once($path.'third_party/CFPropertyList/CFPropertyList.php');

        if (($return_var == 0 || $return_var == 1) && $return == 0) {
            $content =file_get_contents('/tmp/Payload/'.$newFile_name.'/Info.plist');
            $plist = new \CFPropertyList\CFPropertyList();
            $plist->parse($content);
            $data = $plist->toArray();

            $info['icon'] = '';
            $info['lable'] = $data['CFBundleName'];
            $info['sys_name'] = $data['CFBundleIdentifier'];
            $info['version'] = $data['CFBundleShortVersionString'];
            $info['version_code'] = $data['CFBundleVersion'];
            // 获取图标

            $CFBundleIcons = $data['CFBundleIcons']['CFBundlePrimaryIcon']['CFBundleIconFiles'];
            //['CFBundleIcons']

            $iconName =  end($CFBundleIcons);

            $icon_name1 = '/tmp/Payload/'.$newFile_name.'/'.$iconName.'.png';
            $icon_name2 = '/tmp/Payload/'.$newFile_name.'/'.$iconName.'@2x.png';
            $md5 = md5($filePath);
            $temp_path = $filesPath.'/icon/'.$md5.'/';
            if (!file_exists($temp_path)) {
                mkdir($temp_path,0777,true);
            }

            require_once($path . '/helpers/parsers_helper.php');
            $filename = null;
            if (file_exists($icon_name1)) {
                $filename = $icon_name1; //需要解密的文件路径
            }elseif (file_exists($icon_name2)){
                $filename = $icon_name2; //需要解密的文件路径
            }

            if ($filename !== null) {
                $newFilename = 'uploads/icon/'.$md5.'/'.$iconName.'.png'; //解密后的文件路径
                Parsers::fix($filename,$newFilename);
                $info['icon'] = 'uploads/icon/'.$md5.'/'.$iconName.'.png';
            }
            $info['type'] = 'ios';
            exec('rm -rf /tmp/Payload');
            return $info;
        }
        exec('rm -rf /tmp/Payload');
        return false;
    }

下载文件

/**
 * @param $url 下载地址
 * @param string $publicDir 文件存放地址
 * @param string $filename 文件名称
 * @param int $type
 * @return array|bool
 */
function getDownload($url, $publicDir = '', $fileName = '', $type = 0)
{
//    $res = getDownload('http://www.***.top/uploads/demo2.apk','apktemp/demo.apk','demo.apk');
    //获取文件路径
    $publicDir = app()->getRootPath() . 'public/uploads/' . $publicDir;

    $newOneDir = substr($publicDir, 0, strrpos($publicDir, "/"));
    if (trim($url) == '') {
        return false;
    }
    //检验访问url是否有效
    $array = get_headers($url, 1);
    if (!preg_match('/200/', $array[0])) {
        return false;
    }

//    if (trim($publicDir) == '') {
//        return false;
//    }
    //创建保存目录
    if (!file_exists($newOneDir) && !mkdir($newOneDir, 0777, true)) {
        return false;
    }
    //原来文件存在则删除
//    if (file_exists($save_dir)) {
//        unlink($save_dir);
//    }
    //获取远程文件所采用的方法
    if ($type) {
        $ch = curl_init();
        $timeout = 5;
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        $content = curl_exec($ch);
        curl_close($ch);
    } else {
        ob_start();
        readfile($url);
        $content = ob_get_contents();
        ob_end_clean();
    }
//    $size = strlen($content);
    //文件大小
    $fp2 = @fopen($publicDir, 'a');
    fwrite($fp2, $content);
    fclose($fp2);
    unset($content, $url);
    return array(
        'file_name' => $fileName,
        'save_path' => $publicDir,
//        'file_size' => $size
    );
}

给TA打赏
共{{data.count}}人
人已打赏
技术教程

PHP str_shuffle()用法

2024-2-26 14:33:11

技术教程

PHP中的精确计算bcadd,bcsub,bcmul,bcdiv 及 扩展安装

2024-3-30 10:58:49

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索