app-info 3.0.0.beta1 → 3.0.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +14 -3
- data/README.md +4 -4
- data/lib/app_info/aab.rb +33 -112
- data/lib/app_info/android/signature.rb +5 -5
- data/lib/app_info/android/signatures/base.rb +41 -37
- data/lib/app_info/android/signatures/info.rb +135 -129
- data/lib/app_info/android/signatures/v1.rb +56 -52
- data/lib/app_info/android/signatures/v2.rb +114 -110
- data/lib/app_info/android/signatures/v3.rb +124 -120
- data/lib/app_info/android/signatures/v4.rb +13 -9
- data/lib/app_info/android.rb +162 -0
- data/lib/app_info/apk.rb +45 -99
- data/lib/app_info/apple.rb +192 -0
- data/lib/app_info/certificate.rb +11 -17
- data/lib/app_info/const.rb +47 -13
- data/lib/app_info/dsym.rb +6 -3
- data/lib/app_info/error.rb +1 -7
- data/lib/app_info/file.rb +30 -4
- data/lib/app_info/helper/file_size.rb +1 -1
- data/lib/app_info/info_plist.rb +54 -25
- data/lib/app_info/ipa.rb +39 -118
- data/lib/app_info/macos.rb +38 -94
- data/lib/app_info/mobile_provision.rb +50 -21
- data/lib/app_info/pe.rb +39 -5
- data/lib/app_info/png_uncrush.rb +19 -0
- data/lib/app_info/proguard.rb +21 -2
- data/lib/app_info/protobuf/manifest.rb +5 -1
- data/lib/app_info/version.rb +1 -1
- data/lib/app_info.rb +4 -3
- metadata +3 -1
@@ -0,0 +1,192 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'macho'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'forwardable'
|
6
|
+
require 'cfpropertylist'
|
7
|
+
|
8
|
+
module AppInfo
|
9
|
+
# Apple base parser for ipa and macos file
|
10
|
+
class Apple < File
|
11
|
+
extend Forwardable
|
12
|
+
include Helper::HumanFileSize
|
13
|
+
include Helper::Archive
|
14
|
+
|
15
|
+
# Export types
|
16
|
+
module ExportType
|
17
|
+
# debug configuration
|
18
|
+
DEBUG = :debug
|
19
|
+
# adhoc configuration (iOS only)
|
20
|
+
ADHOC = :adhoc
|
21
|
+
# enterprise configuration (iOS only)
|
22
|
+
ENTERPRISE = :enterprise
|
23
|
+
# release configuration
|
24
|
+
RELEASE = :release
|
25
|
+
# release configuration but download from App Store
|
26
|
+
APPSTORE = :appstore
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Symbol] {Platform}
|
30
|
+
def platform
|
31
|
+
Platform::APPLE
|
32
|
+
end
|
33
|
+
|
34
|
+
# return file size
|
35
|
+
# @example Read file size in integer
|
36
|
+
# aab.size # => 3618865
|
37
|
+
#
|
38
|
+
# @example Read file size in human readabale
|
39
|
+
# aab.size(human_size: true) # => '3.45 MB'
|
40
|
+
#
|
41
|
+
# @param [Boolean] human_size Convert integer value to human readable.
|
42
|
+
# @return [Integer, String]
|
43
|
+
def size(human_size: false)
|
44
|
+
file_to_human_size(@file, human_size: human_size)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @!method device
|
48
|
+
# @see InfoPlist#device
|
49
|
+
# @!method opera_system
|
50
|
+
# @see InfoPlist#opera_system
|
51
|
+
# @!method iphone?
|
52
|
+
# @see InfoPlist#iphone?
|
53
|
+
# @!method ipad?
|
54
|
+
# @see InfoPlist#ipad?
|
55
|
+
# @!method universal?
|
56
|
+
# @see InfoPlist#universal?
|
57
|
+
# @!method build_version
|
58
|
+
# @see InfoPlist#build_version
|
59
|
+
# @!method name
|
60
|
+
# @see InfoPlist#name
|
61
|
+
# @!method release_version
|
62
|
+
# @see InfoPlist#release_version
|
63
|
+
# @!method identifier
|
64
|
+
# @see InfoPlist#identifier
|
65
|
+
# @!method bundle_id
|
66
|
+
# @see InfoPlist#bundle_id
|
67
|
+
# @!method display_name
|
68
|
+
# @see InfoPlist#display_name
|
69
|
+
# @!method bundle_name
|
70
|
+
# @see InfoPlist#bundle_name
|
71
|
+
# @!method min_sdk_version
|
72
|
+
# @see InfoPlist#min_sdk_version
|
73
|
+
# @!method min_os_version
|
74
|
+
# @see InfoPlist#min_os_version
|
75
|
+
def_delegators :info, :device, :opera_system, :iphone?, :ipad?, :universal?, :macos?,
|
76
|
+
:build_version, :name, :release_version, :identifier, :bundle_id,
|
77
|
+
:display_name, :bundle_name, :min_sdk_version, :min_os_version
|
78
|
+
|
79
|
+
# @!method devices
|
80
|
+
# @see MobileProvision#devices
|
81
|
+
# @!method team_name
|
82
|
+
# @see MobileProvision#team_name
|
83
|
+
# @!method team_identifier
|
84
|
+
# @see MobileProvision#team_identifier
|
85
|
+
# @!method profile_name
|
86
|
+
# @see MobileProvision#profile_name
|
87
|
+
# @!method expired_date
|
88
|
+
# @see MobileProvision#expired_date
|
89
|
+
def_delegators :mobileprovision, :devices, :team_name, :team_identifier,
|
90
|
+
:profile_name, :expired_date
|
91
|
+
|
92
|
+
# @return [String, nil]
|
93
|
+
def distribution_name
|
94
|
+
"#{profile_name} - #{team_name}" if profile_name && team_name
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [String]
|
98
|
+
def release_type
|
99
|
+
if stored?
|
100
|
+
ExportType::APPSTORE
|
101
|
+
else
|
102
|
+
build_type
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# return iOS build configuration, not correct in macOS app.
|
107
|
+
# @return [String]
|
108
|
+
def build_type
|
109
|
+
if mobileprovision?
|
110
|
+
return ExportType::RELEASE if macos?
|
111
|
+
|
112
|
+
devices ? ExportType::ADHOC : ExportType::ENTERPRISE
|
113
|
+
else
|
114
|
+
ExportType::DEBUG
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# @return [Array<MachO>, nil]
|
119
|
+
def archs
|
120
|
+
return unless ::File.exist?(binary_path)
|
121
|
+
|
122
|
+
file = MachO.open(binary_path)
|
123
|
+
case file
|
124
|
+
when MachO::MachOFile
|
125
|
+
[file.cpusubtype]
|
126
|
+
else
|
127
|
+
file.machos.each_with_object([]) do |arch, obj|
|
128
|
+
obj << arch.cpusubtype
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
alias architectures archs
|
133
|
+
|
134
|
+
# @abstract Subclass and override {#icons} to implement.
|
135
|
+
def icons(_uncrush: true)
|
136
|
+
not_implemented_error!(__method__)
|
137
|
+
end
|
138
|
+
|
139
|
+
# @abstract Subclass and override {#stored?} to implement.
|
140
|
+
def stored?
|
141
|
+
not_implemented_error!(__method__)
|
142
|
+
end
|
143
|
+
|
144
|
+
# force remove developer certificate data from {#mobileprovision} method
|
145
|
+
# @return [nil]
|
146
|
+
def hide_developer_certificates
|
147
|
+
mobileprovision.delete('DeveloperCertificates') if mobileprovision?
|
148
|
+
end
|
149
|
+
|
150
|
+
# @return [MobileProvision]
|
151
|
+
def mobileprovision
|
152
|
+
return unless mobileprovision?
|
153
|
+
|
154
|
+
@mobileprovision ||= MobileProvision.new(mobileprovision_path)
|
155
|
+
end
|
156
|
+
|
157
|
+
# @return [Boolean]
|
158
|
+
def mobileprovision?
|
159
|
+
::File.exist?(mobileprovision_path)
|
160
|
+
end
|
161
|
+
|
162
|
+
# @abstract Subclass and override {#mobileprovision_path} to implement.
|
163
|
+
def mobileprovision_path
|
164
|
+
not_implemented_error!(__method__)
|
165
|
+
end
|
166
|
+
|
167
|
+
# @return [InfoPlist]
|
168
|
+
def info
|
169
|
+
@info ||= InfoPlist.new(info_path)
|
170
|
+
end
|
171
|
+
|
172
|
+
# @abstract Subclass and override {#info_path} to implement.
|
173
|
+
def info_path
|
174
|
+
not_implemented_error!(__method__)
|
175
|
+
end
|
176
|
+
|
177
|
+
# @abstract Subclass and override {#app_path} to implement.
|
178
|
+
def app_path
|
179
|
+
not_implemented_error!(__method__)
|
180
|
+
end
|
181
|
+
|
182
|
+
# @abstract Subclass and override {#clear!} to implement.
|
183
|
+
def clear!
|
184
|
+
not_implemented_error!(__method__)
|
185
|
+
end
|
186
|
+
|
187
|
+
# @return [String] contents path of contents
|
188
|
+
def contents
|
189
|
+
@contents ||= unarchive(@file, prefix: format.to_s)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
data/lib/app_info/certificate.rb
CHANGED
@@ -54,18 +54,22 @@ module AppInfo
|
|
54
54
|
convert_cert_name(raw.subject, format: format)
|
55
55
|
end
|
56
56
|
|
57
|
+
# @return [Time]
|
57
58
|
def created_at
|
58
59
|
raw.not_before
|
59
60
|
end
|
60
61
|
|
62
|
+
# @return [Time]
|
61
63
|
def expired_at
|
62
64
|
raw.not_after
|
63
65
|
end
|
64
66
|
|
67
|
+
# @return [Boolean]
|
65
68
|
def expired?
|
66
69
|
expired_at < Time.now.utc
|
67
70
|
end
|
68
71
|
|
72
|
+
# @return [String] format always be :x509.
|
69
73
|
def format
|
70
74
|
:x509
|
71
75
|
end
|
@@ -114,6 +118,7 @@ module AppInfo
|
|
114
118
|
end
|
115
119
|
|
116
120
|
# return size of public key
|
121
|
+
# @return [Integer]
|
117
122
|
def size
|
118
123
|
case public_key
|
119
124
|
when OpenSSL::PKey::RSA
|
@@ -126,23 +131,9 @@ module AppInfo
|
|
126
131
|
end
|
127
132
|
|
128
133
|
# return fingerprint of certificate
|
134
|
+
# @return [String]
|
129
135
|
def fingerprint(name = :sha256, transform: :lower, delimiter: nil)
|
130
136
|
digest = OpenSSL::Digest.new(name.to_s.upcase)
|
131
|
-
# digest = case name.to_sym
|
132
|
-
# when :sha1
|
133
|
-
# OpenSSL::Digest::SHA1.new
|
134
|
-
# when :sha224
|
135
|
-
# OpenSSL::Digest::SHA224.new
|
136
|
-
# when :sha384
|
137
|
-
# OpenSSL::Digest::SHA384.new
|
138
|
-
# when :sha512
|
139
|
-
# OpenSSL::Digest::SHA512.new
|
140
|
-
# when :md5
|
141
|
-
# OpenSSL::Digest::MD5.new
|
142
|
-
# else
|
143
|
-
# OpenSSL::Digest::SHA256.new
|
144
|
-
# end
|
145
|
-
|
146
137
|
digest.update(raw.to_der)
|
147
138
|
fingerprint = digest.to_s
|
148
139
|
fingerprint = fingerprint.upcase if transform.to_sym == :upper
|
@@ -152,6 +143,7 @@ module AppInfo
|
|
152
143
|
end
|
153
144
|
|
154
145
|
# Orginal OpenSSL X509 certificate
|
146
|
+
# @return [OpenSSL::X509::Certificate]
|
155
147
|
def raw
|
156
148
|
@cert
|
157
149
|
end
|
@@ -174,8 +166,10 @@ module AppInfo
|
|
174
166
|
@cert.send(method.to_sym, *args, &block) || super
|
175
167
|
end
|
176
168
|
|
177
|
-
def respond_to_missing?(
|
178
|
-
@cert.
|
169
|
+
def respond_to_missing?(method_name, *args)
|
170
|
+
@cert.key?(method_name.to_sym) ||
|
171
|
+
@cert.respond_to?(method_name) ||
|
172
|
+
super
|
179
173
|
end
|
180
174
|
end
|
181
175
|
end
|
data/lib/app_info/const.rb
CHANGED
@@ -3,21 +3,28 @@
|
|
3
3
|
module AppInfo
|
4
4
|
# Full Format
|
5
5
|
module Format
|
6
|
-
#
|
7
|
-
|
6
|
+
# Apple
|
7
|
+
|
8
8
|
INFOPLIST = :infoplist
|
9
9
|
MOBILEPROVISION = :mobileprovision
|
10
10
|
DSYM = :dsym
|
11
11
|
|
12
|
+
# macOS
|
13
|
+
|
14
|
+
MACOS = :macos
|
15
|
+
|
16
|
+
# iOS
|
17
|
+
|
18
|
+
IPA = :ipa
|
19
|
+
|
12
20
|
# Android
|
21
|
+
|
13
22
|
APK = :apk
|
14
23
|
AAB = :aab
|
15
24
|
PROGUARD = :proguard
|
16
25
|
|
17
|
-
# macOS
|
18
|
-
MACOS = :macos
|
19
|
-
|
20
26
|
# Windows
|
27
|
+
|
21
28
|
PE = :pe
|
22
29
|
|
23
30
|
UNKNOWN = :unknown
|
@@ -25,17 +32,44 @@ module AppInfo
|
|
25
32
|
|
26
33
|
# Platform
|
27
34
|
module Platform
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
35
|
+
APPLE = :apple
|
36
|
+
GOOGLE = :google
|
37
|
+
WINDOWS = :windows
|
38
|
+
end
|
39
|
+
|
40
|
+
module OperaSystem
|
41
|
+
MACOS = :macos
|
42
|
+
IOS = :ios
|
43
|
+
ANDROID = :android
|
44
|
+
WINDOWS = :windows
|
32
45
|
end
|
33
46
|
|
34
47
|
# Apple Device Type
|
35
48
|
module Device
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
49
|
+
# macOS
|
50
|
+
MACOS = :macos
|
51
|
+
|
52
|
+
# Apple iPhone
|
53
|
+
IPHONE = :iphone
|
54
|
+
# Apple iPad
|
55
|
+
IPAD = :ipad
|
56
|
+
# Apple Watch
|
57
|
+
IWATCH = :iwatch # not implemented yet
|
58
|
+
# Apple Universal (iPhone and iPad)
|
59
|
+
UNIVERSAL = :universal
|
60
|
+
|
61
|
+
# Android Phone
|
62
|
+
PHONE = :phone
|
63
|
+
# Android Tablet (not implemented yet)
|
64
|
+
TABLET = :tablet
|
65
|
+
# Android Watch
|
66
|
+
WATCH = :watch
|
67
|
+
# Android TV
|
68
|
+
TELEVISION = :television
|
69
|
+
# Android Car Automotive
|
70
|
+
AUTOMOTIVE = :automotive
|
71
|
+
|
72
|
+
# Windows
|
73
|
+
WINDOWS = :windows
|
40
74
|
end
|
41
75
|
end
|
data/lib/app_info/dsym.rb
CHANGED
@@ -7,16 +7,18 @@ module AppInfo
|
|
7
7
|
class DSYM < File
|
8
8
|
include Helper::Archive
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
# @return [Symbol] {Platform}
|
11
|
+
def platform
|
12
|
+
Platform::APPLE
|
12
13
|
end
|
13
14
|
|
14
15
|
def each_file(&block)
|
15
16
|
files.each { |file| block.call(file) }
|
16
17
|
end
|
17
18
|
|
19
|
+
# @return [Array<DebugInfo>] dsym_files files by alphabetical order
|
18
20
|
def files
|
19
|
-
@files ||= Dir.children(contents).each_with_object([]) do |file, obj|
|
21
|
+
@files ||= Dir.children(contents).sort.each_with_object([]) do |file, obj|
|
20
22
|
obj << DebugInfo.new(::File.join(contents, file))
|
21
23
|
end
|
22
24
|
end
|
@@ -30,6 +32,7 @@ module AppInfo
|
|
30
32
|
@files = nil
|
31
33
|
end
|
32
34
|
|
35
|
+
# @return [String] contents path of dsym
|
33
36
|
def contents
|
34
37
|
@contents ||= lambda {
|
35
38
|
return @file if ::File.directory?(@file)
|
data/lib/app_info/error.rb
CHANGED
@@ -9,13 +9,7 @@ module AppInfo
|
|
9
9
|
|
10
10
|
class NotFoundError < Error; end
|
11
11
|
|
12
|
-
class NotFoundWinBinraryError < NotFoundError; end
|
13
|
-
|
14
12
|
class ProtobufParseError < Error; end
|
15
13
|
|
16
|
-
class
|
17
|
-
|
18
|
-
# @deprecated Correct to the new {UnknownFileTypeError} class because typo.
|
19
|
-
# It will remove since 2.7.0.
|
20
|
-
class UnkownFileTypeError < Error; end
|
14
|
+
class UnknownFormatError < Error; end
|
21
15
|
end
|
data/lib/app_info/file.rb
CHANGED
@@ -10,14 +10,40 @@ module AppInfo
|
|
10
10
|
@logger = logger
|
11
11
|
end
|
12
12
|
|
13
|
-
# @
|
14
|
-
def
|
15
|
-
|
13
|
+
# @return [Symbol] {Format}
|
14
|
+
def format
|
15
|
+
@format ||= lambda {
|
16
|
+
if instance_of?(AppInfo::File) || instance_of?(AppInfo::Apple) ||
|
17
|
+
instance_of?(AppInfo::Android)
|
18
|
+
not_implemented_error!(__method__)
|
19
|
+
end
|
20
|
+
|
21
|
+
self.class.name.split('::')[-1].downcase.to_sym
|
22
|
+
}.call
|
23
|
+
end
|
24
|
+
|
25
|
+
# @abstract Subclass and override {#opera_system} to implement.
|
26
|
+
def opera_system
|
27
|
+
not_implemented_error!(__method__)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @abstract Subclass and override {#platform} to implement.
|
31
|
+
def platform
|
32
|
+
not_implemented_error!(__method__)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @abstract Subclass and override {#device} to implement.
|
36
|
+
def device
|
37
|
+
not_implemented_error!(__method__)
|
16
38
|
end
|
17
39
|
|
18
40
|
# @abstract Subclass and override {#size} to implement
|
19
41
|
def size(human_size: false)
|
20
|
-
|
42
|
+
not_implemented_error!(__method__)
|
43
|
+
end
|
44
|
+
|
45
|
+
def not_implemented_error!(method)
|
46
|
+
raise NotImplementedError, ".#{method} method implantation required in #{self.class}"
|
21
47
|
end
|
22
48
|
end
|
23
49
|
end
|
@@ -16,7 +16,7 @@ module AppInfo::Helper
|
|
16
16
|
max_exp = FILE_SIZE_UNITS.size - 1
|
17
17
|
exponent = (Math.log(number) / Math.log(1024)).to_i
|
18
18
|
exponent = max_exp if exponent > max_exp
|
19
|
-
number = format('%<number>.2f', number: (number / (1024**exponent.to_f)))
|
19
|
+
number = Kernel.format('%<number>.2f', number: (number / (1024**exponent.to_f)))
|
20
20
|
end
|
21
21
|
|
22
22
|
"#{number} #{FILE_SIZE_UNITS[exponent]}"
|
data/lib/app_info/info_plist.rb
CHANGED
@@ -17,94 +17,120 @@ module AppInfo
|
|
17
17
|
Device::MACOS => %w[CFBundleIconFile CFBundleIconName]
|
18
18
|
}.freeze
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
# @return [Symbol] {Platform}
|
21
|
+
def platform
|
22
|
+
Platform::APPLE
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Symbol] {OperaSystem}
|
26
|
+
def opera_system
|
27
|
+
case device
|
28
|
+
when Device::MACOS
|
29
|
+
OperaSystem::MACOS
|
30
|
+
when Device::IPHONE, Device::IPAD, Device::UNIVERSAL
|
31
|
+
OperaSystem::IOS
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Symbol] {Device}
|
36
|
+
def device
|
37
|
+
if device_family == [1]
|
38
|
+
Device::IPHONE
|
39
|
+
elsif device_family == [2]
|
40
|
+
Device::IPAD
|
41
|
+
elsif device_family == [1, 2]
|
42
|
+
Device::UNIVERSAL
|
43
|
+
elsif !info.try(:[], 'DTSDKName').nil? || !info.try(:[], 'DTPlatformName').nil?
|
44
|
+
Device::MACOS
|
45
|
+
else
|
46
|
+
raise NotImplementedError, "Unkonwn device: #{device_family}"
|
47
|
+
end
|
22
48
|
end
|
23
49
|
|
50
|
+
# @return [String, nil]
|
24
51
|
def version
|
25
52
|
release_version || build_version
|
26
53
|
end
|
27
54
|
|
55
|
+
# @return [String, nil]
|
28
56
|
def build_version
|
29
57
|
info.try(:[], 'CFBundleVersion')
|
30
58
|
end
|
31
59
|
|
60
|
+
# @return [String, nil]
|
32
61
|
def release_version
|
33
62
|
info.try(:[], 'CFBundleShortVersionString')
|
34
63
|
end
|
35
64
|
|
65
|
+
# @return [String, nil]
|
36
66
|
def identifier
|
37
67
|
info.try(:[], 'CFBundleIdentifier')
|
38
68
|
end
|
39
69
|
alias bundle_id identifier
|
40
70
|
|
71
|
+
# @return [String, nil]
|
41
72
|
def name
|
42
73
|
display_name || bundle_name
|
43
74
|
end
|
44
75
|
|
76
|
+
# @return [String, nil]
|
45
77
|
def display_name
|
46
78
|
info.try(:[], 'CFBundleDisplayName')
|
47
79
|
end
|
48
80
|
|
81
|
+
# @return [String, nil]
|
49
82
|
def bundle_name
|
50
83
|
info.try(:[], 'CFBundleName')
|
51
84
|
end
|
52
85
|
|
86
|
+
# @return [String, nil]
|
53
87
|
def min_os_version
|
54
88
|
min_sdk_version || min_system_version
|
55
89
|
end
|
56
90
|
|
57
|
-
#
|
58
91
|
# Extract the Minimum OS Version from the Info.plist (iOS Only)
|
59
|
-
#
|
92
|
+
# @return [String, nil]
|
60
93
|
def min_sdk_version
|
61
94
|
info.try(:[], 'MinimumOSVersion')
|
62
95
|
end
|
63
96
|
|
64
|
-
#
|
65
97
|
# Extract the Minimum OS Version from the Info.plist (macOS Only)
|
66
|
-
#
|
98
|
+
# @return [String, nil]
|
67
99
|
def min_system_version
|
68
100
|
info.try(:[], 'LSMinimumSystemVersion')
|
69
101
|
end
|
70
102
|
|
103
|
+
# @return [Array<String>]
|
71
104
|
def icons
|
72
|
-
@icons ||= ICON_KEYS[
|
73
|
-
end
|
74
|
-
|
75
|
-
def device_type
|
76
|
-
device_family = info.try(:[], 'UIDeviceFamily')
|
77
|
-
if device_family == [1]
|
78
|
-
Device::IPHONE
|
79
|
-
elsif device_family == [2]
|
80
|
-
Device::IPAD
|
81
|
-
elsif device_family == [1, 2]
|
82
|
-
Device::UNIVERSAL
|
83
|
-
elsif !info.try(:[], 'DTSDKName').nil? || !info.try(:[], 'DTPlatformName').nil?
|
84
|
-
Device::MACOS
|
85
|
-
end
|
105
|
+
@icons ||= ICON_KEYS[device]
|
86
106
|
end
|
87
107
|
|
108
|
+
# @return [Boolean]
|
88
109
|
def iphone?
|
89
|
-
|
110
|
+
device == Device::IPHONE
|
90
111
|
end
|
91
112
|
|
113
|
+
# @return [Boolean]
|
92
114
|
def ipad?
|
93
|
-
|
115
|
+
device == Device::IPAD
|
94
116
|
end
|
95
117
|
|
118
|
+
# @return [Boolean]
|
96
119
|
def universal?
|
97
|
-
|
120
|
+
device == Device::UNIVERSAL
|
98
121
|
end
|
99
122
|
|
123
|
+
# @return [Boolean]
|
100
124
|
def macos?
|
101
|
-
|
125
|
+
device == Device::MACOS
|
102
126
|
end
|
103
127
|
|
128
|
+
# @return [Array<String>]
|
104
129
|
def device_family
|
105
130
|
info.try(:[], 'UIDeviceFamily') || []
|
106
131
|
end
|
107
132
|
|
133
|
+
# @return [String]
|
108
134
|
def release_type
|
109
135
|
if stored?
|
110
136
|
'Store'
|
@@ -113,10 +139,13 @@ module AppInfo
|
|
113
139
|
end
|
114
140
|
end
|
115
141
|
|
142
|
+
# @return [String, nil]
|
116
143
|
def [](key)
|
117
144
|
info.try(:[], key.to_s)
|
118
145
|
end
|
119
146
|
|
147
|
+
# @!method to_h
|
148
|
+
# @see CFPropertyList#to_h
|
120
149
|
def_delegators :info, :to_h
|
121
150
|
|
122
151
|
def method_missing(method_name, *args, &block)
|
@@ -140,7 +169,7 @@ module AppInfo
|
|
140
169
|
end
|
141
170
|
|
142
171
|
def app_path
|
143
|
-
@app_path ||= case
|
172
|
+
@app_path ||= case device
|
144
173
|
when Device::MACOS
|
145
174
|
::File.dirname(@file)
|
146
175
|
else
|