androidmanifest.xml是一个格式化的xml. 文档结构如图
尝试去读了一下
#encoding:utf-8
require 'zip'
require "rexml/document"
class AndroidManifest
STEP=4
MAGIC_VALUE=0x00080003
STRING_CHUNK=0x001c0001
RESOURCE_CHUNK=0x00080180
START_NAMESPACE_CHUNK=0x00100100
#节点标签
END_DOC_TAG =0x00100101
START_TAG =0x00100102
END_TAG =0x00100103
TEXT_TAG =0x00100104
#只分析出了这几种常见的类型
INT_VALUE_TYPE =0x10000008
BOOL_VALUE_TYPE =0x12000008
HEX_VALUE_TYPE =0x11000008
STRING_VALUE_TYPE =0x03000008
DOUBLE_VALUE_TYPE =0x04000008
STRING_R_ID =0x01000008
def read_number(length=4)
@seek+=length
if length==2
@manifest[@seek-length,length].unpack('S')[0]
elsif length==4
@manifest[@seek-length,length].unpack('V')[0]
else
raise "未知的数据格式"
end
end
def read_string
string_length=read_number(2)
string = @manifest[@seek,string_length*2].force_encoding('UTF-16LE').encode('utf-8')
@seek+=string_length*2+2
string
end
#第3字节开始是字符串块
def init_string_table
#字符串表开始标志
start_offset=@seek
raise "string_table?(#{@seek.to_s(16)})" unless STRING_CHUNK == read_number
#块长度
chunk_size=read_number
#字符串数量
string_count= read_number
#样式表数量
style_count =read_number
#未知
@seek+=4
#偏移量
string_pool_offset=read_number
style_pool_offset=read_number
string_offsets=string_count.times.map{|x| read_number }
style_offsets=style_count.times.map{|x| read_number }
string_count.times { @strings<<read_string }
style_count.times { @styles<<read_string }
#这儿有个问题是补位,如果读完字符串不是正好4的倍数,要补齐
@seek=start_offset+chunk_size
end
#在字符串块之后是资源列表
def init_resource_table
raise "resource_table #{@seek.to_s(16)}?" unless RESOURCE_CHUNK == read_number
chunk_size=read_number
(chunk_size / 4 -2).times.map{|x| @resource<<read_number}
end
def start_name_space
#24字节
raise "start_name_space? #{@seek.to_s(16)}?" unless START_NAMESPACE_CHUNK == read_number
chunk_size=read_number
line_number=read_number
read_number
@prefix=read_number
@uri=read_number
end
def read_xml
#一共只有4种节点
begin
tag=read_number
if START_TAG == tag
read_start_tag
elsif END_TAG == tag
@seek += 4*4
name=read_number
puts "</#{@strings[name]}>"
elsif END_DOC_TAG ==tag
puts "文档结束"
break
elsif tag==TEXT_TAG
@seek += 6*4
else
raise "tag at "+@seek.to_s(16)
end
end while true
end
def read_start_tag
chunk_size=read_number
line =read_number
@seek+=4 #0xFFFFFFFF
ns=read_number
name=read_number
flag=read_number
attr_count=read_number
class_attribute=read_number
string="<#{@strings[name]}"
attr_count.times do |index|
ns=read_number
name=read_number
key="#{@strings[@prefix]}:#{@strings[name]}"
value=read_number
type=read_number
data=read_number
if type == INT_VALUE_TYPE
value=data
elsif type == STRING_VALUE_TYPE
value=@strings[value]
elsif type == BOOL_VALUE_TYPE
value=data ? "true" : "false"
elsif type == STRING_R_ID
value="0x"+data.to_s(16)
elsif HEX_VALUE_TYPE == type
value="0x"+data.to_s(16)
elsif DOUBLE_VALUE_TYPE == type
#这儿的精度会缺失错误
value=[data].pack('L').unpack('e')[0]
else
puts "#{key}=\"#{value}\" type #{type.to_s(16)} data:#{data}"
raise "未知的数据类型"
end
string<< " #{key}=\"#{value}\""
#puts "#{key}=\"#{value}\" type #{type.to_s(16)} data:#{data}"
end
string<<">"
puts string
end
def initialize(manifest)
@manifest=manifest
@doc = REXML::Document.new('<?xml version="1.0" encoding="utf-8" standalone="no"?>')
@seek=0
@strings=[]
@styles=[]
@resource=[]
raise "未知的文件标志符" unless MAGIC_VALUE == read_number
@file_size=read_number
init_string_table
init_resource_table
start_name_space
read_xml
end
end
apk_file="test2.apk"
Zip::File.open(apk_file) do |zip|
AndroidManifest.new zip.read('AndroidManifest.xml')
end
嗯嗯,好象不错的样子
如果不使用apktool 解压apk包。而直接使用aapt r&a 来修改androidmanifest文件会快好多