php获取apk包信息的方法,php获取apk包
php获取apk包信息的方法,php获取apk包
有时候在使用php上传安卓apk包的时候,我们需要获取安卓apk包内的信息,本文以实例形式讲述了php获取apk包信息的方法。具体实现方法如下:
<?php /*解析安卓apk包中的压缩XML文件,还原和读取XML内容 依赖功能:需要PHP的ZIP包函数支持。*/ include('./Apkparser.php'); $appObj = new Apkparser(); $targetFile = a.apk;//apk所在的路径地址 $res = $appObj->open($targetFile); $appObj->getAppName(); // 应用名称 $appObj->getPackage(); // 应用包名 $appObj->getVersionName(); // 版本名称 $appObj->getVersionCode(); // 版本代码 ?>
以下是Apkparser类包,把以下代码复制出来保存为Apkparser.php就可以执行以上代码
<?php //------------------------------- //Apkparser类包开始 //------------------------------- class ApkParser{ //---------------------- // 公共函数,供外部调用 //---------------------- public function open($apk_file, $xml_file='AndroidManifest.xml'){ $zip = new \ZipArchive; if ($zip->open($apk_file) === TRUE) { $xml = $zip->getFromName($xml_file); $zip->close(); if ($xml){ try { return $this->parseString($xml); }catch (Exception $e){ } } } return false; } public function parseString($xml){ $this->xml = $xml; $this->length = strlen($xml); $this->root = $this->parseBlock(self::AXML_FILE); return true; } public function getXML($node=NULL, $lv=-1){ if ($lv == -1) $node = $this->root; if (!$node) return ''; if ($node['type'] == self::END_TAG) $lv--; $xml = @($node['line'] == 0 || $node['line'] == $this->line) ? '' : "\n".str_repeat(' ', $lv); $xml .= $node['tag']; $this->line = @$node['line']; foreach ($node['child'] as $c){ $xml .= $this->getXML($c, $lv+1); } return $xml; } public function getPackage(){ return $this->getAttribute('manifest', 'package'); } public function getVersionName(){ return $this->getAttribute('manifest', 'android:versionName'); } public function getVersionCode(){ return $this->getAttribute('manifest', 'android:versionCode'); } public function getAppName(){ return $this->getAttribute('manifest/application', 'android:name'); } public function getMainActivity(){ for ($id=0; true; $id++){ $act = $this->getAttribute("manifest/application/activity[{$id}]/intent-filter/action", 'android:name'); if (!$act) break; if ($act == 'android.intent.action.MAIN') return $this->getActivity($id); } return NULL; } public function getActivity($idx=0){ $idx = intval($idx); return $this->getAttribute("manifest/application/activity[{$idx}]", 'android:name'); } public function getAttribute($path, $name){ $r = $this->getElement($path); if (is_null($r)) return NULL; if (isset($r['attrs'])){ foreach ($r['attrs'] as $a){ if ($a['ns_name'] == $name) return $this->getAttributeValue($a); } } return NULL; } //---------------------- // 类型常量定义 //---------------------- const AXML_FILE = 0x00080003; const STRING_BLOCK = 0x001C0001; const RESOURCEIDS = 0x00080180; const START_NAMESPACE = 0x00100100; const END_NAMESPACE = 0x00100101; const START_TAG = 0x00100102; const END_TAG = 0x00100103; const TEXT = 0x00100104; const TYPE_NULL =0; const TYPE_REFERENCE =1; const TYPE_ATTRIBUTE =2; const TYPE_STRING =3; const TYPE_FLOAT =4; const TYPE_DIMENSION =5; const TYPE_FRACTION =6; const TYPE_INT_DEC =16; const TYPE_INT_HEX =17; const TYPE_INT_BOOLEAN =18; const TYPE_INT_COLOR_ARGB8 =28; const TYPE_INT_COLOR_RGB8 =29; const TYPE_INT_COLOR_ARGB4 =30; const TYPE_INT_COLOR_RGB4 =31; const UNIT_MASK = 15; private static $RADIX_MULTS = array(0.00390625, 3.051758E-005, 1.192093E-007, 4.656613E-010); private static $DIMENSION_UNITS = array("px","dip","sp","pt","in","mm","",""); private static $FRACTION_UNITS = array("%","%p","","","","","",""); private $xml=''; private $length = 0; private $stringCount = 0; private $styleCount = 0; private $stringTab = array(); private $styleTab = array(); private $resourceIDs = array(); private $ns = array(); private $cur_ns = NULL; private $root = NULL; private $line = 0; //---------------------- // 内部私有函数 //---------------------- private function getElement($path){ if (!$this->root) return NULL; $ps = explode('/', $path); $r = $this->root; foreach ($ps as $v){ if (preg_match('/([^\[]+)\[([0-9]+)\]$/', $v, $ms)){ $v = $ms[1]; $off = $ms[2]; }else { $off = 0; } foreach ($r['child'] as $c){ if ($c['type'] == self::START_TAG && $c['ns_name'] == $v){ if ($off == 0){ $r = $c; continue 2; }else { $off--; } } } // 没有找到节点 return NULL; } return $r; } private function parseBlock($need = 0){ $o = 0; $type = $this->get32($o); if ($need && $type != $need) throw new Exception('Block Type Error', 1); $size = $this->get32($o); if ($size < 8 || $size > $this->length) throw new Exception('Block Size Error', 2); $left = $this->length - $size; $props = false; switch ($type){ case self::AXML_FILE: $props = array( 'line' => 0, 'tag' => '<?xml version="1.0" encoding="utf-8"?>' ); break; case self::STRING_BLOCK: $this->stringCount = $this->get32($o); $this->styleCount = $this->get32($o); $o += 4; $strOffset = $this->get32($o); $styOffset = $this->get32($o); $strListOffset = $this->get32array($o, $this->stringCount); $styListOffset = $this->get32array($o, $this->styleCount); $this->stringTab = $this->stringCount > 0 ? $this->getStringTab($strOffset, $strListOffset) : array(); $this->styleTab = $this->styleCount > 0 ? $this->getStringTab($styOffset, $styListOffset) : array(); $o = $size; break; case self::RESOURCEIDS: $count = $size / 4 - 2; $this->resourceIDs = $this->get32array($o, $count); break; case self::START_NAMESPACE: $o += 8; $prefix = $this->get32($o); $uri = $this->get32($o); if (empty($this->cur_ns)){ $this->cur_ns = array(); $this->ns[] = &$this->cur_ns; } $this->cur_ns[$uri] = $prefix; break; case self::END_NAMESPACE: $o += 8; $prefix = $this->get32($o); $uri = $this->get32($o); if (empty($this->cur_ns)) break; unset($this->cur_ns[$uri]); break; case self::START_TAG: $line = $this->get32($o); $o += 4; $attrs = array(); $props = array( 'line' => $line, 'ns' => $this->getNameSpace($this->get32($o)), 'name' => $this->getString($this->get32($o)), 'flag' => $this->get32($o), 'count' => $this->get16($o), 'id' => $this->get16($o)-1, 'class' => $this->get16($o)-1, 'style' => $this->get16($o)-1, 'attrs' => &$attrs ); $props['ns_name'] = $props['ns'].$props['name']; for ($i=0; $i < $props['count']; $i++){ $a = array( 'ns' => $this->getNameSpace($this->get32($o)), 'name' => $this->getString($this->get32($o)), 'val_str' => $this->get32($o), 'val_type' => $this->get32($o), 'val_data' => $this->get32($o) ); $a['ns_name'] = $a['ns'].$a['name']; $a['val_type'] >>= 24; $attrs[] = $a; } // 处理TAG字符串 $tag = "<{$props['ns_name']}"; foreach ($this->cur_ns as $uri => $prefix){ $uri = $this->getString($uri); $prefix = $this->getString($prefix); $tag .= " xmlns:{$prefix}=\"{$uri}\""; } foreach ($props['attrs'] as $a){ $tag .= " {$a['ns_name']}=\"". $this->getAttributeValue($a). '"'; } $tag .= '>'; $props['tag'] = $tag; unset($this->cur_ns); $this->cur_ns = array(); $this->ns[] = &$this->cur_ns; $left = -1; break; case self::END_TAG: $line = $this->get32($o); $o += 4; $props = array( 'line' => $line, 'ns' => $this->getNameSpace($this->get32($o)), 'name' => $this->getString($this->get32($o)) ); $props['ns_name'] = $props['ns'].$props['name']; $props['tag'] = "</{$props['ns_name']}>"; if (count($this->ns) > 1){ array_pop($this->ns); unset($this->cur_ns); $this->cur_ns = array_pop($this->ns); $this->ns[] = &$this->cur_ns; } break; case self::TEXT: $o += 8; $props = array( 'tag' => $this->getString($this->get32($o)) ); $o += 8; break; default: throw new Exception('Block Type Error', 3); break; } $this->skip($o); $child = array(); while ($this->length > $left){ $c = $this->parseBlock(); if ($props && $c) $child[] = $c; if ($left == -1 && $c['type'] == self::END_TAG){ $left = $this->length; break; } } if ($this->length != $left) throw new Exception('Block Overflow Error', 4); if ($props){ $props['type'] = $type; $props['size'] = $size; $props['child'] = $child; return $props; }else { return false; } } private function getAttributeValue($a){ $type = &$a['val_type']; $data = &$a['val_data']; switch ($type){ case self::TYPE_STRING: return $this->getString($a['val_str']); case self::TYPE_ATTRIBUTE: return sprintf('?%s%08X', self::_getPackage($data), $data); case self::TYPE_REFERENCE: return sprintf('@%s%08X', self::_getPackage($data), $data); case self::TYPE_INT_HEX: return sprintf('0x%08X', $data); case self::TYPE_INT_BOOLEAN: return ($data != 0 ? 'true' : 'false'); case self::TYPE_INT_COLOR_ARGB8: case self::TYPE_INT_COLOR_RGB8: case self::TYPE_INT_COLOR_ARGB4: case self::TYPE_INT_COLOR_RGB4: return sprintf('#%08X', $data); case self::TYPE_DIMENSION: return $this->_complexToFloat($data).self::$DIMENSION_UNITS[$data & self::UNIT_MASK]; case self::TYPE_FRACTION: return $this->_complexToFloat($data).self::$FRACTION_UNITS[$data & self::UNIT_MASK]; case self::TYPE_FLOAT: return $this->_int2float($data); } if ($type >=self::TYPE_INT_DEC && $type < self::TYPE_INT_COLOR_ARGB8){ return (string)$data; } return sprintf('<0x%X, type 0x%02X>', $data, $type); } private function _complexToFloat($data){ return (float)($data & 0xFFFFFF00) * self::$RADIX_MULTS[($data>>4) & 3]; } private function _int2float($v) { $x = ($v & ((1 << 23) - 1)) + (1 << 23) * ($v >> 31 | 1); $exp = ($v >> 23 & 0xFF) - 127; return $x * pow(2, $exp - 23); } private static function _getPackage($data){ return ($data >> 24 == 1) ? 'android:' : ''; } private function getStringTab($base, $list){ $tab = array(); foreach ($list as $off){ $off += $base; $len = $this->get16($off); $mask = ($len >> 0x8) & 0xFF; $len = $len & 0xFF; if ($len == $mask){ if ($off + $len > $this->length) throw new Exception('String Table Overflow', 11); $tab[] = substr($this->xml, $off, $len); }else { if ($off + $len * 2 > $this->length) throw new Exception('String Table Overflow', 11); $str = substr($this->xml, $off, $len * 2); $tab[] = mb_convert_encoding($str, 'UTF-8', 'UCS-2LE'); } } return $tab; } private function getString($id){ if ($id > -1 && $id < $this->stringCount){ return $this->stringTab[$id]; }else { return ''; } } private function getNameSpace($uri){ for ($i=count($this->ns); $i > 0; ){ $ns = $this->ns[--$i]; if (isset($ns[$uri])){ $ns = $this->getString($ns[$uri]); if (!empty($ns)) $ns .= ':'; return $ns; } } return ''; } private function get32(&$off){ $int = unpack('V', substr($this->xml, $off, 4)); $off += 4; return array_shift($int); } private function get32array(&$off, $size){ if ($size <= 0) return NULL; $arr = unpack('V*', substr($this->xml, $off, 4 * $size)); if (count($arr) != $size) throw new Exception('Array Size Error', 10); $off += 4 * $size; return $arr; } private function get16(&$off){ $int = unpack('v', substr($this->xml, $off, 2)); $off += 2; return array_shift($int); } private function skip($size){ $this->xml = substr($this->xml, $size); $this->length -= $size; } } //--------------------- //Apkparser类包结束 //--------------------- ?>
感兴趣的朋友可以调试运行一下本文实例,相信会对大家的php程序开发带来一定的启发。
$_POST是一个数组,echo $_POST当然是Array.你可以var_dump($_POST)看一下数组里的参数和值。如果你传过去的参数是a,值是hello,你可以用 $_POST['a']来获取,仿GET方式welcome.php?a=hello
echo $_GET['a'];
你现在的做法是唯一可行的做法了,只能让APK定时刷新,除非APK和服务器保持连接不断开,否则服务器的PHP是服务去找到APK的,因为你的APK不是服务器,不能反过来执行。
如果要减轻服务器压力,那就必须把你的APK做成一个服务器,侦听一个网络端口,允许网络上的其它设备来连接。不过这个工程会很大,APK和PHP的逻辑都会变得非常复杂,因为PHP要在需要的时候来找APK,如果手机关机还得延时再来,而APK为了随时等待PHP来连接,要以服务方式工作,随时待命。

핫 AI 도구

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

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

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

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

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

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

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

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

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

뜨거운 주제











PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

Redmi Note 14 Pro Plus는 이제 작년 Redmi Note 13 Pro Plus(Amazon에서 현재 $375)의 직접적인 후속 제품으로 공식화되었습니다. 예상대로 Redmi Note 14 Pro Plus는 Redmi Note 14 및 Redmi Note 14 Pro와 함께 Redmi Note 14 시리즈를 주도합니다. 리

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

역사적으로 Oppo는 2018년 6월에 발표한 오리지널 Find X를 제외하고 늦겨울이나 초봄에 주력 제품인 'Find X' 시리즈를 새로 고쳤습니다. 이를 위해 Find X7과 Find X7 Ultra는 출시된 지 6개월이 채 되지 않았습니다. 이 시점에서. 시간

이 튜토리얼은 PHP를 사용하여 XML 문서를 효율적으로 처리하는 방법을 보여줍니다. XML (Extensible Markup Language)은 인간의 가독성과 기계 구문 분석을 위해 설계된 다목적 텍스트 기반 마크 업 언어입니다. 일반적으로 데이터 저장 AN에 사용됩니다

문자열은 문자, 숫자 및 기호를 포함하여 일련의 문자입니다. 이 튜토리얼은 다른 방법을 사용하여 PHP의 주어진 문자열의 모음 수를 계산하는 방법을 배웁니다. 영어의 모음은 A, E, I, O, U이며 대문자 또는 소문자 일 수 있습니다. 모음이란 무엇입니까? 모음은 특정 발음을 나타내는 알파벳 문자입니다. 대문자와 소문자를 포함하여 영어에는 5 개의 모음이 있습니다. a, e, i, o, u 예 1 입력 : String = "Tutorialspoint" 출력 : 6 설명하다 문자열의 "Tutorialspoint"의 모음은 u, o, i, a, o, i입니다. 총 6 개의 위안이 있습니다

숙련된 PHP 개발자라면 이미 그런 일을 해왔다는 느낌을 받을 것입니다. 귀하는 상당한 수의 애플리케이션을 개발하고, 수백만 줄의 코드를 디버깅하고, 여러 스크립트를 수정하여 작업을 수행했습니다.

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