gamnit: make `SpriteSet` public so clients can use its services
[nit.git] / lib / android / nit_activity.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Some documentation of this module has been adapted from the
16 # Android Open Source Project.
17
18 # Core implementation of `app.nit` on Android using a custom Java entry point
19 #
20 # This module is implemented in 3 languages:
21 #
22 # * The Java code, in `NitActivity.java` acts as the entry point registered
23 # to the Android OS. It relays most of the Android callbacks to C.
24 # In theory, there may be more than one instance of `NitActivity` alive at
25 # a given time. They hold a reference to the corresponding Nit `Activity`
26 # in the attribute `nitActivity`.
27 #
28 # * The C code is defined in the top part of this source file. It acts as a
29 # glue between Java and Nit by relaying calls between both languages.
30 # It keeps a global variables reference to the Java VM and the Nit `App`.
31 #
32 # * The Nit code defines the `Activity` class with the callbacks from Android.
33 # The callback methods should be redefined by user modules.
34 #
35 # The main is invoked when the native library is dynamically linked by
36 # the Java virtual machine. For this reason, the main _must_ execute quickly,
37 # on the main UI thread at least.
38 module nit_activity is
39 extra_java_files "NitActivity.java"
40 android_activity "nit.app.NitActivity"
41 end
42
43 import platform
44 import log
45 import activities
46 import key_event
47 import bundle
48 import dalvik
49
50 in "C body" `{
51
52 #include <jni.h>
53 #include <android/log.h>
54
55 // Nit's App running instance
56 App global_app;
57
58 // Java VM that launched this program
59 JavaVM *global_jvm;
60
61 // JNI callback on loading this program
62 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
63 // Set aside the Java VM
64 global_jvm = vm;
65
66 // Invoke Nit system and main
67 main(0, NULL);
68
69 return JNI_VERSION_1_2;
70 }
71
72 /*
73 * Implementations of NitActivity.java native methods
74 */
75
76 JNIEXPORT jint JNICALL Java_nit_app_NitActivity_nitRegisterActivity
77 (JNIEnv *env, jobject java_activity)
78 {
79 Activity nit_activity = App_register_activity(global_app, java_activity);
80 Activity_incr_ref(nit_activity);
81 return (jint)(void*)nit_activity;
82 }
83
84 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnCreate
85 (JNIEnv *env, jobject java_activity, jint nit_activity, jobject saved_state)
86 {
87 Activity_on_create((Activity)nit_activity, saved_state);
88 }
89
90 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnStart
91 (JNIEnv *env, jobject java_activity, jint nit_activity)
92 {
93 Activity_on_start((Activity)nit_activity);
94 }
95
96 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnRestart
97 (JNIEnv *env, jobject java_activity, jint nit_activity)
98 {
99 Activity_on_restart((Activity)nit_activity);
100 }
101
102 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnResume
103 (JNIEnv *env, jobject java_activity, jint nit_activity)
104 {
105 Activity_on_resume((Activity)nit_activity);
106 }
107
108 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnPause
109 (JNIEnv *env, jobject java_activity, jint nit_activity)
110 {
111 Activity_on_pause((Activity)nit_activity);
112 }
113
114 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnStop
115 (JNIEnv *env, jobject java_activity, jint nit_activity)
116 {
117 Activity_on_stop((Activity)nit_activity);
118 }
119
120 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnDestroy
121 (JNIEnv *env, jobject java_activity, jint nit_activity)
122 {
123 Activity_on_destroy((Activity)nit_activity);
124 }
125
126 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnSaveInstanceState
127 (JNIEnv *env, jobject java_activity, jint nit_activity, jobject saved_state)
128 {
129 Activity_on_save_instance_state((Activity)nit_activity, saved_state);
130 }
131
132 JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnRestoreInstanceState
133 (JNIEnv *env, jobject java_activity, jint nit_activity, jobject saved_state)
134 {
135 Activity_on_restore_instance_state((Activity)nit_activity, saved_state);
136 }
137
138 JNIEXPORT jboolean JNICALL Java_nit_app_NitActivity_nitOnBackPressed
139 (JNIEnv *env, jobject java_activity, jint nit_activity)
140 {
141 return (jboolean)Activity_on_back_pressed((Activity)nit_activity);
142 }
143
144 JNIEXPORT jboolean JNICALL Java_nit_app_NitActivity_nitOnKeyDown
145 (JNIEnv *env, jobject java_activity, jint nit_activity, jint keyCode, jobject event)
146 {
147 return (jboolean)Activity_on_key_down((Activity)nit_activity, keyCode, event);
148 }
149
150 JNIEXPORT jboolean JNICALL Java_nit_app_NitActivity_nitOnKeyLongPress
151 (JNIEnv *env, jobject java_activity, jint nit_activity, jint keyCode, jobject event)
152 {
153 return (jboolean)Activity_on_key_long_press((Activity)nit_activity, keyCode, event);
154 }
155
156 JNIEXPORT jboolean JNICALL Java_nit_app_NitActivity_nitOnKeyMultiple
157 (JNIEnv *env, jobject java_activity, jint nit_activity, jint keyCode, jint count, jobject event)
158 {
159 return (jboolean)Activity_on_key_multiple((Activity)nit_activity, keyCode, count, event);
160 }
161
162 JNIEXPORT jboolean JNICALL Java_nit_app_NitActivity_nitOnKeyUp
163 (JNIEnv *env, jobject java_activity, jint nit_activity, jint keyCode, jobject event)
164 {
165 return (jboolean)Activity_on_key_up((Activity)nit_activity, keyCode, event);
166 }
167 `}
168
169 # Wrapper to our Java `NitActivity`
170 extern class NativeNitActivity in "Java" `{ nit.app.NitActivity `}
171 super NativeActivity
172 end
173
174 redef class Sys
175 redef fun jvm `{ return global_jvm; `}
176 end
177
178 redef class App
179 # Known activities
180 var activities = new Array[Activity]
181
182 # The main Java Activity of this application
183 redef fun native_activity do return activities.first.native
184
185 redef fun setup do set_global_app
186
187 # Register app in C
188 private fun set_global_app import register_activity,
189 Activity.on_create, Activity.on_destroy,
190 Activity.on_start, Activity.on_restart, Activity.on_stop,
191 Activity.on_pause, Activity.on_resume,
192 Activity.on_save_instance_state, Activity.on_restore_instance_state,
193 Activity.on_back_pressed,
194 Activity.on_key_down, Activity.on_key_long_press,
195 Activity.on_key_multiple, Activity.on_key_up `{
196 App_incr_ref(self);
197 global_app = self;
198 `}
199
200 # Create the Nit side to this new `native` Java activity, and return it to Java
201 private fun register_activity(native: NativeNitActivity): Activity
202 do
203 native = native.new_global_ref
204 var activity = new Activity(native)
205 activities.add activity
206 return activity
207 end
208 end
209
210 redef class AppComponent
211 # The application is starting or restarting, it is visible to the user
212 fun on_start do end
213
214 # The application is being destroyed
215 fun on_destroy do end
216 end
217
218 # An Android activity
219 #
220 # You must implement the callbacks (prefixed with `on_`) to follow the
221 # standard Android life-cycle.
222 class Activity
223 # Native Java activity
224 var native: NativeActivity
225
226 # Notification from Android, the activity is created
227 #
228 # Do your normal static set up here.
229 #
230 # If available, `save_state` contains the activity's previous state
231 # as registered by `on_save_instance_state`.
232 #
233 # Followed by `on_start`.
234 fun on_create(save_state: NativeBundle)
235 do
236 app.on_create
237 app.on_restore_state
238 end
239
240 # Notification from Android, the activity has been restarted
241 #
242 # Followed by `on_start`.
243 fun on_restart do app.on_restart
244
245 # Notification from Android, the activity has been started
246 #
247 # Followed by `on_resume` or `on_stop`.
248 fun on_start do app.on_start
249
250 # Notification from Android, the activity has been resumed
251 #
252 # Followed by `on_pause`
253 fun on_resume do app.on_resume
254
255 # Notification from Android, the activity has been paused
256 #
257 # Followed by `on_resume` or `on_stop`.
258 fun on_pause do app.on_pause
259
260 # Notification from Android, the activity has been stopped
261 #
262 # Followed by `on_restart` or `on_destroy`.
263 fun on_stop do app.on_stop
264
265 # Notification from Android, the activity is being destroyed
266 #
267 # Clean up and exit.
268 fun on_destroy
269 do
270 app.on_destroy
271
272 native.delete_global_ref
273 app.activities.remove self
274 end
275
276 # Notification from Android, the activity is being re-initialized from a `save_state`
277 #
278 # Occurs after `on_start`.
279 fun on_restore_instance_state(save_state: NativeBundle) do end
280
281 # Notification from Android, the activity may be stopped, save state
282 #
283 # Occurs before `on_stop` and, without guarantee, before or after `on_pause`.
284 fun on_save_instance_state(save_state: NativeBundle) do app.on_save_state
285
286 # Notification from Android, the system is running low on memory
287 #
288 # Try to reduce your memory use.
289 fun on_low_memory do end
290
291 # Notification from Android, the current window of the activity has lost or gained focus
292 fun on_window_focus_changed(has_focus: Bool) do end
293
294 # Notification from Android, the current device configuration has changed
295 fun on_configuration_changed do end
296
297 # The back key has been pressed
298 #
299 # Return `true` if the event has been handled.
300 fun on_back_pressed: Bool do return false
301
302 # A key has been pressed
303 #
304 # Return `true` if the event has been handled.
305 fun on_key_down(key_code: Int, event: NativeKeyEvent): Bool do return false
306
307 # A key has been long pressed
308 #
309 # Return `true` if the event has been handled.
310 fun on_key_long_press(key_code: Int, event: NativeKeyEvent): Bool do return false
311
312 # Multiple down/up pairs of the same key have occurred in a row
313 #
314 # Return `true` if the event has been handled.
315 fun on_key_multiple(key_code, count: Int, event: NativeKeyEvent): Bool do return false
316
317 # A key has been released
318 #
319 # Return `true` if the event has been handled.
320 fun on_key_up(key_code: Int, event: NativeKeyEvent): Bool do return false
321 end
322
323 # Set up global data in C and leave it to Android to callback Java, which we relay to Nit
324 app.setup