1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2012-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 # Java related services specific to Android and its Dalvik VM
23 # Main Java Activity of this application
25 # Require: A Nit activity is currently running.
26 fun native_activity
: NativeActivity is abstract
28 # Current reference context, either an activity or a service
29 fun native_context
: NativeContext do return native_activity
32 extern class JavaClassLoader in "Java" `{java.lang.ClassLoader`}
37 # We cannot create a JVM on Android
39 # This method is not reachable on this platform anyway.
40 # `Sys::jvm
` is implemented by the main activity modules.
41 redef fun create_default_jvm do abort
43 redef fun jni_env do return jvm.attach_current_thread
45 private var class_loader: nullable JavaObject = null
46 private var class_loader_method: nullable JMethodID = null
47 redef fun load_jclass(name)
49 var class_loader = self.class_loader
50 if class_loader == null then
51 find_class_loader app.native_context
52 class_loader = self.class_loader
53 assert class_loader != null
56 var class_loader_method = self.class_loader_method
57 assert class_loader_method != null
59 return load_jclass_intern(class_loader, class_loader_method, name)
62 private fun find_class_loader(native_context: NativeContext) import jni_env, class_loader=, JavaObject.as nullable, class_loader_method=, JMethodID.as nullable `{
63 JNIEnv *env
= Sys_jni_env(self);
65 // Retrieve main activity
66 jclass class_context
= (*env
)->GetObjectClass(env
, native_context
);
67 if (class_context
== NULL) {
68 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed to retrieve activity class");
69 (*env
)->ExceptionDescribe(env
);
73 jmethodID class_activity_getClassLoader
= (*env
)->GetMethodID(env
, class_context
, "getClassLoader", "()Ljava/lang/ClassLoader;");
74 if (class_activity_getClassLoader
== NULL) {
75 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed to retrieve 'getClassLoader' method");
76 (*env
)->ExceptionDescribe(env
);
80 // Call activity
.getClassLoader
81 jobject instance_class_loader
= (*env
)->CallObjectMethod(env
, native_context
, class_activity_getClassLoader
);
82 if (instance_class_loader
== NULL) {
83 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed to retrieve class loader instance");
84 (*env
)->ExceptionDescribe(env
);
88 jclass class_class_loader
= (*env
)->GetObjectClass(env
, instance_class_loader
);
89 if (class_class_loader
== NULL) {
90 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed to retrieve class of class loader");
91 (*env
)->ExceptionDescribe(env
);
95 // Get the method
ClassLoader.findClass
96 jmethodID class_class_loader_findClass
= (*env
)->GetMethodID(env
, class_class_loader
, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
97 if (class_class_loader_findClass
== NULL) {
98 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed to retrieve 'findClass' method");
99 (*env
)->ExceptionDescribe(env
);
103 // Return the values to
Nit
104 Sys_class_loader__assign(self, JavaObject_as_nullable((*env
)->NewGlobalRef(env
, instance_class_loader
)));
105 Sys_class_loader_method__assign(self, JMethodID_as_nullable(class_class_loader_findClass
));
108 (*env
)->DeleteLocalRef(env
, class_context
);
109 (*env
)->DeleteLocalRef(env
, instance_class_loader
);
110 (*env
)->DeleteLocalRef(env
, class_class_loader
);
113 private fun load_jclass_intern(instance_class_loader: JavaObject, class_loader_findClass: JMethodID, name: NativeString): JClass import jni_env `{
114 JNIEnv *env
= Sys_jni_env(self);
115 jobject class_name
= (*env
)->NewStringUTF(env
, name
);
117 jclass java_class
= (*env
)->CallObjectMethod(env
, instance_class_loader
, class_loader_findClass
, class_name
);
118 if (java_class
== NULL) {
119 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed loading targeted class");
120 (*env
)->ExceptionDescribe(env
);
124 (*env
)->DeleteLocalRef(env
, class_name
);