danger-apkstats 0.1.0 → 0.3.1
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/.circleci/android-sdk-license +3 -0
- data/.circleci/config.yml +104 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +47 -12
- data/Dangerfile.sample +2 -0
- data/Gemfile.lock +70 -61
- data/LICENSE.txt +1 -1
- data/README.md +36 -12
- data/danger-apkstats.gemspec +3 -4
- data/lib/apkstats/command/apk_analyzer.rb +21 -2
- data/lib/apkstats/command/executable.rb +6 -0
- data/lib/apkstats/entity/apk_info.rb +3 -1
- data/lib/apkstats/entity/apk_info_diff.rb +10 -0
- data/lib/apkstats/entity/feature.rb +1 -0
- data/lib/apkstats/entity/permission.rb +1 -0
- data/lib/apkstats/gem_version.rb +1 -1
- data/lib/apkstats/plugin.rb +149 -67
- data/spec/apkstats_spec.rb +25 -9
- data/spec/command/apk_analyzer_spec.rb +13 -3
- data/spec/entity/apk_info_diff_spec.rb +6 -0
- data/spec/entity/apk_info_spec.rb +2 -0
- data/spec/spec_helper.rb +1 -1
- metadata +8 -36
- data/.bundle/config +0 -3
- data/.travis.yml +0 -25
- data/spec/fixture/app-base.apk +0 -0
- data/spec/fixture/app-other1.apk +0 -0
- data/spec/fixture/app-other2.apk +0 -0
- data/spec/fixture/app-other3.apk +0 -0
- data/spec/fixture/app-other4.apk +0 -0
- data/spec/fixture/app-other5.apk +0 -0
- data/spec/fixture/github_pr.json +0 -345
data/danger-apkstats.gemspec
CHANGED
|
@@ -9,12 +9,12 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.version = Apkstats::VERSION
|
|
10
10
|
spec.authors = ["Jumpei Matsuda"]
|
|
11
11
|
spec.email = ["jmatsu.drm@gmail.com"]
|
|
12
|
-
spec.description = "To
|
|
12
|
+
spec.description = "To inspect android application file with danger."
|
|
13
13
|
spec.summary = "This is a danger plugin to inspect android application file."
|
|
14
14
|
spec.homepage = "https://github.com/jmatsu/danger-apkstats"
|
|
15
15
|
spec.license = "MIT"
|
|
16
16
|
|
|
17
|
-
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.files = `git ls-files | grep -v 'fixture/'`.split($/)
|
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
20
20
|
spec.require_paths = ["lib"]
|
|
@@ -22,8 +22,7 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.add_runtime_dependency "danger-plugin-api", "~> 1.0"
|
|
23
23
|
|
|
24
24
|
# General ruby development
|
|
25
|
-
spec.add_development_dependency "
|
|
26
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
|
25
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
27
26
|
|
|
28
27
|
# Testing support
|
|
29
28
|
spec.add_development_dependency "rspec", "~> 3.4"
|
|
@@ -5,7 +5,7 @@ module Apkstats::Command
|
|
|
5
5
|
include Apkstats::Command::Executable
|
|
6
6
|
|
|
7
7
|
def initialize(opts)
|
|
8
|
-
@command_path = opts
|
|
8
|
+
@command_path = opts.fetch(:command_path)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def file_size(apk_filepath)
|
|
@@ -37,6 +37,17 @@ module Apkstats::Command
|
|
|
37
37
|
run_command("manifest", "target-sdk", apk_filepath)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def method_reference_count(apk_filepath)
|
|
41
|
+
ApkAnalyzer.parse_reference_to_map(run_command("dex", "references", apk_filepath))
|
|
42
|
+
.values
|
|
43
|
+
.map(&:to_i)
|
|
44
|
+
.inject(:+)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def dex_count(apk_filepath)
|
|
48
|
+
ApkAnalyzer.parse_reference_to_map(run_command("dex", "references", apk_filepath)).size
|
|
49
|
+
end
|
|
50
|
+
|
|
40
51
|
def self.parse_permissions(command_output)
|
|
41
52
|
command_output.split(/\r?\n/).map { |s| to_permission(s) }
|
|
42
53
|
end
|
|
@@ -59,11 +70,19 @@ module Apkstats::Command
|
|
|
59
70
|
::Apkstats::Entity::Feature.new(name, not_required: kind == "not-required", implied_reason: kind == "implied:" && tail)
|
|
60
71
|
end
|
|
61
72
|
|
|
73
|
+
def self.parse_reference_to_map(command_output)
|
|
74
|
+
command_output.split(/\r?\n/).each_with_object({}) do |s, acc|
|
|
75
|
+
dex_file, method_count = s.strip.split(/\t/, 2)
|
|
76
|
+
acc[dex_file] = method_count
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
62
80
|
private
|
|
63
81
|
|
|
64
82
|
def run_command(*args)
|
|
65
|
-
out, err, status = Open3.capture3(
|
|
83
|
+
out, err, status = Open3.capture3(command_path, *args)
|
|
66
84
|
raise err unless status.success?
|
|
85
|
+
|
|
67
86
|
out.rstrip
|
|
68
87
|
end
|
|
69
88
|
end
|
|
@@ -21,6 +21,8 @@ module Apkstats::Command
|
|
|
21
21
|
# permissions: Array<String>,
|
|
22
22
|
# min_sdk: String,
|
|
23
23
|
# target_sdk: String,
|
|
24
|
+
# method_reference_count: Integer,
|
|
25
|
+
# dex_count: Integer,
|
|
24
26
|
# },
|
|
25
27
|
# other: {
|
|
26
28
|
# file_size: Integer,
|
|
@@ -30,6 +32,8 @@ module Apkstats::Command
|
|
|
30
32
|
# permissions: Array<String>,
|
|
31
33
|
# min_sdk: String,
|
|
32
34
|
# target_sdk: String,
|
|
35
|
+
# method_reference_count: Integer,
|
|
36
|
+
# dex_count: Integer,
|
|
33
37
|
# },
|
|
34
38
|
# diff: {
|
|
35
39
|
# file_size: Integer,
|
|
@@ -48,6 +52,8 @@ module Apkstats::Command
|
|
|
48
52
|
# },
|
|
49
53
|
# min_sdk: Array<String>,
|
|
50
54
|
# target_sdk: Array<String>,
|
|
55
|
+
# method_reference_count: Integer,
|
|
56
|
+
# dex_count: Integer,
|
|
51
57
|
# }
|
|
52
58
|
# }
|
|
53
59
|
#
|
|
@@ -10,10 +10,12 @@ module Apkstats::Entity
|
|
|
10
10
|
permissions
|
|
11
11
|
min_sdk
|
|
12
12
|
target_sdk
|
|
13
|
+
method_reference_count
|
|
14
|
+
dex_count
|
|
13
15
|
).freeze
|
|
14
16
|
|
|
15
17
|
# Integer
|
|
16
|
-
attr_accessor :file_size, :download_size
|
|
18
|
+
attr_accessor :file_size, :download_size, :method_reference_count, :dex_count
|
|
17
19
|
|
|
18
20
|
# String
|
|
19
21
|
attr_accessor :min_sdk, :target_sdk
|
|
@@ -63,5 +63,15 @@ module Apkstats::Entity
|
|
|
63
63
|
# String
|
|
64
64
|
[@base[__method__], @other[__method__]].uniq
|
|
65
65
|
end
|
|
66
|
+
|
|
67
|
+
def method_reference_count
|
|
68
|
+
# Integer
|
|
69
|
+
@base[__method__].to_i - @other[__method__].to_i
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def dex_count
|
|
73
|
+
# Integer
|
|
74
|
+
@base[__method__].to_i - @other[__method__].to_i
|
|
75
|
+
end
|
|
66
76
|
end
|
|
67
77
|
end
|
data/lib/apkstats/gem_version.rb
CHANGED
data/lib/apkstats/plugin.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "gem_version"
|
|
3
4
|
require_relative "helper/bytes"
|
|
4
5
|
|
|
5
6
|
require_relative "entity/apk_info"
|
|
@@ -51,28 +52,46 @@ module Danger
|
|
|
51
52
|
#
|
|
52
53
|
# apkstats.target_sdk
|
|
53
54
|
#
|
|
55
|
+
# @example Show the methods reference count of your apk file.
|
|
56
|
+
#
|
|
57
|
+
# apkstats.method_reference_count
|
|
58
|
+
#
|
|
59
|
+
# @example Show the number of dex of your apk file.
|
|
60
|
+
#
|
|
61
|
+
# apkstats.dex_count
|
|
62
|
+
#
|
|
54
63
|
# @see Jumpei Matsuda/danger-apkstats
|
|
55
64
|
# @tags android, apk_stats
|
|
56
65
|
#
|
|
57
66
|
class DangerApkstats < Plugin
|
|
67
|
+
class Error < StandardError; end
|
|
68
|
+
|
|
69
|
+
# @deprecated this field have no effect
|
|
58
70
|
COMMAND_TYPE_MAP = {
|
|
59
71
|
apk_analyzer: Apkstats::Command::ApkAnalyzer,
|
|
60
72
|
}.freeze
|
|
61
73
|
|
|
62
74
|
private_constant(:COMMAND_TYPE_MAP)
|
|
63
75
|
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
# One of keys of COMMAND_TYPE_MAP
|
|
76
|
+
# @deprecated this field have no effect
|
|
77
|
+
# This will be removed in further versions
|
|
67
78
|
#
|
|
68
|
-
# @return [
|
|
79
|
+
# @return [String] _
|
|
69
80
|
attr_accessor :command_type
|
|
70
81
|
|
|
71
|
-
# *
|
|
72
|
-
# A
|
|
82
|
+
# *Required*
|
|
83
|
+
# A path of apkanalyzer command
|
|
73
84
|
#
|
|
74
|
-
# @return [
|
|
75
|
-
attr_accessor :
|
|
85
|
+
# @return [String] _
|
|
86
|
+
attr_accessor :apkanalyzer_path
|
|
87
|
+
|
|
88
|
+
# @deprecated Use apkanalyzer_path instead
|
|
89
|
+
# @return [String] _
|
|
90
|
+
alias command_path apkanalyzer_path
|
|
91
|
+
|
|
92
|
+
# @deprecated Use apkanalyzer_path= instead
|
|
93
|
+
# @return [String] _
|
|
94
|
+
alias command_path= apkanalyzer_path=
|
|
76
95
|
|
|
77
96
|
# *Required*
|
|
78
97
|
# Your target apk filepath.
|
|
@@ -80,7 +99,7 @@ module Danger
|
|
|
80
99
|
# @return [String]
|
|
81
100
|
attr_accessor :apk_filepath
|
|
82
101
|
|
|
83
|
-
# rubocop:disable Metrics/AbcSize
|
|
102
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
84
103
|
|
|
85
104
|
# Get stats of two apk files and calculate diffs between them.
|
|
86
105
|
#
|
|
@@ -90,84 +109,102 @@ module Danger
|
|
|
90
109
|
def compare_with(other_apk_filepath, do_report: true)
|
|
91
110
|
raise "apk filepaths must be specified" if apk_filepath.nil? || apk_filepath.empty?
|
|
92
111
|
|
|
93
|
-
base_apk = Apkstats::Entity::ApkInfo.new(
|
|
94
|
-
other_apk = Apkstats::Entity::ApkInfo.new(
|
|
112
|
+
base_apk = Apkstats::Entity::ApkInfo.new(apkanalyzer_command, apk_filepath)
|
|
113
|
+
other_apk = Apkstats::Entity::ApkInfo.new(apkanalyzer_command, other_apk_filepath)
|
|
95
114
|
|
|
96
|
-
|
|
115
|
+
result = {
|
|
97
116
|
base: base_apk.to_h,
|
|
98
117
|
other: base_apk.to_h,
|
|
99
118
|
diff: Apkstats::Entity::ApkInfoDiff.new(base_apk, other_apk).to_h,
|
|
100
|
-
}
|
|
101
|
-
break unless do_report
|
|
119
|
+
}
|
|
102
120
|
|
|
103
|
-
|
|
121
|
+
return result unless do_report
|
|
104
122
|
|
|
105
|
-
|
|
106
|
-
md << "Property | Summary" << "\n"
|
|
107
|
-
md << ":--- | :---" << "\n"
|
|
123
|
+
diff = result[:diff]
|
|
108
124
|
|
|
109
|
-
|
|
110
|
-
|
|
125
|
+
md = +"### Apk comparison results" << "\n\n"
|
|
126
|
+
md << "Property | Summary" << "\n"
|
|
127
|
+
md << ":--- | :---" << "\n"
|
|
111
128
|
|
|
112
|
-
|
|
113
|
-
|
|
129
|
+
diff[:min_sdk].tap do |min_sdk|
|
|
130
|
+
break if min_sdk.size == 1
|
|
114
131
|
|
|
115
|
-
|
|
116
|
-
|
|
132
|
+
md << "Min SDK Change | Before #{min_sdk[1]} / After #{min_sdk[0]}" << "\n"
|
|
133
|
+
end
|
|
117
134
|
|
|
118
|
-
|
|
119
|
-
|
|
135
|
+
diff[:target_sdk].tap do |target_sdk|
|
|
136
|
+
break if target_sdk.size == 1
|
|
120
137
|
|
|
121
|
-
|
|
122
|
-
|
|
138
|
+
md << "Target SDK Change | Before #{target_sdk[1]} / After #{target_sdk[0]}" << "\n"
|
|
139
|
+
end
|
|
123
140
|
|
|
124
|
-
|
|
125
|
-
|
|
141
|
+
result[:base][:file_size].tap do |file_size|
|
|
142
|
+
size = Apkstats::Helper::Bytes.from_b(file_size)
|
|
126
143
|
|
|
127
|
-
|
|
128
|
-
|
|
144
|
+
md << "New File Size | #{size.to_b} Bytes. (#{size.to_mb} MB) " << "\n"
|
|
145
|
+
end
|
|
129
146
|
|
|
130
|
-
|
|
131
|
-
|
|
147
|
+
diff[:file_size].tap do |file_size|
|
|
148
|
+
size = Apkstats::Helper::Bytes.from_b(file_size)
|
|
132
149
|
|
|
133
|
-
|
|
134
|
-
|
|
150
|
+
md << "File Size Change | #{size.to_s_b} Bytes. (#{size.to_s_kb} KB) " << "\n"
|
|
151
|
+
end
|
|
135
152
|
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
diff[:download_size].tap do |download_size|
|
|
154
|
+
size = Apkstats::Helper::Bytes.from_b(download_size)
|
|
138
155
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
diff[key][type_key].tap do |features|
|
|
142
|
-
break if features.empty?
|
|
156
|
+
md << "Download Size Change | #{size.to_s_b} Bytes. (#{size.to_s_kb} KB) " << "\n"
|
|
157
|
+
end
|
|
143
158
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
result[:base][:method_reference_count].tap do |method_reference_count|
|
|
160
|
+
md << "New Method Reference Count | #{method_reference_count}" << "\n"
|
|
161
|
+
end
|
|
147
162
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
163
|
+
diff[:method_reference_count].tap do |method_reference_count|
|
|
164
|
+
md << "Method Reference Count Change | #{method_reference_count}" << "\n"
|
|
165
|
+
end
|
|
151
166
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
167
|
+
result[:base][:dex_count].tap do |dex_count|
|
|
168
|
+
md << "New Number of dex file(s) | #{dex_count}" << "\n"
|
|
169
|
+
end
|
|
155
170
|
|
|
156
|
-
|
|
171
|
+
diff[:dex_count].tap do |dex_count|
|
|
172
|
+
md << "Number of dex file(s) Change | #{dex_count}" << "\n"
|
|
157
173
|
end
|
|
174
|
+
|
|
175
|
+
report_hash_and_arrays = lambda { |key, name|
|
|
176
|
+
list_up_entities = lambda { |type_key, label|
|
|
177
|
+
diff[key][type_key].tap do |features|
|
|
178
|
+
break if features.empty?
|
|
179
|
+
|
|
180
|
+
md << "#{label} | " << features.map { |f| "- #{f}" }.join("<br>").to_s << "\n"
|
|
181
|
+
end
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
list_up_entities.call(:new, "New #{name}")
|
|
185
|
+
list_up_entities.call(:removed, "Removed #{name}")
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
report_hash_and_arrays.call(:required_features, "Required Features")
|
|
189
|
+
report_hash_and_arrays.call(:non_required_features, "Non-required Features")
|
|
190
|
+
report_hash_and_arrays.call(:permissions, "Permissions")
|
|
191
|
+
|
|
192
|
+
markdown(md)
|
|
193
|
+
true
|
|
158
194
|
rescue StandardError => e
|
|
159
195
|
warn("apkstats failed to execute the command due to #{e.message}")
|
|
160
196
|
|
|
161
|
-
e
|
|
197
|
+
on_error(e)
|
|
198
|
+
false
|
|
162
199
|
end
|
|
163
200
|
|
|
164
|
-
# rubocop:enable Metrics/AbcSize
|
|
201
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
165
202
|
|
|
166
203
|
# Show the file size of your apk file.
|
|
167
204
|
#
|
|
168
205
|
# @return [Fixnum] return positive value if exists, otherwise -1.
|
|
169
206
|
def file_size(_opts = {})
|
|
170
|
-
result = run_command(__method__)
|
|
207
|
+
result = run_command(apkanalyzer_command, __method__)
|
|
171
208
|
result ? result.to_i : -1
|
|
172
209
|
end
|
|
173
210
|
|
|
@@ -175,7 +212,7 @@ module Danger
|
|
|
175
212
|
#
|
|
176
213
|
# @return [Fixnum] return positive value if exists, otherwise -1.
|
|
177
214
|
def download_size(_opts = {})
|
|
178
|
-
result = run_command(__method__)
|
|
215
|
+
result = run_command(apkanalyzer_command, __method__)
|
|
179
216
|
result ? result.to_i : -1
|
|
180
217
|
end
|
|
181
218
|
|
|
@@ -184,7 +221,7 @@ module Danger
|
|
|
184
221
|
#
|
|
185
222
|
# @return [Array<String>, Nil] return nil unless retrieved.
|
|
186
223
|
def required_features(_opts = {})
|
|
187
|
-
result = run_command(__method__)
|
|
224
|
+
result = run_command(apkanalyzer_command, __method__)
|
|
188
225
|
result ? result.to_a : nil
|
|
189
226
|
end
|
|
190
227
|
|
|
@@ -193,7 +230,7 @@ module Danger
|
|
|
193
230
|
#
|
|
194
231
|
# @return [Array<String>, Nil] return nil unless retrieved.
|
|
195
232
|
def non_required_features(_opts = {})
|
|
196
|
-
result = run_command(__method__)
|
|
233
|
+
result = run_command(apkanalyzer_command, __method__)
|
|
197
234
|
result ? result.to_a : nil
|
|
198
235
|
end
|
|
199
236
|
|
|
@@ -201,7 +238,7 @@ module Danger
|
|
|
201
238
|
#
|
|
202
239
|
# @return [Array<String>, Nil] return nil unless retrieved.
|
|
203
240
|
def permissions(_opts = {})
|
|
204
|
-
result = run_command(__method__)
|
|
241
|
+
result = run_command(apkanalyzer_command, __method__)
|
|
205
242
|
result ? result.to_a : nil
|
|
206
243
|
end
|
|
207
244
|
|
|
@@ -209,33 +246,78 @@ module Danger
|
|
|
209
246
|
#
|
|
210
247
|
# @return [String, Nil] return nil unless retrieved.
|
|
211
248
|
def min_sdk(_opts = {})
|
|
212
|
-
run_command(__method__)
|
|
249
|
+
run_command(apkanalyzer_command, __method__)
|
|
213
250
|
end
|
|
214
251
|
|
|
215
252
|
# Show the target sdk version of your apk file.
|
|
216
253
|
#
|
|
217
254
|
# @return [String, Nil] return nil unless retrieved.
|
|
218
255
|
def target_sdk(_opts = {})
|
|
219
|
-
run_command(__method__)
|
|
256
|
+
run_command(apkanalyzer_command, __method__)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Show the methods reference count of your apk file.
|
|
260
|
+
#
|
|
261
|
+
# @return [Fixnum] return positive value if exists, otherwise -1.
|
|
262
|
+
def method_reference_count(_opts = {})
|
|
263
|
+
result = run_command(apkanalyzer_command, __method__)
|
|
264
|
+
result || -1
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Show the number of dex of your apk file.
|
|
268
|
+
#
|
|
269
|
+
# @return [Fixnum] return positive value if exists, otherwise -1.
|
|
270
|
+
def dex_count(_opts = {})
|
|
271
|
+
result = run_command(apkanalyzer_command, __method__)
|
|
272
|
+
result || -1
|
|
220
273
|
end
|
|
221
274
|
|
|
222
275
|
private
|
|
223
276
|
|
|
224
|
-
|
|
277
|
+
# @param [Apkstats::Command::Executable] command a wrapper class of a command
|
|
278
|
+
# @param [String] name an attribute name
|
|
279
|
+
def run_command(command, name)
|
|
225
280
|
raise "#{command.command_path} is not found or is not executable" unless command.executable?
|
|
226
281
|
|
|
227
282
|
return command.send(name, apk_filepath)
|
|
228
283
|
rescue StandardError => e
|
|
229
284
|
warn("apkstats failed to execute the command #{name} due to #{e.message}")
|
|
230
285
|
|
|
231
|
-
e
|
|
286
|
+
on_error(e)
|
|
287
|
+
end
|
|
232
288
|
|
|
233
|
-
|
|
289
|
+
def apkanalyzer_command
|
|
290
|
+
return @apkanalyzer_command if defined?(@apkanalyzer_command)
|
|
291
|
+
|
|
292
|
+
command_path = apkanalyzer_path || `which apkanalyzer`.chomp
|
|
293
|
+
|
|
294
|
+
if command_path.empty?
|
|
295
|
+
sdk_path = ENV["ANDROID_HOME"] || ENV["ANDROID_SDK_ROOT"]
|
|
296
|
+
|
|
297
|
+
if sdk_path
|
|
298
|
+
tmp_path = File.join(sdk_path, "cmdline-tools/tools/bin/apkanalyzer")
|
|
299
|
+
tmp_path = File.join(sdk_path, "tools/bin/apkanalyzer") unless File.executable?(tmp_path)
|
|
300
|
+
|
|
301
|
+
command_path = tmp_path if File.executable?(tmp_path)
|
|
302
|
+
else
|
|
303
|
+
warn("apkstats will not infer the apkanalyzer path in further versions so please include apkanalyer in your PATH or specify it explicitly.")
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
command_path = command_path.chomp
|
|
308
|
+
|
|
309
|
+
raise Error, "Please include apkanalyer in your PATH or specify it explicitly." if command_path.empty?
|
|
310
|
+
raise Error, "#{command_path} is not executable." unless File.executable?(command_path)
|
|
311
|
+
|
|
312
|
+
@apkanalyzer_command = Apkstats::Command::ApkAnalyzer.new(command_path: command_path)
|
|
234
313
|
end
|
|
235
314
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
315
|
+
# @param [StandardError] err a happened error
|
|
316
|
+
# @return [NilClass]
|
|
317
|
+
def on_error(err)
|
|
318
|
+
warn err.message
|
|
319
|
+
err.backtrace&.each { |line| warn line }
|
|
320
|
+
nil
|
|
239
321
|
end
|
|
240
322
|
end
|
|
241
323
|
end
|