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 # The main Java Activity of this application
24 fun native_activity
: NativeActivity is abstract
27 extern class JavaClassLoader in "Java" `{java.lang.ClassLoader`}
32 # We cannot create a JVM on Android
34 # This method is not reachable on this platform anyway.
35 # `Sys::jvm
` is implemented by the main activity modules.
36 redef fun create_default_jvm do abort
38 redef fun jni_env do return jvm.attach_current_thread
40 private var class_loader: nullable JavaObject = null
41 private var class_loader_method: nullable JMethodID = null
42 redef fun load_jclass(name)
44 var class_loader = self.class_loader
45 if class_loader == null then
46 find_class_loader app.native_activity
47 class_loader = self.class_loader
48 assert class_loader != null
51 var class_loader_method = self.class_loader_method
52 assert class_loader_method != null
54 return load_jclass_intern(class_loader, class_loader_method, name)
57 private fun find_class_loader(native_activity: NativeActivity) import jni_env, class_loader=, JavaObject.as nullable, class_loader_method=, JMethodID.as nullable `{
58 JNIEnv *env
= Sys_jni_env(recv
);
60 // Retrieve main activity
61 jclass class_activity
= (*env
)->GetObjectClass(env
, native_activity
);
62 if (class_activity
== NULL) {
63 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retrieving activity class");
64 (*env
)->ExceptionDescribe(env
);
68 jmethodID class_activity_getClassLoader
= (*env
)->GetMethodID(env
, class_activity
, "getClassLoader", "()Ljava/lang/ClassLoader;");
69 if (class_activity_getClassLoader
== NULL) {
70 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retrieving 'getClassLoader' method");
71 (*env
)->ExceptionDescribe(env
);
75 // Call activity
.getClassLoader
76 jobject instance_class_loader
= (*env
)->CallObjectMethod(env
, native_activity
, class_activity_getClassLoader
);
77 if (instance_class_loader
== NULL) {
78 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retrieving class loader instance");
79 (*env
)->ExceptionDescribe(env
);
83 jclass class_class_loader
= (*env
)->GetObjectClass(env
, instance_class_loader
);
84 if (class_class_loader
== NULL) {
85 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retrieving class of class loader");
86 (*env
)->ExceptionDescribe(env
);
90 // Get the method
ClassLoader.findClass
91 jmethodID class_class_loader_findClass
= (*env
)->GetMethodID(env
, class_class_loader
, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
92 if (class_class_loader_findClass
== NULL) {
93 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retrieving 'findClass' method");
94 (*env
)->ExceptionDescribe(env
);
98 // Return the values to
Nit
99 Sys_class_loader__assign(recv
, JavaObject_as_nullable((*env
)->NewGlobalRef(env
, instance_class_loader
)));
100 Sys_class_loader_method__assign(recv
, JMethodID_as_nullable(class_class_loader_findClass
));
103 (*env
)->DeleteLocalRef(env
, class_activity
);
104 (*env
)->DeleteLocalRef(env
, instance_class_loader
);
105 (*env
)->DeleteLocalRef(env
, class_class_loader
);
108 private fun load_jclass_intern(instance_class_loader: JavaObject, class_loader_findClass: JMethodID, name: NativeString): JClass import jni_env `{
109 JNIEnv *env
= Sys_jni_env(recv
);
110 jobject class_name
= (*env
)->NewStringUTF(env
, name
);
112 jclass java_class
= (*env
)->CallObjectMethod(env
, instance_class_loader
, class_loader_findClass
, class_name
);
113 if (java_class
== NULL) {
114 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed loading targeted class");
115 (*env
)->ExceptionDescribe(env
);
119 (*env
)->DeleteLocalRef(env
, class_name
);