Class: Android::Apk
- Inherits:
-
Object
- Object
- Android::Apk
- Defined in:
- lib/android/apk.rb
Overview
apk object class
Constant Summary collapse
- MANIFEST =
AndroidManifest file name
'AndroidManifest.xml'- DEX =
dex file name
'classes.dex'- RESOURCE =
resource file name
'resources.arsc'
Instance Attribute Summary collapse
-
#bindata ⇒ String
readonly
Binary data of apk.
- #dex ⇒ Android::Dex? readonly
- #manifest ⇒ Android::Manifest? readonly
-
#path ⇒ String
readonly
Apk file path.
- #resource ⇒ Resource? readonly
Instance Method Summary collapse
-
#certificates ⇒ Hash{String => OpenSSL::X509::Certificate }
v1 certificate info which is used for signing.
-
#digest(type = :sha1) ⇒ String
return hex digest string of apk file.
- #each_entry {|entry| ... } ⇒ Object
- #each_file {|name, data| ... } ⇒ Object
-
#entry(name) ⇒ Zip::Entry
find and return zip entry with name.
-
#file(name) ⇒ String
find and return binary data with name.
-
#find {|name, data| ... } ⇒ Array
find files which is matched with block condition.
-
#icon ⇒ Hash{ String => String }
extract application icon data from AndroidManifest and resource.
-
#icon_by_id(icon_id) ⇒ Hash{ String => String }
extract icon data from AndroidManifest and resource by a given icon id.
-
#initialize(filepath) ⇒ Apk
constructor
create new apk object.
-
#kotlin? ⇒ Boolean
detect if use kotlin language (may be third-party sdk or not).
-
#label(lang = nil) ⇒ String?
deprecated
Deprecated.
move to Manifest#label
-
#layouts ⇒ Hash{ String => Android::Layout }
get screen layout xml datas.
-
#signs ⇒ Hash{ String => OpenSSL::PKCS7 }
apk’s v1 signature information.
-
#size ⇒ Integer
return apk file size.
-
#time ⇒ Time
returns date of AndroidManifest.xml as Apk date.
Constructor Details
#initialize(filepath) ⇒ Apk
create new apk object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/android/apk.rb', line 41 def initialize(filepath) Zip.warn_invalid_date = false @path = filepath raise NotFoundError, "'#{filepath}'" unless File.exist? @path begin @zip = Zip::File.open(@path) rescue Zip::Error => e raise NotApkFileError, e. end @bindata = File.open(@path, 'rb') {|f| f.read } @bindata.force_encoding(Encoding::ASCII_8BIT) raise NotApkFileError, "manifest file is not found." if @zip.find_entry(MANIFEST).nil? begin @resource = Android::Resource.new(self.file(RESOURCE)) rescue => e $stderr.puts "failed to parse resource: #{e}" #$stderr.puts e.backtrace end begin @manifest = Android::Manifest.new(self.file(MANIFEST), @resource) rescue => e $stderr.puts "failed to parse manifest:#{e}" #$stderr.puts e.backtrace end begin @dex = Android::Dex.new(self.file(DEX)) rescue => e $stderr.puts "failed to parse dex:#{e}" #$stderr.puts e.backtrace end end |
Instance Attribute Details
#bindata ⇒ String (readonly)
Returns binary data of apk.
25 26 27 |
# File 'lib/android/apk.rb', line 25 def bindata @bindata end |
#manifest ⇒ Android::Manifest? (readonly)
20 21 22 |
# File 'lib/android/apk.rb', line 20 def manifest @manifest end |
#path ⇒ String (readonly)
Returns apk file path.
17 18 19 |
# File 'lib/android/apk.rb', line 17 def path @path end |
#resource ⇒ Resource? (readonly)
28 29 30 |
# File 'lib/android/apk.rb', line 28 def resource @resource end |
Instance Method Details
#certificates ⇒ Hash{String => OpenSSL::X509::Certificate }
v1 certificate info which is used for signing
222 223 224 |
# File 'lib/android/apk.rb', line 222 def certificates @certificates ||= Hash[self.signs.map{|path, sign| [path, sign.certificates.first] }] end |
#digest(type = :sha1) ⇒ String
return hex digest string of apk file
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/android/apk.rb', line 85 def digest(type = :sha1) case type when :sha1 Digest::SHA1.hexdigest(@bindata) when :sha256 Digest::SHA256.hexdigest(@bindata) when :md5 Digest::MD5.hexdigest(@bindata) else raise ArgumentError end end |
#each_entry {|entry| ... } ⇒ Object
124 125 126 127 128 129 |
# File 'lib/android/apk.rb', line 124 def each_entry @zip.each do |entry| next unless entry.file? yield entry end end |
#each_file {|name, data| ... } ⇒ Object
107 108 109 110 111 112 |
# File 'lib/android/apk.rb', line 107 def each_file @zip.each do |entry| next unless entry.file? yield entry.name, @zip.read(entry) end end |
#entry(name) ⇒ Zip::Entry
find and return zip entry with name
135 136 137 138 139 |
# File 'lib/android/apk.rb', line 135 def entry(name) entry = @zip.find_entry(name) raise NotFoundError, "'#{name}'" if entry.nil? return entry end |
#file(name) ⇒ String
find and return binary data with name
118 119 120 |
# File 'lib/android/apk.rb', line 118 def file(name) # get data by entry name(path) @zip.read(entry(name)) end |
#find {|name, data| ... } ⇒ Array
find files which is matched with block condition
150 151 152 153 154 155 156 157 |
# File 'lib/android/apk.rb', line 150 def find(&block) found = [] self.each_file do |name, data| ret = block.call(name, data) found << name if ret end found end |
#icon ⇒ Hash{ String => String }
extract application icon data from AndroidManifest and resource.
163 164 165 166 |
# File 'lib/android/apk.rb', line 163 def icon icon_id = @manifest.doc.elements['/manifest/application'].attributes['icon'] icon_by_id(icon_id) end |
#icon_by_id(icon_id) ⇒ Hash{ String => String }
extract icon data from AndroidManifest and resource by a given icon id.
173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/android/apk.rb', line 173 def icon_by_id(icon_id) if /^@(\w+\/\w+)|(0x[0-9a-fA-F]{8})$/ =~ icon_id drawables = @resource.find(icon_id) Hash[drawables.map {|name| [name, file(name)] }] else begin { icon_id => file(icon_id) } # ugh!: not tested!! rescue NotFoundError {} end end end |
#kotlin? ⇒ Boolean
detect if use kotlin language (may be third-party sdk or not)
229 230 231 |
# File 'lib/android/apk.rb', line 229 def kotlin? @kotlin ||= kotlin_file? || kotlin_classes? end |
#label(lang = nil) ⇒ String?
move to Manifest#label
get application label from AndroidManifest and resources.
192 193 194 |
# File 'lib/android/apk.rb', line 192 def label(lang = nil) @manifest.label end |
#layouts ⇒ Hash{ String => Android::Layout }
get screen layout xml datas
199 200 201 |
# File 'lib/android/apk.rb', line 199 def layouts @layouts ||= Layout.collect_layouts(self) # lazy parse end |
#signs ⇒ Hash{ String => OpenSSL::PKCS7 }
apk’s v1 signature information
206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/android/apk.rb', line 206 def signs @signs ||= lambda { signs = {} self.each_file do |path, data| # find META-INF/xxx.{RSA|DSA|EC} next unless path =~ /^META-INF\// && data.unpack("CC") == [0x30, 0x82] signs[path] = OpenSSL::PKCS7.new(data) end signs }.call end |
#size ⇒ Integer
return apk file size
77 78 79 |
# File 'lib/android/apk.rb', line 77 def size @bindata.size end |
#time ⇒ Time
returns date of AndroidManifest.xml as Apk date
100 101 102 |
# File 'lib/android/apk.rb', line 100 def time entry(MANIFEST).time end |