diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 818e06d..d335075 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,12 +31,10 @@ jobs: fail-fast: false matrix: ruby: [ ruby-3.1, ruby-3.2, ruby-3.3 ] - experimental: [false] + experimental: [ false ] include: - ruby: head experimental: true - - ruby: truffleruby-head - experimental: true steps: - uses: actions/checkout@v4 diff --git a/lib/app_info/aab.rb b/lib/app_info/aab.rb index 364bdd9..6cf227b 100644 --- a/lib/app_info/aab.rb +++ b/lib/app_info/aab.rb @@ -80,23 +80,33 @@ def components @components ||= manifest.components.transform_values end + # @param [String] base_path + # @return [Array] + def native_codes(base_path: BASE_PATH) + @native_codes ||= zip.glob(::File.join(base_path, 'lib/**/*')) + .each_with_object([]) do |entry, obj| + lib = entry.name.split('/')[2] + obj << lib unless obj.include?(lib) + end + end + def each_file zip.each do |entry| next unless entry.file? - yield entry.name, @zip.read(entry) + yield entry.name, zip.read(entry) end end def read_file(name, base_path: BASE_PATH) - content = @zip.read(entry(name, base_path: base_path)) + content = zip.read(entry(name, base_path: base_path)) return parse_binary_xml(content) if xml_file?(name) content end def entry(name, base_path: BASE_PATH) - entry = @zip.find_entry(::File.join(base_path, name)) + entry = zip.find_entry(::File.join(base_path, name)) raise NotFoundError, "'#{name}'" if entry.nil? entry diff --git a/lib/app_info/android.rb b/lib/app_info/android.rb index 21fc521..b1b3fad 100644 --- a/lib/app_info/android.rb +++ b/lib/app_info/android.rb @@ -136,6 +136,11 @@ def resource not_implemented_error!(__method__) end + # @abstract Subclass and override {#native_codes} to implement. + def native_codes + not_implemented_error!(__method__) + end + # @abstract Subclass and override {#zip} to implement. def zip not_implemented_error!(__method__) diff --git a/lib/app_info/apk.rb b/lib/app_info/apk.rb index 9004f79..e215570 100644 --- a/lib/app_info/apk.rb +++ b/lib/app_info/apk.rb @@ -59,6 +59,14 @@ def activities components.select { |c| c.type == 'activity' } end + # @return [Array] + def native_codes + @native_codes ||= zip.glob('lib/**/*').each_with_object([]) do |entry, obj| + lib = entry.name.split('/')[1] + obj << lib unless obj.include?(lib) + end + end + # @return [::Android::Apk] def apk @apk ||= ::Android::Apk.new(@file) diff --git a/spec/app_info/aab_spec.rb b/spec/app_info/aab_spec.rb index d5cf265..a843578 100644 --- a/spec/app_info/aab_spec.rb +++ b/spec/app_info/aab_spec.rb @@ -39,6 +39,7 @@ it { expect(subject.manifest.label).to eq('AppInfoDemo') } it { expect(subject.manifest.label(locale: 'en')).to eq('AppInfoDemo') } it { expect(subject.manifest.label(locale: 'zh-CN')).to eq('AppInfo演示') } + it { expect(subject.native_codes).to be_empty } it { expect(subject.signs).to be_kind_of(Hash) } it { expect(subject.signs).to have_key('META-INF/KEY0.RSA') } @@ -82,6 +83,7 @@ it { expect(subject.manifest.label).to eq('My Application') } it { expect(subject.manifest.label(locale: 'en')).to eq('My Application') } it { expect(subject.manifest.label(locale: 'zh-CN')).to eq('My Application') } + it { expect(subject.native_codes).to be_empty } it { expect(subject.certificates).to be_empty } it { expect(subject.signs).to be_empty } @@ -109,5 +111,12 @@ expect(icons.size).to eq(0) end end + + context 'with Native codes' do + let(:file) { fixture_path('apps/android-native-code.aab') } + + it { expect(subject.native_codes.size).to eq(7) } + it { expect(subject.native_codes).to contain_exactly('arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64') } + end end end diff --git a/spec/app_info/android_spec.rb b/spec/app_info/android_spec.rb index 15dd099..6085c51 100644 --- a/spec/app_info/android_spec.rb +++ b/spec/app_info/android_spec.rb @@ -44,6 +44,7 @@ it { expect { subject.services }.to raise_error NotImplementedError } it { expect { subject.components }.to raise_error NotImplementedError } it { expect { subject.manifest }.to raise_error NotImplementedError } + it { expect { subject.native_codes }.to raise_error NotImplementedError } it { expect { subject.resource }.to raise_error NotImplementedError } it { expect { subject.zip }.to raise_error NotImplementedError } it { expect { subject.clear! }.to raise_error NotImplementedError } diff --git a/spec/app_info/apk_spec.rb b/spec/app_info/apk_spec.rb index e84f4b4..f3f7020 100644 --- a/spec/app_info/apk_spec.rb +++ b/spec/app_info/apk_spec.rb @@ -39,6 +39,7 @@ it { expect(subject.manifest.use_permissions).to eq(subject.use_permissions) } it { expect(subject.deep_links).to eq(['icyleaf.com']) } it { expect(subject.schemes).to eq(['appinfo']) } + it { expect(subject.native_codes).to be_empty } # TODO: it will remove soon. it { expect(subject.certificates).to be_kind_of(Array) } @@ -71,6 +72,13 @@ expect(icons.size).to eq(0) end end + + context 'with Native codes' do + let(:file) { fixture_path('apps/android-native-code.apk') } + + it { expect(subject.native_codes.size).to eq(7) } + it { expect(subject.native_codes).to contain_exactly('arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64') } + end end describe '#Wear' do @@ -101,6 +109,7 @@ it { expect(subject.icons.length).not_to be_nil } it { expect(subject.min_sdk_version).to eq 21 } it { expect(subject.target_sdk_version).to eq 23 } + it { expect(subject.native_codes).to be_empty } end describe '#TV' do @@ -131,6 +140,7 @@ it { expect(subject.icons.length).not_to be_nil } it { expect(subject.min_sdk_version).to eq 23 } it { expect(subject.target_sdk_version).to eq 23 } + it { expect(subject.native_codes).to be_empty } end describe '#Automotive' do @@ -161,5 +171,6 @@ it { expect(subject.icons.length).not_to be_nil } it { expect(subject.min_sdk_version).to eq 29 } it { expect(subject.target_sdk_version).to eq 31 } + it { expect(subject.native_codes).to be_empty } end end diff --git a/spec/app_info_spec.rb b/spec/app_info_spec.rb index 3ea1937..735d65a 100644 --- a/spec/app_info_spec.rb +++ b/spec/app_info_spec.rb @@ -8,6 +8,8 @@ 'android-v1-v2-v3-signed.apk' => :apk, 'android-v2-signed-only.apk' => :apk, 'android-v3-signed-only.apk' => :apk, + 'android-native-code.apk' => :apk, + 'android-native-code.aab' => :aab, 'tv.apk' => :apk, 'wear.apk' => :apk, 'automotive.apk' => :apk, diff --git a/spec/fixtures/apps/android-native-code.aab b/spec/fixtures/apps/android-native-code.aab new file mode 100644 index 0000000..910a123 Binary files /dev/null and b/spec/fixtures/apps/android-native-code.aab differ diff --git a/spec/fixtures/apps/android-native-code.apk b/spec/fixtures/apps/android-native-code.apk new file mode 100644 index 0000000..70da8a2 Binary files /dev/null and b/spec/fixtures/apps/android-native-code.apk differ