ruboto-core 0.0.3 → 0.1.0
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.
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +42 -3
- data/Rakefile +5 -0
- data/assets/Rakefile +72 -7
- data/assets/assets/scripts/ruboto.rb +124 -71
- data/assets/res/drawable-hdpi/icon.png +0 -0
- data/assets/res/drawable-ldpi/icon.png +0 -0
- data/assets/res/drawable-mdpi/icon.png +0 -0
- data/assets/samples/sample_activity.rb +3 -3
- data/assets/samples/sample_activity_test.rb +21 -0
- data/assets/samples/sample_broadcast_receiver.rb +1 -1
- data/assets/samples/sample_broadcast_receiver_test.rb +1 -0
- data/assets/samples/sample_service.rb +2 -1
- data/assets/samples/sample_service_test.rb +1 -0
- data/assets/src/InheritingActivity.java +6 -4
- data/assets/src/RubotoActivity.java +17 -5
- data/assets/src/org/ruboto/Script.java +30 -17
- data/assets/src/org/ruboto/test/ActivityTest.java +58 -0
- data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +102 -0
- data/assets/test/assets/scripts/test_helper.rb +9 -0
- data/bin/ruboto +3 -920
- data/lib/java_class_gen/android_api.xml +1 -1
- data/lib/ruboto.rb +15 -0
- data/lib/ruboto/api.rb +21 -0
- data/lib/ruboto/commands/base.rb +373 -0
- data/lib/ruboto/core_ext/array.rb +6 -0
- data/lib/ruboto/core_ext/object.rb +10 -0
- data/lib/ruboto/util/asset_copier.rb +20 -0
- data/lib/ruboto/util/build.rb +183 -0
- data/lib/ruboto/util/code_formatting.rb +22 -0
- data/lib/ruboto/util/log_action.rb +20 -0
- data/lib/ruboto/util/main_fix.rb +13 -0
- data/lib/ruboto/util/objectspace.rb +8 -0
- data/lib/ruboto/util/scan_in_api.rb +40 -0
- data/lib/ruboto/util/update.rb +102 -0
- data/lib/ruboto/util/verify.rb +59 -0
- data/lib/ruboto/util/xml_element.rb +197 -0
- data/test/app_test.rb +44 -0
- data/test/test_helper.rb +4 -0
- metadata +41 -14
@@ -0,0 +1,183 @@
|
|
1
|
+
module Ruboto
|
2
|
+
module Util
|
3
|
+
module Build
|
4
|
+
include Verify
|
5
|
+
###########################################################################
|
6
|
+
#
|
7
|
+
# Build Subclass or Interface:
|
8
|
+
#
|
9
|
+
|
10
|
+
#
|
11
|
+
# build_file: Reads the src from the appropriate location,
|
12
|
+
# uses the substitutions hash to modify the contents,
|
13
|
+
# and writes to the new location
|
14
|
+
#
|
15
|
+
def build_file(src, package, name, substitutions, dest='.')
|
16
|
+
to = File.join(dest, "src/#{package.gsub('.', '/')}")
|
17
|
+
Dir.mkdir(to) unless File.directory?(to)
|
18
|
+
|
19
|
+
text = File.read(File.expand_path(Ruboto::GEM_ROOT + "/assets/src/#{src}.java"))
|
20
|
+
substitutions.each {|k,v| text.gsub!(k, v)}
|
21
|
+
|
22
|
+
File.open(File.join(to, "#{name}.java"), 'w') {|f| f << text}
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# get_class_or_interface: Opens the xml file and locates the specified class.
|
27
|
+
# Aborts if the class is not found or if it is not available for
|
28
|
+
# all api levels
|
29
|
+
#
|
30
|
+
def get_class_or_interface(klass, force=false)
|
31
|
+
element = verify_api.find_class_or_interface(klass, "either")
|
32
|
+
|
33
|
+
abort "ERROR: #{klass} not found" unless element
|
34
|
+
|
35
|
+
unless force
|
36
|
+
abort "#{klass} not available in minSdkVersion, added in #{element.attribute('api_added')}; use --force to create it" if
|
37
|
+
element.attribute('api_added') and element.attribute('api_added').to_i > verify_min_sdk.to_i
|
38
|
+
abort "#{klass} deprecated for targetSdkVersion, deprecatrd in #{element.attribute('deprecated')}; use --force to create it" if
|
39
|
+
element.attribute('deprecated') and element.attribute('deprecated').to_i <= verify_target_sdk.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
abort "#{klass} removed for targetSdkVersion, removed in #{element.attribute('api_removed')}" if
|
43
|
+
element.attribute('api_removed') and element.attribute('api_removed').to_i <= verify_target_sdk.to_i
|
44
|
+
|
45
|
+
element
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# check_methods: Checks the methods to see if they are available for all api levels
|
50
|
+
#
|
51
|
+
def check_methods(methods, force=false)
|
52
|
+
min_api = verify_min_sdk.to_i
|
53
|
+
target_api = verify_target_sdk.to_i
|
54
|
+
|
55
|
+
# Remove methods changed outside of the scope of the sdk versions
|
56
|
+
methods = methods.select{|i| not i.attribute('api_added') or i.attribute('api_added').to_i <= target_api}
|
57
|
+
methods = methods.select{|i| not i.attribute('deprecated') or i.attribute('deprecated').to_i > min_api}
|
58
|
+
methods = methods.select{|i| not i.attribute('api_removed') or i.attribute('api_removed').to_i > min_api}
|
59
|
+
|
60
|
+
# Inform and remove methods that do not exist in one of the sdk versions
|
61
|
+
methods = methods.select do |i|
|
62
|
+
if i.attribute('api_removed') and i.attribute('api_removed').to_i <= target_api
|
63
|
+
puts "Can't create #{i.method_signature} -- removed in #{i.attribute('api_removed')}"
|
64
|
+
false
|
65
|
+
else
|
66
|
+
true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
new_methods = methods
|
71
|
+
unless force
|
72
|
+
# Inform and remove methods changed inside the scope of the sdk versions
|
73
|
+
new_methods = methods.select do |i|
|
74
|
+
if i.attribute('api_added') and i.attribute('api_added').to_i > min_api
|
75
|
+
puts "Can't create #{i.method_signature} -- added in #{i.attribute('api_added')} -- exclude or force"
|
76
|
+
false
|
77
|
+
elsif i.attribute('deprecated') and i.attribute('deprecated').to_i <= target_api
|
78
|
+
puts "Can't create #{i.method_signature} -- deprecated in #{i.attribute('deprecated')} -- exclude or force"
|
79
|
+
false
|
80
|
+
else
|
81
|
+
true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
abort("Aborting!") if methods.count != new_methods.count
|
86
|
+
end
|
87
|
+
|
88
|
+
new_methods
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# generate_subclass_or_interface: Creates a subclass or interface based on the specifications.
|
93
|
+
#
|
94
|
+
def generate_subclass_or_interface(params)
|
95
|
+
defaults = {:template => "InheritingClass", :method_base => "all", :method_include => "", :method_exclude => "", :force => false, :implements => ""}
|
96
|
+
params = defaults.merge(params)
|
97
|
+
params[:package] = verify_package unless params[:package]
|
98
|
+
|
99
|
+
class_desc = get_class_or_interface(params[:class] || params[:interface], params[:force])
|
100
|
+
|
101
|
+
puts "Generating methods for #{params[:name]}..."
|
102
|
+
methods = class_desc.all_methods(params[:method_base], params[:method_include], params[:method_exclude], params[:implements])
|
103
|
+
methods = check_methods(methods, params[:force])
|
104
|
+
puts "Done. Methods created: #{methods.count}"
|
105
|
+
|
106
|
+
# Remove any duplicate constants (use *args handle multiple parameter lists)
|
107
|
+
constants = methods.map(&:constant_string).uniq
|
108
|
+
|
109
|
+
build_file params[:template], params[:package], params[:name], {
|
110
|
+
"THE_PACKAGE" => params[:package],
|
111
|
+
"THE_ACTION" => class_desc.name == "class" ? "extends" : "implements",
|
112
|
+
"THE_ANDROID_CLASS" => (params[:class] || params[:interface]) +
|
113
|
+
(params[:implements] == "" ? "" : (" implements " + params[:implements].split(",").join(", "))),
|
114
|
+
"THE_RUBOTO_CLASS" => params[:name],
|
115
|
+
"THE_CONSTANTS" => constants.map {|i| "public static final int #{i} = #{constants.index(i)};"}.indent.join("\n"),
|
116
|
+
"CONSTANTS_COUNT" => methods.count.to_s,
|
117
|
+
"THE_CONSTRUCTORS" => class_desc.name == "class" ?
|
118
|
+
class_desc.get_elements("constructor").map{|i| i.constructor_definition(params[:name])}.join("\n\n") : "",
|
119
|
+
"THE_METHODS" => methods.map{|i| i.method_definition}.join("\n\n")
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# generate_core_classe: generates RubotoActivity, RubotoService, etc. based
|
125
|
+
# on the API specifications.
|
126
|
+
#
|
127
|
+
def generate_core_classes(params)
|
128
|
+
%w(android.view.View.OnClickListener android.widget.AdapterView.OnItemClickListener).each do |i|
|
129
|
+
name = i.split(".")[-1]
|
130
|
+
if(params[:class] == name or params[:class] == "all")
|
131
|
+
generate_subclass_or_interface({:package => "org.ruboto.callbacks", :class => i, :name => "Ruboto#{name}"})
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
hash = {:package => "org.ruboto"}
|
136
|
+
%w(method_base method_include implements force).inject(hash) {|h, i| h[i.to_sym] = params[i.to_sym]; h}
|
137
|
+
hash[:method_exclude] = params[:method_exclude].split(",").push("onCreate").push("onReceive").join(",")
|
138
|
+
|
139
|
+
%w(android.app.Activity android.app.Service android.content.BroadcastReceiver android.view.View).each do |i|
|
140
|
+
name = i.split(".")[-1]
|
141
|
+
if(params[:class] == name or params[:class] == "all")
|
142
|
+
generate_subclass_or_interface(
|
143
|
+
hash.merge({:template => name == "View" ? "InheritingClass" : "Ruboto#{name}", :class => i, :name => "Ruboto#{name}"}))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Activities that can be created, but only directly (i.e., not included in all)
|
148
|
+
%w(android.preference.PreferenceActivity android.app.TabActivity).each do |i|
|
149
|
+
name = i.split(".")[-1]
|
150
|
+
if params[:class] == name
|
151
|
+
generate_subclass_or_interface(hash.merge({:template => "RubotoActivity", :class => i, :name => "Ruboto#{name}"}))
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
###########################################################################
|
157
|
+
#
|
158
|
+
# generate_inheriting_file:
|
159
|
+
# Builds a script based subclass of Activity, Service, or BroadcastReceiver
|
160
|
+
#
|
161
|
+
|
162
|
+
def generate_inheriting_file(klass, name, package, script_name, dest='.', filename = name)
|
163
|
+
file = File.join(dest, "src/#{package.gsub('.', '/')}", "#{filename}.java")
|
164
|
+
text = File.read(File.join(Ruboto::ASSETS, "src/Inheriting#{klass}.java"))
|
165
|
+
File.open(file, 'w') do |f|
|
166
|
+
f << text.gsub("THE_PACKAGE", package).gsub("Inheriting#{klass}", name).gsub("start.rb", script_name)
|
167
|
+
end
|
168
|
+
|
169
|
+
sample_source = File.read(File.join(Ruboto::ASSETS, "samples/sample_#{underscore klass}.rb")).gsub("THE_PACKAGE", package).gsub("Sample#{klass}", name).gsub("start.rb", script_name)
|
170
|
+
FileUtils.mkdir_p File.join(dest, 'assets/scripts')
|
171
|
+
File.open File.join(dest, "assets/scripts/#{script_name}"), "a" do |f|
|
172
|
+
f << sample_source
|
173
|
+
end
|
174
|
+
|
175
|
+
sample_test_source = File.read(File.join(Ruboto::ASSETS, "samples/sample_#{underscore klass}_test.rb")).gsub("THE_PACKAGE", package).gsub("Sample#{klass}", name)
|
176
|
+
FileUtils.mkdir_p File.join(dest, 'test/assets/scripts')
|
177
|
+
File.open File.join(dest, "test/assets/scripts/#{script_name.chomp('.rb')}_test.rb"), "a" do |f|
|
178
|
+
f << sample_test_source
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Ruboto
|
2
|
+
module Util
|
3
|
+
module CodeFormatting
|
4
|
+
###########################################################################
|
5
|
+
#
|
6
|
+
# Methods for formatting code
|
7
|
+
#
|
8
|
+
def method_call(return_type=nil, method_name="", parameters=[], body_clause=[])
|
9
|
+
["public #{return_type || ""} #{method_name}(" + parameters.map{|i| "#{i[1]} #{i[0]}"}.join(", ") + ") {",
|
10
|
+
body_clause.indent, "}"]
|
11
|
+
end
|
12
|
+
|
13
|
+
def if_else(condition, if_clause, else_clause)
|
14
|
+
["if (#{condition}) {", if_clause.indent, else_clause.compact.empty? ? nil : "} else {", else_clause.indent, "}"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def try_catch(try_clause, catch_clause)
|
18
|
+
["try {", try_clause.indent, "} catch (RaiseException re) {", catch_clause.indent, "}"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ruboto
|
2
|
+
module Util
|
3
|
+
module LogAction
|
4
|
+
###########################################################################
|
5
|
+
#
|
6
|
+
# log_action: put text to stdout around the execution of a block
|
7
|
+
#
|
8
|
+
|
9
|
+
def log_action(initial_text, final_text="Done.", &block)
|
10
|
+
$stdout.sync = true
|
11
|
+
|
12
|
+
print initial_text, "..."
|
13
|
+
result = yield
|
14
|
+
puts final_text
|
15
|
+
|
16
|
+
result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Ruboto
|
2
|
+
module Util
|
3
|
+
module ScanInAPI
|
4
|
+
###########################################################################
|
5
|
+
#
|
6
|
+
# Scan the XML file. Much faster than using REXML.
|
7
|
+
#
|
8
|
+
|
9
|
+
def scan_in_api(file)
|
10
|
+
require 'strscan'
|
11
|
+
doc = StringScanner.new(file)
|
12
|
+
Thread.current[:api] = XMLElement.new
|
13
|
+
parents = [Thread.current[:api]]
|
14
|
+
|
15
|
+
while not doc.eos?
|
16
|
+
doc.scan(/</)
|
17
|
+
if doc.scan(/\/\w+>/)
|
18
|
+
parents.pop
|
19
|
+
else
|
20
|
+
name = doc.scan(/\w+/)
|
21
|
+
doc.scan(/\s+/)
|
22
|
+
values = {}
|
23
|
+
while not (term = doc.scan(/[\/>]/))
|
24
|
+
key = doc.scan(/\w+/)
|
25
|
+
doc.scan(/='/)
|
26
|
+
value = doc.scan(/[^']*/)
|
27
|
+
doc.scan(/'\s*/)
|
28
|
+
values[key] = value.include?("&") ? value.gsub('<', '<').gsub('>', '>').gsub('"', "\"") : value
|
29
|
+
end
|
30
|
+
element = parents[-1].add_element(name, values)
|
31
|
+
parents.push(element) if term == ">"
|
32
|
+
doc.scan(/>/) if term == "/"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Thread.current[:api]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Ruboto
|
2
|
+
module Util
|
3
|
+
module Update
|
4
|
+
###########################################################################
|
5
|
+
#
|
6
|
+
# Updating components
|
7
|
+
#
|
8
|
+
|
9
|
+
def update_jruby(force=nil)
|
10
|
+
jruby_core = Dir.glob("libs/jruby-core-*.jar")[0]
|
11
|
+
jruby_stdlib = Dir.glob("libs/jruby-stdlib-*.jar")[0]
|
12
|
+
new_jruby_version = JRubyJars::core_jar_path.split('/')[-1][11..-5]
|
13
|
+
|
14
|
+
unless force
|
15
|
+
abort "cannot find existing jruby jars in libs. Make sure you're in the root directory of your app" if
|
16
|
+
(not jruby_core or not jruby_stdlib)
|
17
|
+
|
18
|
+
current_jruby_version = jruby_core ? jruby_core[16..-5] : "None"
|
19
|
+
abort "both jruby versions are #{new_jruby_version}. Nothing to update. Make sure you 'gem update jruby-jars' if there is a new version" if
|
20
|
+
current_jruby_version == new_jruby_version
|
21
|
+
|
22
|
+
puts "Current jruby version: #{current_jruby_version}"
|
23
|
+
puts "New jruby version: #{new_jruby_version}"
|
24
|
+
end
|
25
|
+
|
26
|
+
copier = AssetCopier.new Ruboto::ASSETS, File.expand_path(".")
|
27
|
+
log_action("Removing #{jruby_core}") {File.delete jruby_core} if jruby_core
|
28
|
+
log_action("Removing #{jruby_stdlib}") {File.delete jruby_stdlib} if jruby_stdlib
|
29
|
+
log_action("Copying #{JRubyJars::core_jar_path} to libs") {copier.copy_from_absolute_path JRubyJars::core_jar_path, "libs"}
|
30
|
+
log_action("Copying #{JRubyJars::stdlib_jar_path} to libs") {copier.copy_from_absolute_path JRubyJars::stdlib_jar_path, "libs"}
|
31
|
+
|
32
|
+
reconfigure_jruby_libs
|
33
|
+
|
34
|
+
puts "JRuby version is now: #{new_jruby_version}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_ruboto(force=nil)
|
38
|
+
verify_manifest
|
39
|
+
|
40
|
+
from = File.expand_path(Ruboto::GEM_ROOT + "/assets/assets/scripts/ruboto.rb")
|
41
|
+
to = File.expand_path("./assets/scripts/ruboto.rb")
|
42
|
+
|
43
|
+
from_text = File.read(from)
|
44
|
+
to_text = File.read(to) if File.exists?(to)
|
45
|
+
|
46
|
+
unless force
|
47
|
+
puts "New version: #{from_text[/\$RUBOTO_VERSION = (\d+)/, 1]}"
|
48
|
+
puts "Old version: #{to_text ? to_text[/\$RUBOTO_VERSION = (\d+)/, 1] : 'none'}"
|
49
|
+
|
50
|
+
abort "The ruboto.rb verion has not changed. Use --force to force update." if
|
51
|
+
from_text[/\$RUBOTO_VERSION = (\d+)/, 1] == to_text[/\$RUBOTO_VERSION = (\d+)/, 1]
|
52
|
+
end
|
53
|
+
|
54
|
+
log_action("Copying ruboto.rb and setting the package name") do
|
55
|
+
File.open(to, 'w') {|f| f << from_text.gsub("THE_PACKAGE", verify_package).gsub("ACTIVITY_NAME", verify_activity)}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# reconfigure_jruby_libs:
|
61
|
+
# - removes unneeded code from jruby-core
|
62
|
+
# - moves ruby stdlib to the root of the ruby-stdlib jar
|
63
|
+
#
|
64
|
+
|
65
|
+
def reconfigure_jruby_libs
|
66
|
+
jruby_core = JRubyJars::core_jar_path.split('/')[-1]
|
67
|
+
log_action("Removing unneeded classes from #{jruby_core}") do
|
68
|
+
Dir.mkdir "libs/tmp"
|
69
|
+
Dir.chdir "libs/tmp"
|
70
|
+
FileUtils.move "../#{jruby_core}", "."
|
71
|
+
`jar -xf #{jruby_core}`
|
72
|
+
File.delete jruby_core
|
73
|
+
['cext', 'jni', 'org/jruby/ant', 'org/jruby/compiler/ir', 'org/jruby/demo', 'org/jruby/embed/bsf',
|
74
|
+
'org/jruby/embed/jsr223', 'org/jruby/ext/ffi','org/jruby/javasupport/bsf'
|
75
|
+
].each {|i| FileUtils.remove_dir i, true}
|
76
|
+
`jar -cf ../#{jruby_core} .`
|
77
|
+
Dir.chdir "../.."
|
78
|
+
FileUtils.remove_dir "libs/tmp", true
|
79
|
+
end
|
80
|
+
|
81
|
+
jruby_stdlib = JRubyJars::stdlib_jar_path.split('/')[-1]
|
82
|
+
log_action("Reformatting #{jruby_stdlib}") do
|
83
|
+
Dir.mkdir "libs/tmp"
|
84
|
+
Dir.chdir "libs/tmp"
|
85
|
+
FileUtils.move "../#{jruby_stdlib}", "."
|
86
|
+
`jar -xf #{jruby_stdlib}`
|
87
|
+
File.delete jruby_stdlib
|
88
|
+
FileUtils.move "META-INF/jruby.home/lib/ruby/1.8", ".."
|
89
|
+
Dir["META-INF/jruby.home/lib/ruby/site_ruby/1.8/*"].each do |f|
|
90
|
+
next if File.basename(f) =~ /^..?$/
|
91
|
+
FileUtils.move f, "../1.8/" + File.basename(f)
|
92
|
+
end
|
93
|
+
Dir.chdir "../1.8"
|
94
|
+
FileUtils.remove_dir "../tmp", true
|
95
|
+
`jar -cf ../#{jruby_stdlib} .`
|
96
|
+
Dir.chdir "../.."
|
97
|
+
FileUtils.remove_dir "libs/1.8", true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'ruboto/api'
|
2
|
+
|
3
|
+
module Ruboto
|
4
|
+
module Util
|
5
|
+
module Verify
|
6
|
+
###########################################################################
|
7
|
+
#
|
8
|
+
# Verify the presence of important components
|
9
|
+
#
|
10
|
+
|
11
|
+
def verify_manifest
|
12
|
+
abort "cannot find your AndroidManifest.xml to extract info from it. Make sure you're in the root directory of your app" unless
|
13
|
+
File.exists? 'AndroidManifest.xml'
|
14
|
+
@manifest ||= REXML::Document.new(File.read('AndroidManifest.xml')).root
|
15
|
+
end
|
16
|
+
|
17
|
+
def verify_package
|
18
|
+
verify_manifest
|
19
|
+
@package ||= @manifest.attribute('package').value
|
20
|
+
end
|
21
|
+
|
22
|
+
def verify_activity
|
23
|
+
verify_manifest
|
24
|
+
@activity ||= @manifest.elements['application/activity'].attribute('android:name').value
|
25
|
+
end
|
26
|
+
|
27
|
+
def verify_sdk_versions
|
28
|
+
verify_manifest
|
29
|
+
@uses_sdk ||= @manifest.elements["uses-sdk"]
|
30
|
+
abort "you must specify your sdk level in the manifest (e.g., <uses-sdk android:minSdkVersion='3' android:targetSdkVersion='8' />)" unless @uses_sdk
|
31
|
+
@uses_sdk
|
32
|
+
end
|
33
|
+
|
34
|
+
def verify_min_sdk
|
35
|
+
verify_sdk_versions
|
36
|
+
@min_sdk ||= @uses_sdk.attribute('android:minSdkVersion').value
|
37
|
+
abort "you must specify a minimum sdk level in the manifest (e.g., <uses-sdk android:minSdkVersion='3' android:targetSdkVersion='8' />)" unless @min_sdk
|
38
|
+
@min_sdk
|
39
|
+
end
|
40
|
+
|
41
|
+
def verify_target_sdk
|
42
|
+
verify_sdk_versions
|
43
|
+
@target_sdk ||= @uses_sdk.attribute('android:targetSdkVersion').value
|
44
|
+
abort "you must specify a target sdk level in the manifest (e.g., <uses-sdk android:minSdkVersion='3' android:targetSdkVersion='8' />)" unless @target_sdk
|
45
|
+
@target_sdk
|
46
|
+
end
|
47
|
+
|
48
|
+
def verify_strings
|
49
|
+
abort "cannot find your strings.xml to extract info from it. Make sure you're in the root directory of your app" unless
|
50
|
+
File.exists? 'res/values/strings.xml'
|
51
|
+
@strings ||= REXML::Document.new(File.read('res/values/strings.xml'))
|
52
|
+
end
|
53
|
+
|
54
|
+
def verify_api
|
55
|
+
Ruboto::API.api
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|