class Android::Apk

apk object class

Constants

DEX

dex file name

MANIFEST

AndroidManifest file name

RESOURCE

resource file name

Attributes

bindata[R]

@return [String] binary data of apk

dex[R]

@return [Android::Dex] dex instance @return [nil] when parsing dex is failed.

manifest[R]

@return [Android::Manifest] manifest instance @return [nil] when parsing manifest is failed.

path[R]

@return [String] apk file path

resource[R]

@return [Resource] resouce data @return [nil] when parsing resource is failed.

Public Class Methods

new(filepath) click to toggle source

create new apk object @param [String] filepath apk file path @raise [Android::NotFoundError] path file does'nt exist @raise [Android::NotApkFileError] path file is not Apk file.

# File lib/android/apk.rb, line 39
def initialize(filepath)
  @path = filepath
  raise NotFoundError, "'#{filepath}'" unless File.exist? @path
  begin
    @zip = Zip::File.open(@path)
  rescue Zip::Error => e
    raise NotApkFileError, e.message 
  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

Public Instance Methods

certificates() click to toggle source

certificate info which is used for signing @return [Hash{String => OpenSSL::X509::Certificate }] key: sign file path, value: first certficate in the sign file @since 0.7.0

# File lib/android/apk.rb, line 202
def certificates
  return Hash[self.signs.map{|path, sign| [path, sign.certificates.first] }]
end
digest(type = :sha1) click to toggle source

return hex digest string of apk file @param [Symbol] type hash digest type(:sha1, sha256, :md5) @return [String] hex digest string @raise [ArgumentError] type is knknown type

# File lib/android/apk.rb, line 81
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| ... } click to toggle source

@yield [entry] @yieldparam [Zip::Entry] entry zip entry

# File lib/android/apk.rb, line 120
def each_entry
  @zip.each do |entry|
    next unless entry.file?
    yield entry
  end
end
each_file() { |name, read| ... } click to toggle source

@yield [name, data] @yieldparam [String] name file name in apk @yieldparam [String] data file data in apk

# File lib/android/apk.rb, line 103
def each_file
  @zip.each do |entry|
    next unless entry.file?
    yield entry.name, @zip.read(entry)
  end
end
entry(name) click to toggle source

find and return zip entry with name @param [String] name file name in apk(fullpath) @return [Zip::ZipEntry] zip entry object @raise [NotFoundError] when 'name' doesn't exist in the apk

# File lib/android/apk.rb, line 131
def entry(name)
  entry = @zip.find_entry(name)
  raise NotFoundError, "'#{name}'" if entry.nil?
  return entry
end
file(name) click to toggle source

find and return binary data with name @param [String] name file name in apk(fullpath) @return [String] binary data @raise [NotFoundError] when 'name' doesn't exist in the apk

# File lib/android/apk.rb, line 114
def file(name) # get data by entry name(path)
  @zip.read(entry(name))
end
find(&block) click to toggle source

find files which is matched with block condition @yield [name, data] find condition @yieldparam [String] name file name in apk @yieldparam [String] data file data in apk @yieldreturn [Array] Array of matched entry name @return [Array] Array of matched entry name @example

apk = Apk.new(path)
elf_files = apk.find  { |name, data|  data[0..3] == [0x7f, 0x45, 0x4c, 0x46] } # ELF magic number
# File lib/android/apk.rb, line 146
def find(&block)
  found = []
  self.each_file do |name, data|
    ret = block.call(name, data)
    found << name if ret
  end
  found
end
icon() click to toggle source

extract icon data from AndroidManifest and resource. @return [Hash{ String => String }] hash key is icon filename. value is image data @raise [NotFoundError] @since 0.6.0

# File lib/android/apk.rb, line 159
def icon
  icon_id = @manifest.doc.elements['/manifest/application'].attributes['icon']
  if /^@(\w+\/\w+)|(0x[0-9a-fA-F]{8})$/ =~ icon_id
    drawables = @resource.find(icon_id)
    Hash[drawables.map {|name| [name, file(name)] }]
  else 
    { icon_id => file(icon_id) } # ugh!: not tested!!
  end
end
label(lang=nil) click to toggle source

get application label from AndroidManifest and resources. @param [String] lang language code like 'ja', 'cn', … @return [String] application label string @return [nil] when label is not found @deprecated move to {Android::Manifest#label} @since 0.6.0

# File lib/android/apk.rb, line 175
def label(lang=nil)
  @manifest.label
end
layouts() click to toggle source

get screen layout xml datas @return [Hash{ String => Android::Layout }] key: laytout file path, value: layout object @since 0.6.0

# File lib/android/apk.rb, line 182
def layouts
  @layouts ||= Layout.collect_layouts(self) # lazy parse
end
signs() click to toggle source

apk's signature information @return [Hash{ String => OpenSSL::PKCS7 } ] key: sign file path, value: signature @since 0.7.0

# File lib/android/apk.rb, line 189
def signs
  signs = {}
  self.each_file do |path, data|
    # find META-INF/xxx.{RSA|DSA}
    next unless path =~ /^META-INF\// && data.unpack("CC") == [0x30, 0x82]
    signs[path] = OpenSSL::PKCS7.new(data)
  end
  signs
end
size() click to toggle source

return apk file size @return [Integer] bytes

# File lib/android/apk.rb, line 73
def size
  @bindata.size
end
time() click to toggle source

returns date of AndroidManifest.xml as Apk date @return [Time]

# File lib/android/apk.rb, line 96
def time
  entry(MANIFEST).time
end