ruboto 0.5.2

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.
Files changed (67) hide show
  1. data/COPYING +19 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +21 -0
  4. data/README.md +293 -0
  5. data/Rakefile +114 -0
  6. data/assets/Rakefile +386 -0
  7. data/assets/res/drawable-hdpi/icon.png +0 -0
  8. data/assets/res/drawable-ldpi/icon.png +0 -0
  9. data/assets/res/drawable-mdpi/icon.png +0 -0
  10. data/assets/res/layout/get_ruboto_core.xml +25 -0
  11. data/assets/samples/sample_activity.rb +21 -0
  12. data/assets/samples/sample_activity_test.rb +21 -0
  13. data/assets/samples/sample_broadcast_receiver.rb +6 -0
  14. data/assets/samples/sample_broadcast_receiver_test.rb +1 -0
  15. data/assets/samples/sample_service.rb +14 -0
  16. data/assets/samples/sample_service_test.rb +1 -0
  17. data/assets/src/InheritingActivity.java +195 -0
  18. data/assets/src/InheritingBroadcastReceiver.java +27 -0
  19. data/assets/src/InheritingClass.java +19 -0
  20. data/assets/src/InheritingService.java +9 -0
  21. data/assets/src/RubotoActivity.java +111 -0
  22. data/assets/src/RubotoBroadcastReceiver.java +51 -0
  23. data/assets/src/RubotoService.java +61 -0
  24. data/assets/src/org/ruboto/RubotoDialog.java +11 -0
  25. data/assets/src/org/ruboto/Script.java +545 -0
  26. data/assets/src/org/ruboto/test/ActivityTest.java +63 -0
  27. data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +124 -0
  28. data/assets/src/ruboto.rb +621 -0
  29. data/assets/test/assets/scripts/test_helper.rb +13 -0
  30. data/bin/ruboto +5 -0
  31. data/lib/java_class_gen/InheritingClass.java.erb +10 -0
  32. data/lib/java_class_gen/android_api.xml +1 -0
  33. data/lib/ruboto.rb +16 -0
  34. data/lib/ruboto/api.rb +21 -0
  35. data/lib/ruboto/commands/base.rb +392 -0
  36. data/lib/ruboto/core_ext/array.rb +6 -0
  37. data/lib/ruboto/core_ext/object.rb +10 -0
  38. data/lib/ruboto/util/asset_copier.rb +27 -0
  39. data/lib/ruboto/util/build.rb +201 -0
  40. data/lib/ruboto/util/code_formatting.rb +22 -0
  41. data/lib/ruboto/util/log_action.rb +20 -0
  42. data/lib/ruboto/util/main_fix.rb +13 -0
  43. data/lib/ruboto/util/objectspace.rb +8 -0
  44. data/lib/ruboto/util/scan_in_api.rb +40 -0
  45. data/lib/ruboto/util/update.rb +420 -0
  46. data/lib/ruboto/util/verify.rb +87 -0
  47. data/lib/ruboto/util/xml_element.rb +200 -0
  48. data/lib/ruboto/version.rb +3 -0
  49. data/test/activity/image_button_activity.rb +21 -0
  50. data/test/activity/image_button_activity_test.rb +21 -0
  51. data/test/activity/image_button_and_button_activity.rb +24 -0
  52. data/test/activity/image_button_and_button_activity_test.rb +27 -0
  53. data/test/activity/option_menu_activity.rb +21 -0
  54. data/test/activity/option_menu_activity_test.rb +20 -0
  55. data/test/activity/stack_activity.rb +21 -0
  56. data/test/activity/stack_activity_test.rb +23 -0
  57. data/test/app_test_methods.rb +41 -0
  58. data/test/minimal_app_test.rb +23 -0
  59. data/test/rake_test.rb +40 -0
  60. data/test/ruboto_gen_test.rb +32 -0
  61. data/test/ruboto_gen_with_psych_test.rb +16 -0
  62. data/test/ruboto_update_test.rb +5 -0
  63. data/test/ruboto_update_with_psych_test.rb +18 -0
  64. data/test/service_test.rb +49 -0
  65. data/test/test_helper.rb +177 -0
  66. data/test/update_test_methods.rb +33 -0
  67. metadata +157 -0
@@ -0,0 +1,23 @@
1
+ activity org.ruboto.test_app.StackActivity
2
+
3
+ setup do |activity|
4
+ start = Time.now
5
+ loop do
6
+ @text_view = activity.findViewById(42)
7
+ break if @text_view || (Time.now - start > 60)
8
+ sleep 1
9
+ end
10
+ assert @text_view
11
+ end
12
+
13
+ test('stack depth') do |activity|
14
+ os_offset = {13 => 1}[android.os.Build::VERSION::SDK_INT].to_i
15
+ jruby_offset = {
16
+ '1.5.6' => [-2, -5, -6, -8],
17
+ }[org.jruby.runtime.Constants::VERSION] || [0,0,0,0]
18
+ version_message ="ANDROID: #{android.os.Build::VERSION::SDK_INT}, JRuby: #{org.jruby.runtime.Constants::VERSION}"
19
+ assert_equal 44 + os_offset + jruby_offset[0], activity.find_view_by_id(42).text.to_i, version_message
20
+ assert_equal 68 + os_offset + jruby_offset[1], activity.find_view_by_id(43).text.to_i, version_message
21
+ assert_equal 77 + os_offset + jruby_offset[2], activity.find_view_by_id(44).text.to_i, version_message
22
+ assert_equal 96 + os_offset + jruby_offset[3], activity.find_view_by_id(45).text.to_i, version_message
23
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+
3
+ module AppTestMethods
4
+ include RubotoTest
5
+
6
+ def test_activity_tests
7
+ if not ON_JRUBY_JARS_1_5_6
8
+ assert_code 'YamlLoads', "with_large_stack{require 'yaml'}"
9
+ else
10
+ puts "Skipping YAML tests on jruby-jars-1.5.6"
11
+ end
12
+
13
+ assert_code 'ReadSourceFile', "File.read(__FILE__)"
14
+ assert_code 'DirListsFilesInApk', 'Dir["#{File.dirname(__FILE__)}/*"].each{|f| raise "File #{f.inspect} not found" unless File.exists?(f)}'
15
+
16
+ Dir[File.expand_path('activity/*_test.rb', File.dirname(__FILE__))].each do |test_src|
17
+ snake_name = test_src.chomp('_test.rb')
18
+ activity_name = File.basename(snake_name).split('_').map { |s| "#{s[0..0].upcase}#{s[1..-1]}" }.join
19
+ Dir.chdir APP_DIR do
20
+ system "#{RUBOTO_CMD} gen class Activity --name #{activity_name}"
21
+ FileUtils.cp "#{snake_name}.rb", "src/"
22
+ FileUtils.cp test_src, "test/assets/scripts/"
23
+ end
24
+ end
25
+ run_app_tests
26
+ end
27
+
28
+ private
29
+
30
+ def assert_code(activity_name, code)
31
+ snake_name = activity_name.scan(/[A-Z]+[a-z]+/).map { |s| s.downcase }.join('_')
32
+ filename = "src/#{snake_name}_activity.rb"
33
+ Dir.chdir APP_DIR do
34
+ system "#{RUBOTO_CMD} gen class Activity --name #{activity_name}Activity"
35
+ s = File.read(filename)
36
+ s.gsub!(/(require 'ruboto')/, "\\1\n#{code}")
37
+ File.open(filename, 'w') { |f| f << s }
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+ require 'bigdecimal'
3
+
4
+ class MinimalAppTest < Test::Unit::TestCase
5
+ def setup
6
+ generate_app :excluded_stdlibs => %w{ant cgi digest dl drb ffi irb net optparse racc rbconfig rdoc rexml rinda rss rubygems runit shell soap test uri webrick win32 wsdl xmlrpc xsd}
7
+ end
8
+
9
+ def teardown
10
+ cleanup_app
11
+ end
12
+
13
+ def test_minimal_apk_is_less_than_3_mb
14
+ apk_size = BigDecimal(File.size("#{APP_DIR}/bin/RubotoTestApp-debug.apk").to_s) / (1024 * 1024)
15
+ limit = 3.0
16
+ assert apk_size < limit, "APK was larger than #{'%.1f' % limit}MB: #{'%.1f' % apk_size.ceil(1)}MB"
17
+ end
18
+
19
+ def test_minimal_apk_succeeds_tests
20
+ run_app_tests
21
+ end
22
+
23
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+
3
+ class RakeTest < Test::Unit::TestCase
4
+ def setup
5
+ generate_app
6
+ end
7
+
8
+ def teardown
9
+ cleanup_app
10
+ end
11
+
12
+ if ANDROID_OS == 'android-7'
13
+ puts "Skipping sdcard test since files on sdcard are not removed on android-7 on app uninstall"
14
+ else
15
+ def test_that_update_scripts_task_copies_files_to_sdcard_and_are_read_by_activity
16
+ Dir.chdir APP_DIR do
17
+ activity_filename = "src/ruboto_test_app_activity.rb"
18
+ s = File.read(activity_filename)
19
+ s.gsub!(/What hath Matz wrought\?/, "This text was changed by script!")
20
+ File.open(activity_filename, 'w') { |f| f << s }
21
+
22
+ test_filename = "test/assets/scripts/ruboto_test_app_activity_test.rb"
23
+ s2 = File.read(test_filename)
24
+ s2.gsub!(/What hath Matz wrought\?/, "This text was changed by script!")
25
+ File.open(test_filename, 'w') { |f| f << s2 }
26
+
27
+ apk_timestamp = File.ctime("bin/#{APP_NAME}-debug.apk")
28
+ system 'rake test:quick'
29
+ assert_equal 0, $?
30
+
31
+ # FIXME(uwe): Uncomment this when we can build the test package without building the main package
32
+ # assert_equal apk_timestamp, File.ctime("bin/#{APP_NAME}-debug.apk"), 'APK should not have been rebuilt'
33
+ # FIXME end
34
+
35
+ assert `adb shell ls -d /sdcard/Android/data/#{PACKAGE}/files/scripts`.chomp =~ %r{^/sdcard/Android/data/#{PACKAGE}/files/scripts$}
36
+ end
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+ require 'test/app_test_methods'
3
+
4
+ class RubotoGenTest < Test::Unit::TestCase
5
+ include AppTestMethods
6
+
7
+ def setup
8
+ generate_app
9
+ end
10
+
11
+ def teardown
12
+ cleanup_app
13
+ end
14
+
15
+ def test_icons_are_updated
16
+ Dir.chdir APP_DIR do
17
+ assert_equal 4032, File.size('res/drawable-hdpi/icon.png')
18
+ end
19
+ end
20
+
21
+ def test_gen_class_activity_with_lowercase_should_fail
22
+ Dir.chdir APP_DIR do
23
+ system "#{RUBOTO_CMD} gen class activity --name VeryNewActivity"
24
+ assert_equal 1, $?.exitstatus
25
+ assert !File.exists?('src/org/ruboto/test_app/VeryNewActivity.java')
26
+ assert !File.exists?('src/very_new_activity.rb')
27
+ assert !File.exists?('test/assets/scripts/very_new_activity_test.rb')
28
+ assert File.read('AndroidManifest.xml') !~ /VeryNewActivity/
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path("ruboto_gen_test", File.dirname(__FILE__))
2
+
3
+ if not RubotoTest::ON_JRUBY_JARS_1_5_6
4
+ class RubotoGenWithPsychTest < RubotoGenTest
5
+ def setup
6
+ generate_app :with_psych => true
7
+ end
8
+
9
+ def test_psych_jar_exists
10
+ assert File.exists?("#{APP_DIR}/libs/psych.jar"), "Failed to generate psych jar"
11
+ end
12
+
13
+ end
14
+ else
15
+ puts "Skipping Psych tests on jruby-jars-1.5.6"
16
+ end
@@ -0,0 +1,5 @@
1
+ require File.expand_path("update_test_methods", File.dirname(__FILE__))
2
+
3
+ class RubotoUpdateTest < Test::Unit::TestCase
4
+ include UpdateTestMethods
5
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path("update_test_methods", File.dirname(__FILE__))
2
+
3
+ if not RubotoTest::ON_JRUBY_JARS_1_5_6
4
+ class RubotoUpdateWithPsychTest < Test::Unit::TestCase
5
+ include UpdateTestMethods
6
+
7
+ def setup
8
+ super(true)
9
+ end
10
+
11
+ def test_psych_jar_exists
12
+ assert File.exists?("#{APP_DIR}/libs/psych.jar"), "Failed to generate psych jar"
13
+ end
14
+
15
+ end
16
+ else
17
+ puts "Skipping Psych tests on jruby-jars-1.5.6"
18
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+ require 'fileutils'
3
+
4
+ class ServiceTest < Test::Unit::TestCase
5
+ SRC_DIR ="#{APP_DIR}/src"
6
+
7
+ def setup
8
+ generate_app
9
+ end
10
+
11
+ def teardown
12
+ cleanup_app
13
+ end
14
+
15
+ def test_service_startup
16
+ Dir.chdir APP_DIR do
17
+ system "#{RUBOTO_CMD} gen class Service --name RubotoTestService"
18
+ service_filename = "#{SRC_DIR}/ruboto_test_service.rb"
19
+ assert File.exists? service_filename
20
+ File.open(service_filename, 'w'){|f| f << <<EOF}
21
+ require 'ruboto'
22
+
23
+ $service.handle_create do
24
+ Thread.start do
25
+ loop do
26
+ sleep 1
27
+ puts "\#{self.class} running..."
28
+ end
29
+ end
30
+ puts "\#{self.class} started."
31
+ android.app.Service::START_STICKY
32
+ end
33
+
34
+ $service.handle_start_command do
35
+ android.app.Service::START_STICKY
36
+ end
37
+ EOF
38
+
39
+ activity_filename = "#{SRC_DIR}/ruboto_test_app_activity.rb"
40
+ s = File.read(activity_filename)
41
+ s.gsub!(/^(end)$/, "
42
+ startService(android.content.Intent.new($activity.application_context, $package.RubotoTestService.java_class))
43
+ \\1\n")
44
+ File.open(activity_filename, 'w') { |f| f << s }
45
+ end
46
+ run_app_tests
47
+ end
48
+
49
+ end
@@ -0,0 +1,177 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'fileutils'
4
+ require 'yaml'
5
+
6
+ module RubotoTest
7
+ PROJECT_DIR = File.expand_path('..', File.dirname(__FILE__))
8
+ $LOAD_PATH << PROJECT_DIR
9
+
10
+ # FIXME(uwe): Simplify when we stop supporting rubygems < 1.8.0
11
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.8.0')
12
+ gem_spec = Gem::Specification.find_by_path 'jruby-jars'
13
+ else
14
+ gem_spec = Gem.searcher.find('jruby-jars')
15
+ end
16
+ # FIXME end
17
+
18
+ raise StandardError.new("Can't find Gem specification jruby-jars.") unless gem_spec
19
+ JRUBY_JARS_VERSION = gem_spec.version
20
+
21
+ # FIXME(uwe): Remove when we stop supporting JRuby 1.5.6
22
+ ON_JRUBY_JARS_1_5_6 = JRUBY_JARS_VERSION == Gem::Version.new('1.5.6')
23
+
24
+ PACKAGE = 'org.ruboto.test_app'
25
+ APP_NAME = 'RubotoTestApp'
26
+ TMP_DIR = File.join PROJECT_DIR, 'tmp'
27
+ APP_DIR = File.join TMP_DIR, APP_NAME
28
+ ANDROID_TARGET = ENV['ANDROID_TARGET'] || 'android-7'
29
+
30
+ VERSION_TO_API_LEVEL = {
31
+ '2.1' => 'android-7', '2.1-update1' => 'android-7', '2.2' => 'android-8',
32
+ '2.3' => 'android-9', '2.3.1' => 'android-9', '2.3.2' => 'android-9',
33
+ '2.3.3' => 'android-10', '2.3.4' => 'android-10',
34
+ '3.0' => 'android-11', '3.1' => 'android-12', '3.2' => 'android-13',
35
+ '4.0.1' => 'android-14', '4.0.3' => 'android-15',
36
+ }
37
+
38
+ def self.version_from_device
39
+ puts "Reading OS version from device/emulator"
40
+ system "adb wait-for-device"
41
+ start = Time.now
42
+ IO.popen('adb bugreport').each_line do |line|
43
+ if line =~ /sdk-eng (.*?) .*? .*? test-keys/
44
+ version = $1
45
+ api_level = VERSION_TO_API_LEVEL[version]
46
+ raise "Unknown version: #{version}" if api_level.nil?
47
+ puts "Getting version from device/emulator took #{(Time.now - start).to_i}s"
48
+ return api_level
49
+ end
50
+ if line =~ /\[ro\.build\.version\.sdk\]: \[(\d+)\]/
51
+ return $1
52
+ end
53
+ end
54
+ raise "Unable to read device/emulator apilevel"
55
+ end
56
+
57
+ ANDROID_OS = ENV['ANDROID_OS'] || version_from_device
58
+ RUBOTO_CMD = "ruby -rubygems -I #{PROJECT_DIR}/lib #{PROJECT_DIR}/bin/ruboto"
59
+
60
+ puts "ANDROID_OS: #{ANDROID_OS}"
61
+ end
62
+
63
+ class Test::Unit::TestCase
64
+ include RubotoTest
65
+ alias old_run run
66
+
67
+ def run(*args, &block)
68
+ mark_test_start("#{self.class.name}\##{method_name}")
69
+ old_run(*args, &block)
70
+ mark_test_end("#{self.class.name}\##{method_name}")
71
+ end
72
+
73
+ def mark_test_start(test_name)
74
+ @start_time = Time.now
75
+ log
76
+ log '=' * 80
77
+ log "Starting test #{test_name} at #{@start_time.strftime('%Y-%m-%d %H:%M:%S')}:"
78
+ log
79
+ end
80
+
81
+ def mark_test_end(test_name)
82
+ log
83
+ log "Ended test #{test_name}: #{passed? ? 'PASSED' : 'FAILED'} after #{(Time.now - @start_time).to_i}s"
84
+ log '=' * 80
85
+ log
86
+ end
87
+
88
+ def log(message = '')
89
+ puts message
90
+ system "adb shell log -t 'RUBOTO TEST' '#{message}'"
91
+ end
92
+
93
+ def generate_app(options = {})
94
+ with_psych = options.delete(:with_psych) || false
95
+ update = options.delete(:update) || false
96
+ excluded_stdlibs = options.delete(:excluded_stdlibs)
97
+ raise "Unknown options: #{options.inspect}" unless options.empty?
98
+ Dir.mkdir TMP_DIR unless File.exists? TMP_DIR
99
+
100
+ if with_psych || excluded_stdlibs
101
+ system 'rake platform:uninstall'
102
+ else
103
+ system 'rake platform:install'
104
+ end
105
+ if $? != 0
106
+ FileUtils.rm_rf 'tmp/RubotoCore'
107
+ fail 'Error (un)installing RubotoCore'
108
+ end
109
+
110
+ FileUtils.rm_rf APP_DIR if File.exists? APP_DIR
111
+ template_dir = "#{APP_DIR}_template_#{$$}#{'_with_psych' if with_psych}#{'_updated' if update}#{"_without_#{excluded_stdlibs.join('_')}" if excluded_stdlibs}"
112
+ if File.exists?(template_dir)
113
+ puts "Copying app from template #{template_dir}"
114
+ FileUtils.cp_r template_dir, APP_DIR, :preserve => true
115
+ else
116
+ if update
117
+ Dir.chdir TMP_DIR do
118
+ system "tar xzf #{PROJECT_DIR}/examples/RubotoTestApp_0.1.0_jruby_1.6.3.dev.tgz"
119
+ end
120
+ if ENV['ANDROID_HOME']
121
+ android_home = ENV['ANDROID_HOME']
122
+ else
123
+ android_home = File.dirname(File.dirname(`which adb`))
124
+ end
125
+ Dir.chdir APP_DIR do
126
+ File.open('local.properties', 'w') { |f| f.puts "sdk.dir=#{android_home}" }
127
+ File.open('test/local.properties', 'w') { |f| f.puts "sdk.dir=#{android_home}" }
128
+ FileUtils.touch "libs/psych.jar" if with_psych
129
+ exclude_stdlibs(excluded_stdlibs) if excluded_stdlibs
130
+ system "#{RUBOTO_CMD} update app"
131
+ assert_equal 0, $?, "update app failed with return code #$?"
132
+ end
133
+ else
134
+ puts "Generating app #{APP_DIR}"
135
+ system "#{RUBOTO_CMD} gen app --package #{PACKAGE} --path #{APP_DIR} --name #{APP_NAME} --target #{ANDROID_TARGET} #{'--with-psych' if with_psych}"
136
+ if $? != 0
137
+ FileUtils.rm_rf APP_DIR
138
+ raise "gen app failed with return code #$?"
139
+ end
140
+ if excluded_stdlibs
141
+ Dir.chdir APP_DIR do
142
+ exclude_stdlibs(excluded_stdlibs)
143
+ system "#{RUBOTO_CMD} update jruby --force"
144
+ raise "update jruby failed with return code #$?" if $? != 0
145
+ end
146
+ end
147
+ end
148
+ Dir.chdir APP_DIR do
149
+ system 'rake debug'
150
+ assert_equal 0, $?
151
+ end
152
+ puts "Storing app as template #{template_dir}"
153
+ FileUtils.cp_r APP_DIR, template_dir, :preserve => true
154
+ end
155
+ end
156
+
157
+ def cleanup_app
158
+ # FileUtils.rm_rf APP_DIR if File.exists? APP_DIR
159
+ end
160
+
161
+ def run_app_tests
162
+ if ['android-7', 'android-8'].include? ANDROID_OS
163
+ puts "Skipping instrumentation tests on #{ANDROID_OS} since they don't work."
164
+ else
165
+ Dir.chdir APP_DIR do
166
+ system 'rake test:quick'
167
+ assert_equal 0, $?, "tests failed with return code #$?"
168
+ end
169
+ end
170
+ end
171
+
172
+ def exclude_stdlibs(excluded_stdlibs)
173
+ puts "Adding ruboto.yml: #{excluded_stdlibs.join(' ')}"
174
+ File.open('ruboto.yml', 'w') { |f| f << YAML.dump({:excluded_stdlibs => excluded_stdlibs}) }
175
+ end
176
+
177
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+ require 'test/app_test_methods'
3
+
4
+ module UpdateTestMethods
5
+ include RubotoTest
6
+ include AppTestMethods
7
+
8
+ def setup(with_psych = false)
9
+ generate_app(:with_psych => with_psych, :update => true)
10
+ end
11
+
12
+ def teardown
13
+ cleanup_app
14
+ end
15
+
16
+ def test_properties_and_ant_file_has_no_duplicates
17
+ Dir.chdir APP_DIR do
18
+ # FIXME(uwe): Cleanup when we stop support Android SDK <= 13
19
+ prop_file = %w{test/ant.properties test/build.properties}.find{|f| File.exists?(f)}
20
+ # FIXME end
21
+
22
+ assert File.readlines(prop_file).grep(/\w/).uniq!.nil?, "Duplicate lines in #{prop_file}"
23
+ assert_equal 1, File.readlines('test/build.xml').grep(/<macrodef name="run-tests-helper">/).size, 'Duplicate macro in build.xml'
24
+ end
25
+ end
26
+
27
+ def test_icons_are_untouched
28
+ Dir.chdir APP_DIR do
29
+ assert_equal 4100, File.size('res/drawable-hdpi/icon.png')
30
+ end
31
+ end
32
+
33
+ end