lib/android: intro our very own NitActivity
authorAlexis Laferrière <alexis.laf@xymus.net>
Sun, 3 Aug 2014 00:09:47 +0000 (20:09 -0400)
committerAlexis Laferrière <alexis.laf@xymus.net>
Wed, 18 Mar 2015 12:37:57 +0000 (08:37 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

lib/android/NitActivity.java [new file with mode: 0644]
lib/android/nit_activity.nit [new file with mode: 0644]

diff --git a/lib/android/NitActivity.java b/lib/android/NitActivity.java
new file mode 100644 (file)
index 0000000..3744988
--- /dev/null
@@ -0,0 +1,111 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package nit.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/*
+ * Entry point to Nit applications on Android, redirect most calls to Nit
+ */
+public class NitActivity extends Activity {
+
+       // Nit activity associated to `this`
+       protected int nitActivity = 0;
+
+       /*
+        * Calls to Nit or to the C framework
+        */
+
+       static {
+               System.loadLibrary("main");
+       }
+
+       /*
+        * Callbacks to Nit through C
+        */
+       protected native int nitRegisterActivity();
+       protected native void nitOnCreate(int activity, Bundle savedInstanceState);
+       protected native void nitOnStart(int activity);
+       protected native void nitOnRestart(int activity);
+       protected native void nitOnResume(int activity);
+       protected native void nitOnPause(int activity);
+       protected native void nitOnStop(int activity);
+       protected native void nitOnDestroy(int activity);
+       protected native void nitOnSaveInstanceState(int activity, Bundle savedInstanceState);
+       protected native void nitOnRestoreInstanceState(int activity, Bundle savedInstanceState);
+
+       /*
+        * Implementation of OS callbacks
+        */
+
+       @Override
+       public void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               nitActivity = nitRegisterActivity();
+
+               nitOnCreate(nitActivity, savedInstanceState);
+       }
+
+       @Override
+       protected void onStart() {
+               super.onStart();
+               nitOnStart(nitActivity);
+       }
+
+       @Override
+       protected void onRestart() {
+               super.onRestart();
+               nitOnRestart(nitActivity);
+       }
+
+       @Override
+       protected void onResume() {
+               super.onResume();
+               nitOnResume(nitActivity);
+       }
+
+       @Override
+       protected void onPause() {
+               super.onPause();
+               nitOnPause(nitActivity);
+       }
+
+       @Override
+       protected void onStop() {
+               super.onStop();
+               nitOnStop(nitActivity);
+       }
+
+       @Override
+       protected void onDestroy() {
+               super.onDestroy();
+               nitOnDestroy(nitActivity);
+       }
+
+       @Override
+       public void onSaveInstanceState(Bundle savedInstanceState) {
+               super.onSaveInstanceState(savedInstanceState);
+               nitOnSaveInstanceState(nitActivity, savedInstanceState);
+       }
+
+       @Override
+       public void onRestoreInstanceState(Bundle savedInstanceState) {
+               super.onRestoreInstanceState(savedInstanceState);
+               nitOnRestoreInstanceState(nitActivity, savedInstanceState);
+       }
+}
diff --git a/lib/android/nit_activity.nit b/lib/android/nit_activity.nit
new file mode 100644 (file)
index 0000000..765ed01
--- /dev/null
@@ -0,0 +1,251 @@
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Some documentation of this module has been adapted from the
+# Android Open Source Project.
+
+# Core implementation of `app.nit` on Android using a custom Java entry point
+#
+# This module is implemented in 3 languages:
+#
+# * The Java code, in `NitActivity.java` acts as the entry point registered
+#   to the Android OS. It relays most of the Android callbacks to C.
+#   In theory, there may be more than one instance of `NitActivity` alive at
+#   a given time. They hold a reference to the corresponding Nit `Activity`
+#   in the attribute `nitActivity`.
+#
+# * The C code is defined in the top part of this source file. It acts as a
+#   glue between Java and Nit by relaying calls between both languages.
+#   It keeps a global variables reference to the Java VM and the Nit `App`.
+#
+# * The Nit code defines the `Activity` class with the callbacks from Android.
+#   The callback methods should be redefined by user modules.
+#
+# The main is invoked when the native library is dynamically linked by
+# the Java virtual machine. For this reason, the main _must_ execute quickly,
+# on the main UI thread at least.
+module nit_activity is
+       extra_java_files "NitActivity.java"
+       android_activity "nit.app.NitActivity"
+end
+
+import platform
+import log
+import activities
+import bundle
+import dalvik
+
+in "C body" `{
+
+       #include <jni.h>
+       #include <android/log.h>
+
+       // Nit's App running instance
+       App global_app;
+
+       // Java VM that launched this program
+       JavaVM *global_jvm;
+
+       // JNI callback on loading this program
+       jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+               // Set aside the Java VM
+               global_jvm = vm;
+
+               // Invoke Nit system and main
+               main(0, NULL);
+
+               return JNI_VERSION_1_2;
+       }
+
+       /*
+        * Implementations of NitActivity.java native methods
+        */
+
+       JNIEXPORT jint JNICALL Java_nit_app_NitActivity_nitRegisterActivity
+         (JNIEnv *env, jobject java_activity)
+       {
+               Activity nit_activity = App_register_activity(global_app, java_activity);
+               Activity_incr_ref(nit_activity);
+               return (jint)(void*)nit_activity;
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnCreate
+         (JNIEnv *env, jobject java_activity, jint nit_activity, jobject saved_state)
+       {
+               Activity_on_create((Activity)nit_activity, saved_state);
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnStart
+         (JNIEnv *env, jobject java_activity, jint nit_activity)
+       {
+               Activity_on_start((Activity)nit_activity);
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnRestart
+         (JNIEnv *env, jobject java_activity, jint nit_activity)
+       {
+               Activity_on_restart((Activity)nit_activity);
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnResume
+         (JNIEnv *env, jobject java_activity, jint nit_activity)
+       {
+               Activity_on_resume((Activity)nit_activity);
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnPause
+         (JNIEnv *env, jobject java_activity, jint nit_activity)
+       {
+               Activity_on_pause((Activity)nit_activity);
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnStop
+         (JNIEnv *env, jobject java_activity, jint nit_activity)
+       {
+               Activity_on_stop((Activity)nit_activity);
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnDestroy
+         (JNIEnv *env, jobject java_activity, jint nit_activity)
+       {
+               Activity_on_destroy((Activity)nit_activity);
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnSaveInstanceState
+         (JNIEnv *env, jobject java_activity, jint nit_activity, jobject saved_state)
+       {
+               Activity_on_save_instance_state((Activity)nit_activity, saved_state);
+       }
+
+       JNIEXPORT void JNICALL Java_nit_app_NitActivity_nitOnRestoreInstanceState
+         (JNIEnv *env, jobject java_activity, jint nit_activity, jobject saved_state)
+       {
+               Activity_on_restore_instance_state((Activity)nit_activity, saved_state);
+       }
+`}
+
+# Wrapper to our Java `NitActivity`
+extern class NativeNitActivity in "Java" `{ nit.app.NitActivity `}
+       super NativeActivity
+end
+
+redef class Sys
+       redef fun jvm `{ return global_jvm; `}
+end
+
+redef class App
+       # Known activities
+       var activities = new Array[Activity]
+
+       # The main Java Activity of this application
+       redef fun native_activity do return activities.first.native
+
+       redef fun setup do set_global_app
+
+       # Register app in C
+       private fun set_global_app import register_activity,
+       Activity.on_create, Activity.on_destroy,
+       Activity.on_start, Activity.on_restart, Activity.on_stop,
+       Activity.on_pause, Activity.on_resume,
+       Activity.on_save_instance_state, Activity.on_restore_instance_state `{
+               App_incr_ref(recv);
+               global_app = recv;
+       `}
+
+       # Create the Nit side to this new `native` Java activity, and return it to Java
+       private fun register_activity(native: NativeNitActivity): Activity
+       do
+               native = native.new_global_ref
+               var activity = new Activity(native)
+               activities.add activity
+               return activity
+       end
+end
+
+# An Android activity
+#
+# You must implement the callbacks (prefixed with `on_`) to follow the
+# standard Android life-cycle.
+class Activity
+       # Native Java activity
+       var native: NativeActivity
+
+       # Notification from Android, the activity is created
+       #
+       # Do your normal static set up here.
+       #
+       # If available, `save_state` contains the activity's previous state
+       # as registered by `on_save_instance_state`.
+       #
+       # Followed by `on_start`.
+       fun on_create(save_state: NativeBundle) do end
+
+       # Notification from Android, the activity has been restarted
+       #
+       # Followed by `on_start`.
+       fun on_restart do end
+
+       # Notification from Android, the activity has been started
+       #
+       # Followed by `on_resume` or `on_stop`.
+       fun on_start do end
+
+       # Notification from Android, the activity has been resumed
+       #
+       # Followed by `on_pause`
+       fun on_resume do end
+
+       # Notification from Android, the activity has been paused
+       #
+       # Followed by `on_resume` or `on_stop`.
+       fun on_pause do end
+
+       # Notification from Android, the activity has been stopped
+       #
+       # Followed by `on_restart` or `on_destroy`.
+       fun on_stop do end
+
+       # Notification from Android, the activity is being destroyed
+       #
+       # Clean up and exit.
+       fun on_destroy
+       do
+               native.delete_global_ref
+               app.activities.remove self
+       end
+
+       # Notification from Android, the activity is being re-initialized from a `save_state`
+       #
+       # Occurs after `on_start`.
+       fun on_restore_instance_state(save_state: NativeBundle) do end
+
+       # Notification from Android, the activity may be stopped, save state
+       #
+       # Occurs before `on_stop` and, without guarantee, before or after `on_pause`.
+       fun on_save_instance_state(save_state: NativeBundle) do end
+
+       # Notification from Android, the system is running low on memory
+       #
+       # Try to reduce your memory use.
+       fun on_low_memory do end
+
+       # Notification from Android, the current window of the activity has lost or gained focus
+       fun on_window_focus_changed(has_focus: Bool) do end
+
+       # Notification from Android, the current device configuration has changed
+       fun on_configuration_changed do end
+end
+
+# Set up global data in C and leave it to Android to callback Java, which we relay to Nit
+app.setup