lib/android/apk.rb in android_parser-2.6.0 vs lib/android/apk.rb in android_parser-2.7.0.beta1
- old
+ new
@@ -10,11 +10,10 @@
class NotApkFileError < StandardError; end
class NotFoundError < StandardError; end
# apk object class
class Apk
-
# @return [String] apk file path
attr_reader :path
# @return [Android::Manifest] manifest instance
# @return [nil] when parsing manifest is failed.
attr_reader :manifest
@@ -41,36 +40,34 @@
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.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?
+ 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
+ logger.error "failed to parse resource: #{e} with backtrace"
+ logger.error 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
+ logger.error "failed to parse manifest:#{e} with backtrace"
+ logger.error e.backtrace
end
+
begin
@dex = Android::Dex.new(self.file(DEX))
rescue => e
- $stderr.puts "failed to parse dex:#{e}"
- #$stderr.puts e.backtrace
+ logger.error "failed to parse dex:#{e} with backtrace"
+ logger.error e.backtrace
end
end
# return apk file size
# @return [Integer] bytes
@@ -103,39 +100,39 @@
# @yield [name, data]
# @yieldparam [String] name file name in apk
# @yieldparam [String] data file data in apk
def each_file
- @zip.each do |entry|
+ zip.each do |entry|
next unless entry.file?
- yield entry.name, @zip.read(entry)
+ yield entry.name, zip.read(entry)
end
end
# 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
def file(name) # get data by entry name(path)
- @zip.read(entry(name))
+ zip.read(entry(name))
end
# @yield [entry]
# @yieldparam [Zip::Entry] entry zip entry
def each_entry
- @zip.each do |entry|
+ zip.each do |entry|
next unless entry.file?
yield entry
end
end
# find and return zip entry with name
# @param [String] name file name in apk(fullpath)
# @return [Zip::Entry] zip entry object
# @raise [NotFoundError] when 'name' doesn't exist in the apk
def entry(name)
- entry = @zip.find_entry(name)
+ entry = zip.find_entry(name)
raise NotFoundError, "'#{name}'" if entry.nil?
return entry
end
# find files which is matched with block condition
@@ -221,10 +218,27 @@
# @since 0.7.0
def certificates
@certificates ||= Hash[self.signs.map{|path, sign| [path, sign.certificates.first] }]
end
+ # Return all architectures (all most for universal apk)
+ # @return [Array<String>]
+ # @since 2.7.0
+ def archs
+ @archs ||= zip.glob('lib/**/*').each_with_object([]) do |entry, obj|
+ arch = entry.name.split('/')[1]
+ obj << arch unless obj.include?(arch)
+ end
+ end
+
+ # detect if contains multi-platforms (native machine code)
+ # @return [Boolean]
+ # @since 2.7.0
+ def universal?
+ archs.size > 1
+ end
+
# detect if use kotlin language (may be third-party sdk or not)
# @return [Boolean]
# @since 2.6.0
def kotlin?
@kotlin ||= kotlin_file? || kotlin_classes?
@@ -255,8 +269,17 @@
'META-INF/kotlinx_coroutines_android.version',
'META-INF/kotlinx_coroutines_core.version',
'META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler',
'META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory'
].freeze
+
+ def zip
+ @zip ||= Zip::File.open(@path)
+ rescue Zip::Error => e
+ raise NotApkFileError, e.message
+ end
+
+ def logger
+ Android.logger
+ end
end
end
-