Diligent Engine API Reference
JNIHelper.h
1 /*
2  * Copyright 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <jni.h>
20 #include <vector>
21 #include <string>
22 #include <functional>
23 #include <assert.h>
24 #include <mutex>
25 #include <pthread.h>
26 
27 #include <android/log.h>
28 #include <android_native_app_glue.h>
29 
30 #define LOGI(...) \
31  ((void)__android_log_print( \
32  ANDROID_LOG_INFO, ndk_helper::JNIHelper::GetInstance()->GetAppName(), \
33  __VA_ARGS__))
34 #define LOGW(...) \
35  ((void)__android_log_print( \
36  ANDROID_LOG_WARN, ndk_helper::JNIHelper::GetInstance()->GetAppName(), \
37  __VA_ARGS__))
38 #define LOGE(...) \
39  ((void)__android_log_print( \
40  ANDROID_LOG_ERROR, ndk_helper::JNIHelper::GetInstance()->GetAppName(), \
41  __VA_ARGS__))
42 
43 namespace ndk_helper {
44 
45 class JUIView;
46 
47 /******************************************************************
48  * Helper functions for JNI calls
49  * This class wraps JNI calls and provides handy interface calling commonly used
50  *features
51  * in Java SDK.
52  * Such as
53  * - loading graphics files (e.g. PNG, JPG)
54  * - character code conversion
55  * - retrieving system properties which only supported in Java SDK
56  *
57  * NOTE: To use this class, add NDKHelper.java as a corresponding helpers in
58  *Java code
59  */
60 class JNIHelper {
61  private:
62  std::string app_name_;
63 
64  ANativeActivity* activity_;
65  jobject jni_helper_java_ref_;
66  jclass jni_helper_java_class_;
67 
68  jstring GetExternalFilesDirJString(JNIEnv* env);
69  jclass RetrieveClass(JNIEnv* jni, const char* class_name);
70 
71  JNIHelper();
72  ~JNIHelper();
73  JNIHelper(const JNIHelper& rhs);
74  JNIHelper& operator=(const JNIHelper& rhs);
75 
76  std::string app_label_;
77 
78  // mutex for synchronization
79  // This class uses singleton pattern and can be invoked from multiple threads,
80  // each methods locks the mutex for a thread safety
81  mutable std::mutex mutex_;
82 
83  /*
84  * Call method in JNIHelper class
85  */
86  jobject CallObjectMethod(const char* strMethodName, const char* strSignature,
87  ...);
88  void CallVoidMethod(const char* strMethodName, const char* strSignature, ...);
89 
90  /*
91  * Unregister this thread from the VM
92  */
93  static void DetachCurrentThreadDtor(void* p) {
94  LOGI("detached current thread");
95  ANativeActivity* activity = (ANativeActivity*)p;
96  activity->vm->DetachCurrentThread();
97  }
98 
99  public:
100  /*
101  * To load your own Java classes, JNIHelper requires to be initialized with a
102  *ANativeActivity handle.
103  * This methods need to be called before any call to the helper class.
104  * Static member of the class
105  *
106  * arguments:
107  * in: activity, pointer to ANativeActivity. Used internally to set up JNI
108  *environment
109  * in: helper_class_name, pointer to Java side helper class name. (e.g.
110  *"com/sample/helper/NDKHelper" in samples )
111  */
112  static void Init(ANativeActivity* activity, const char* helper_class_name);
113 
114  /*
115  * Init() that accept so name.
116  * When using a JUI helper class, Java side requires SO name to initialize JNI
117  * calls to invoke native callbacks.
118  * Use this version when using JUI helper.
119  *
120  * arguments:
121  * in: activity, pointer to ANativeActivity. Used internally to set up JNI
122  * environment
123  * in: helper_class_name, pointer to Java side helper class name. (e.g.
124  * "com/sample/helper/NDKHelper" in samples )
125  * in: native_soname, pointer to soname of native library. (e.g.
126  * "NativeActivity" for "libNativeActivity.so" )
127  */
128  static void Init(ANativeActivity* activity, const char* helper_class_name,
129  const char* native_soname);
130 
131  /*
132  * Retrieve the singleton object of the helper.
133  * Static member of the class
134 
135  * Methods in the class are designed as thread safe.
136  */
137  static JNIHelper* GetInstance();
138 
139  /*
140  * Read a file from a strorage.
141  * First, the method tries to read the file from an external storage.
142  * If it fails to read, it falls back to use assset manager and try to read
143  * the file from APK asset.
144  *
145  * arguments:
146  * in: file_name, file name to read
147  * out: buffer_ref, pointer to a vector buffer to read a file.
148  * when the call succeeded, the buffer includes contents of specified
149  *file
150  * when the call failed, contents of the buffer remains same
151  * return:
152  * true when file read succeeded
153  * false when it failed to read the file
154  */
155  bool ReadFile(const char* file_name, std::vector<uint8_t>* buffer_ref);
156 
157  /*
158  * Load and create OpenGL texture from given file name.
159  * The method invokes BitmapFactory in Java so it can read jpeg/png formatted
160  * files
161  *
162  * The methods creates mip-map and set texture parameters like this,
163  * glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
164  * GL_LINEAR_MIPMAP_NEAREST );
165  * glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
166  * glGenerateMipmap( GL_TEXTURE_2D );
167  *
168  * arguments:
169  * in: file_name, file name to read, PNG&JPG is supported
170  * outWidth(Optional) pointer to retrieve original bitmap width
171  * outHeight(Optional) pointer to retrieve original bitmap height
172  * return:
173  * OpenGL texture name when the call succeeded
174  * When it failed to load the texture, it returns -1
175  */
176  uint32_t LoadTexture(const char* file_name, int32_t* outWidth = nullptr,
177  int32_t* outHeight = nullptr, bool* hasAlpha = nullptr);
178 
179  /*
180  * Load and create OpenGL cubemap texture from given file name
181  * into specified cubemap face & miplevel
182  * The method invokes BitmapFactory in Java so it can read jpeg/png formatted
183  * files
184  *
185  * arguments:
186  * in: file_name, file name to read, PNG&JPG is supported
187  * outWidth(Optional) pointer to retrieve original bitmap width
188  * outHeight(Optional) pointer to retrieve original bitmap height
189  * return:
190  * OpenGL texture name when the call succeeded
191  * When it failed to load the texture, it returns -1
192  */
193  uint32_t LoadCubemapTexture(const char* file_name, const int32_t face,
194  const int32_t miplevel, const bool sRGB,
195  int32_t* outWidth = nullptr,
196  int32_t* outHeight = nullptr,
197  bool* hasAlpha = nullptr);
198 
199  /*
200  * Load and create image and return it as a byte array.
201  * The method invokes BitmapFactory in Java so it can read jpeg/png formatted
202  * files
203  *
204  * arguments:
205  * in: file_name, file name to read, PNG&JPG is supported
206  * outWidth(Optional) pointer to retrieve original bitmap width
207  * outHeight(Optional) pointer to retrieve original bitmap height
208  * return:
209  * Java ByteBuffer object containing image data converted to RGBA values.
210  */
211  jobject LoadImage(const char* file_name, int32_t* outWidth = nullptr,
212  int32_t* outHeight = nullptr, bool* hasAlpha = nullptr);
213 
214  /*
215  * Convert string from character code other than UTF-8
216  *
217  * arguments:
218  * in: str, pointer to a string which is encoded other than UTF-8
219  * in: encoding, pointer to a character encoding string.
220  * The encoding string can be any valid java.nio.charset.Charset name
221  * e.g. "UTF-16", "Shift_JIS"
222  * return: converted input string as an UTF-8 std::string
223  */
224  std::string ConvertString(const char* str, const char* encode);
225  /*
226  * Retrieve external file directory through JNI call
227  *
228  * return: std::string containing external file diretory
229  */
230  std::string GetExternalFilesDir();
231 
232  /*
233  * Retrieve string resource with a given name
234  * arguments:
235  * in: resourceName, name of string resource to retrieve
236  * return: string resource value, returns "" when there is no string resource
237  * with given name
238  */
239  std::string GetStringResource(const std::string& resourceName);
240 
241  /*
242  * Audio helper
243  * Retrieves native audio buffer size which is required to achieve low latency
244  * audio
245  *
246  * return: Native audio buffer size which is a hint to achieve low latency
247  * audio
248  * If the API is not supported (API level < 17), it returns 0
249  */
250  int32_t GetNativeAudioBufferSize();
251 
252  /*
253  * Audio helper
254  * Retrieves native audio sample rate which is required to achieve low latency
255  * audio
256  *
257  * return: Native audio sample rate which is a hint to achieve low latency
258  * audio
259  */
260  int32_t GetNativeAudioSampleRate();
261 
262  /*
263  * Retrieves application bundle name
264  *
265  * return: pointer to an app name string
266  *
267  */
268  const char* GetAppName() const { return app_name_.c_str(); }
269 
270  /*
271  * Retrieves application label
272  *
273  * return: pointer to an app label string
274  *
275  */
276  const char* GetAppLabel() const { return app_label_.c_str(); }
277 
278  /*
279  * Execute given function in Java UIThread.
280  *
281  * arguments:
282  * in: pFunction, a pointer to a function to be executed in Java UI Thread.
283  * Note that the helper function returns immediately without synchronizing a
284  * function completion.
285  */
286  void RunOnUiThread(std::function<void()> callback);
287 
288  /*
289  * Attach current thread
290  * In Android, the thread doesn't have to be 'Detach' current thread
291  * as application process is only killed and VM does not shut down
292  */
293  JNIEnv* AttachCurrentThread() {
294  JNIEnv* env;
295  if (activity_->vm->GetEnv((void**)&env, JNI_VERSION_1_4) == JNI_OK)
296  return env;
297  activity_->vm->AttachCurrentThread(&env, NULL);
298  pthread_key_create((int32_t*)activity_, DetachCurrentThreadDtor);
299  return env;
300  }
301 
302  void DetachCurrentThread() {
303  activity_->vm->DetachCurrentThread();
304  return;
305  }
306 
307  /*
308  * Decrement a global reference to the object
309  * arguments:
310  * in: obj, obj to decrement a global reference
311  */
312  void DeleteObject(jobject obj);
313 
314  /*
315  * Helper methods to call a method in given object
316  */
317  jobject CreateObject(const char* class_name);
318  jobject CallObjectMethod(jobject object, const char* strMethodName,
319  const char* strSignature, ...);
320  void CallVoidMethod(jobject object, const char* strMethodName,
321  const char* strSignature, ...);
322  float CallFloatMethod(jobject object, const char* strMethodName,
323  const char* strSignature, ...);
324  int32_t CallIntMethod(jobject object, const char* strMethodName,
325  const char* strSignature, ...);
326  bool CallBooleanMethod(jobject object, const char* strMethodName,
327  const char* strSignature, ...);
328 };
329 
330 } // namespace ndkHelper
Definition: gestureDetector.h:32