1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Some documentation of this module has been adapted from the documentation
18 # of the Android NDK projet.
20 # Wrapper of the Android native_app_glue framework to implement app.nit
22 # The framework provides 3 different structures for a single C application
23 # under Android. We use all 3 structures in this API to implement app.nit
24 # on Android. Each structure is wrapped in a Nit extern class:
26 # * `NativeAppGlue` is the lowest level class, it is implemented by the C
27 # structure `android_app`. It offers features on the main Android thread
28 # (not on the same thread as Nit). For this reason, prefer to use
29 # `NdkNativeActivity`.
31 # * `NdkNativeActivity` is implemented by the C structure `ANativeActivity`. It
32 # is on the same thread as Nit and manages the synchronization with the
33 # main Android thread.
35 # * `NativeNativeActivity` is implemented in Java by `android.app.NativeActivity`,
36 # which is a subclass of `Activity` and `Context` (in Java). It represent
37 # main activity of the running application. Use it to get anything related
38 # to the `Context` and as anchor to execute Java UI code.
39 module native_app_glue
is
40 ldflags
("-landroid", "-lnative_app_glue")
41 android_activity
"android.app.NativeActivity"
49 #include <android_native_app_glue.h>
53 struct android_app* native_app_glue_data;
55 // Entry point called by the native_app_glue_framework framework
56 // We relay the call to the Nit application.
57 void android_main(struct android_app* app) {
58 native_app_glue_data = app;
60 int main(int argc, char ** argv);
64 // Main callback on the native_app_glue framework
66 // We relay everything to our App.
67 static void app_cmd_handler(struct android_app* app, int32_t cmd) {
68 App nit_app = app->userData;
70 case APP_CMD_SAVE_STATE:
71 App_save_state(nit_app);
73 case APP_CMD_INIT_WINDOW:
74 App_init_window(nit_app);
76 case APP_CMD_TERM_WINDOW:
77 App_term_window(nit_app);
79 case APP_CMD_GAINED_FOCUS:
80 App_gained_focus(nit_app);
82 case APP_CMD_LOST_FOCUS:
83 App_lost_focus(nit_app);
100 case APP_CMD_LOW_MEMORY:
101 App_low_memory(nit_app);
103 case APP_CMD_CONFIG_CHANGED:
104 App_config_changed(nit_app);
106 case APP_CMD_INPUT_CHANGED:
107 App_input_changed(nit_app);
109 case APP_CMD_WINDOW_RESIZED:
110 App_window_resized(nit_app);
112 case APP_CMD_WINDOW_REDRAW_NEEDED:
113 App_window_redraw_needed(nit_app);
115 case APP_CMD_CONTENT_RECT_CHANGED:
116 App_content_rect_changed(nit_app);
122 # Android SDK's `android.app.NativeActivity`.
124 # Can be used to get anything related to the `Context` of the activity in Java
125 # and as anchor to execute Java UI code.
126 extern class NativeNativeActivity in "Java" `{ android.app.NativeActivity `}
131 redef fun jvm do return app.native_app_glue.ndk_native_activity.vm
137 var native_app_glue = native_app_glue
138 native_app_glue.user_data = self
140 set_as_cmd_handler(native_app_glue)
143 # The underlying implementation using the Android native_app_glue framework
144 fun native_app_glue: NativeAppGlue `{ return native_app_glue_data; `}
146 redef fun native_activity
do return native_app_glue
.ndk_native_activity
.java_native_activity
148 # Set `native_app_glue` command handler to our C implementation which
149 # will callback self.
150 private fun set_as_cmd_handler
(native_app_glue
: NativeAppGlue) import save_state
,
151 init_window
, term_window
, gained_focus
, lost_focus
, pause
, stop
, destroy
,
152 start
, resume
, low_memory
, config_changed
, input_changed
, window_resized
,
153 window_redraw_needed
, content_rect_changed
`{
154 native_app_glue->onAppCmd = &app_cmd_handler;
157 # Notification from the Android framework to generate a new saved state
159 # You can use the `shared_preferences` module or `NativeAppGlue::saved_state`.
160 fun save_state
do end
162 # Notification from the native_app glue framework, a new ANativeWindow is ready
164 # When called, `NativeAppGlue::window` returns a poiter to the new window surface.
165 fun init_window
do end
167 # Notification from the native_app glue framework, the existing window needs to be terminated
169 # Upon receiving this command, `native_app_glue.window` still contains the existing window.
170 fun term_window
do end
172 # Notification from the Android framework, `native_activity` has gained focus
173 fun gained_focus
do end
175 # Notification from the Android framework, `native_activity` has lost focus
176 fun lost_focus
do end
178 # Notification from the Android framework, your app has been paused
181 # Notification from the Android framework, your app has been stopped
184 # Notification from the Android framework, `native_activity` is being destroyed
189 # Notification from the Android framework, `native_activity` has been started
192 # Notification from the Android framework, `native_activity` has been resumed
195 # Notification from the Android framework, the system is running low on memory
197 # Try to reduce your memory use.
198 fun low_memory
do force_garbage_collection
200 # Notification from the Android framework, the current device configuration has changed
201 fun config_changed
do end
203 # Notification from the Android framework, `native_app_glue.input_queue` has changed
204 fun input_changed
do end
206 # Notification from the Android framework, the window has been resized.
208 # Please redraw with its new size.
209 fun window_resized
do end
211 # Notification from the Android framework, the current ANativeWindow must be redrawn
212 fun window_redraw_needed
do end
214 # Notification from the Android framework, the content area of the window has changed
216 # Raised when the soft input window being shown or hidden, and similar events.
217 fun content_rect_changed
do end
219 # Call the `ALooper` to retrieve events and callback the application
220 fun poll_looper
(timeout_ms
: Int) import handle_looper_event
`{
224 while ((ident=ALooper_pollAll(timeout_ms, NULL, &event, &source)) >= 0) {
225 App_handle_looper_event(self, ident, event, source);
229 # Handle an event retrieved by the `ALooper` and `poll_looper` without a callback
230 protected fun handle_looper_event
(ident
, event
: Int, data
: Pointer) import native_app_glue
,
231 save_state
, init_window
, term_window
, gained_focus
, lost_focus
, pause
, stop
,
232 destroy
, start
, resume
, low_memory
, config_changed
, input_changed
,
233 window_resized
, window_redraw_needed
, content_rect_changed
`{
235 struct android_app *app_glue = App_native_app_glue(self);
236 struct android_poll_source* source = (struct android_poll_source*)data;
238 // Process this event.
239 if (source != NULL) source->process(app_glue, source);
243 # An Android activity implemented in C. This is the C part of `NativeActivity`
244 # which is the Java part.
246 # The callbacks at this level are synchronous on the UI thread. Thus app.nit
247 # do not use them, and instead rely on `NativeAppGlue`.
248 extern class NdkNativeActivity `{ ANativeActivity * `}
250 # Callbacks on the main thread
251 # FIXME This would not yet be usable, to implement when Nit has threads
252 #fun set_callbacks_handler(handler: App) or callbacks= ...
254 # Java VM associated to `self`
255 fun vm: JavaVM `{ return self->vm; `}
257 # JNI environmnet associated to `self`
258 fun env
: JniEnv `{ return self->env; `}
260 # The `NativeActivity`, as in the Java object, associated to `self`
261 fun java_native_activity: NativeActivity `{ return self->clazz; `}
263 # Path to this application's internal data directory.
264 fun internal_data_path
: CString `{ return (char*)self->internalDataPath; `}
266 # Path to this application's external (removable/mountable) data directory.
267 fun external_data_path: CString `{ return (char*)self->externalDataPath; `}
269 # The platform's SDK version code.
270 fun sdk_version
: Int `{ return self->sdkVersion; `}
272 # This is the native instance of the application. It is not used by
273 # the framework, but can be set by the application to its own instance
275 fun instance: Pointer `{ return self->instance; `}
277 # Pointer to the Asset Manager instance for the application. The application
278 # uses this to access binary assets bundled inside its own .apk file.
280 # TODO activate in a future `asset_manager` module if it cannot be done in Java
281 #fun asset_manager: AssetManager `{ return self->assetManager; `}
283 # Available starting with Honeycomb: path to the directory containing
284 # the application's OBB files (if any). If the app doesn't have any
285 # OBB files, this directory may not exist.
288 # TODO activate in a future module at API 11
289 #fun obb_path: CString `{ return (char*)self->obbPath; `}
292 # This is the interface for the standard glue code of a threaded
293 # application. In this model, the application's code is running
294 # in its own thread separate from the main thread of the process.
295 # It is not required that this thread be associated with the Java
296 # VM, although it will need to be in order to make JNI calls any
298 extern class NativeAppGlue `{ struct android_app* `}
299 # We use the `userData
` field of the C structure to store an handle to
301 private fun user_data: App `{ return self->userData; `}
302 private fun user_data
=(val
: App) `{
304 self->userData = val;
307 # Fill this in with the function to process input events. At this point
308 # the event has already been pre-dispatched, and it will be finished upon
309 # return. Return 1 if you have handled the event, 0 for any default
311 #int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
312 #fun set_input_event_handler(handler: App) `{ `}
314 # The ANativeActivity object instance that this app is running in.
315 fun ndk_native_activity
: NdkNativeActivity `{ return self->activity; `}
317 # The current configuration the app is running in.
318 fun config: AConfiguration `{ return self->config; `}
320 # This is the last instance's saved state, as provided at creation time.
321 # It is NULL if there was no state. You can use this as you need; the
322 # memory will remain around until you call android_app_exec_cmd() for
323 # APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
324 # These variables should only be changed when processing a APP_CMD_SAVE_STATE,
325 # at which point they will be initialized to NULL and you can malloc your
326 # state and place the information here. In that case the memory will be
327 # freed for you later.
328 fun saved_state
: Pointer `{ return self->savedState; `}
329 fun saved_state_size: Int `{ return self->savedStateSize; `}
331 # The ALooper associated with the app's thread.
332 fun looper
: ALooper `{ return self->looper; `}
334 # When non-NULL, this is the input queue from which the app will
335 # receive user input events.
336 fun input_queue: AInputQueue `{ return self->inputQueue; `}
338 # When non-NULL, this is the window surface that the app can draw in.
339 fun window
: ANativeWindow `{ return self->window; `}
341 # Current content rectangle of the window; this is the area where the
342 # window's content should be placed to be seen by the user.
344 # TODO activate when we know what to return (returns a struct not a pointer)
345 #fun content_self: ARect `{ return self->contentRect; `}
347 # Current state of the app's activity. May be either APP_CMD_START,
348 # APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
349 fun activity_state
: Int `{ return self->activityState; `}
351 # This is non-zero when the application's NativeActivity is being
352 # destroyed and waiting for the app thread to complete.
353 fun detroy_request: Bool `{ return self->destroyRequested; `}
356 # Android NDK's struture holding configurations of the native app
357 extern class AConfiguration `{ AConfiguration* `}
360 # Android NDK's structure to handle events synchronously
361 extern class ALooper `{ ALooper* `}
362 # Returns the looper associated with the calling thread, or NULL if there is not one
363 new for_thread
`{ return ALooper_forThread(); `}
366 # Android NDK's struture to handle input events synchronously
367 extern class AInputQueue `{ AInputQueue* `}
370 # Android NDK's structure to control the native window for drawing
371 extern class ANativeWindow `{ ANativeWindow* `}
372 # Change the format and size of the window buffers
374 # All arguments can be set to 0 to use the default devices values.
375 # `width
` and `height
` must both be set to 0 or have significant values.
377 # `format
` is a value specified by EGL.
378 fun set_buffers_geometry(width, height, format: Int): Bool `{
379 return ANativeWindow_setBuffersGeometry(self, (int32_t
)width
, (int32_t
)height
, (int32_t
)format
);