3 #include <android/log.h>
4 #include "com_iotivity_jar_CALeInterface.h"
6 #define LOG_TAG "jni_BLE_Server"
7 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
8 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
10 static const char *OIC_GATT_SERVICE_UUID = "713d0000-503e-4c75-ba94-3148f18d941e";
11 static const char *OIC_GATT_CHARACTERISTIC_RESPONSE_UUID = "713d0002-503e-4c75-ba94-3148f18d941e";
12 static const char *OIC_GATT_CHARACTERISTIC_REQUEST_UUID = "713d0003-503e-4c75-ba94-3148f18d941e";
14 static jobject gContext;
15 static jobject gBluetoothGattServer;
16 static jobject gBluetoothGattServerCallback;
17 static jobject gAdvertiseCallback;
19 jobject getUuidFromString(JNIEnv *env, const char* uuid)
22 LOGI("[BLE Server] getUuidFromString");
24 jclass jni_cid_UUID = (*env)->FindClass(env, "java/util/UUID");
27 LOGI("[BLE Server] jni_cid_UUID is null");
31 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_UUID, "fromString",
32 "(Ljava/lang/String;)Ljava/util/UUID;");
33 if (!jni_mid_fromString)
35 LOGI("[BLE Server] jni_mid_fromString is null");
39 jstring str_serviceUUID = (*env)->NewStringUTF(env, uuid);
40 LOGI("[BLE Server] uuid: %s", uuid);
41 jobject jni_obj_serviceUUID = (*env)->CallStaticObjectMethod(env, jni_cid_UUID,
42 jni_mid_fromString, str_serviceUUID);
43 if (!jni_obj_serviceUUID)
45 LOGI("[BLE][Server] jni_obj_serviceUUID is null");
49 return jni_obj_serviceUUID;
52 jobject getParcelUuid(JNIEnv *env, jobject uuid)
55 jclass jni_cid_ParcelUuid = (*env)->FindClass(env, "android/os/ParcelUuid");
56 if (!jni_cid_ParcelUuid)
58 LOGI("[BLE Server] jni_cid_ParcelUuid is null");
62 jmethodID jni_mid_ParcelUuid = (*env)->GetMethodID(env, jni_cid_ParcelUuid, "<init>",
63 "(Ljava/util/UUID;)V");
64 if (!jni_mid_ParcelUuid)
66 LOGI("[BLE Server] jni_mid_ParcelUuid is null");
70 jobject jni_ParcelUuid = (*env)->NewObject(env, jni_cid_ParcelUuid, jni_mid_ParcelUuid, uuid);
73 LOGI("[BLE Server] jni_ParcelUuid is null");
77 return jni_ParcelUuid;
80 jobject setData(JNIEnv *env, char* responseData)
83 LOGI("[BLE Server] set response");
85 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
86 "android/bluetooth/BluetoothGattServer");
87 jclass jni_cid_bluetoothGattService = (*env)->FindClass(env,
88 "android/bluetooth/BluetoothGattService");
89 jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env,
90 "android/bluetooth/BluetoothGattCharacteristic");
91 LOGI("[BLE Server] get classes");
93 jmethodID jni_mid_getService = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
94 "getService", "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattService;");
95 LOGI("[BLE Server] get methodID");
97 jobject jni_obj_serviceUUID = getUuidFromString(env, OIC_GATT_SERVICE_UUID);
98 LOGI("[BLE Server] get serviceUUID");
100 if (!gBluetoothGattServer)
102 LOGI("[BLE Server] gBluetoothGattServer is null");
106 jobject jni_obj_bluetoothGattService = (*env)->CallObjectMethod(env, gBluetoothGattServer,
107 jni_mid_getService, jni_obj_serviceUUID);
108 LOGI("[BLE Server] jni_obj_bluetoothGattService");
110 jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
112 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattCharacteristic;");
114 jobject jni_obj_responseUUID = getUuidFromString(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
115 jobject jni_obj_bluetoothGattCharacteristic = (*env)->CallObjectMethod(env,
116 jni_obj_bluetoothGattService, jni_mid_getCharacteristic, jni_obj_responseUUID);
117 LOGI("[BLE Server] jni_obj_bluetoothGattCharacteristic");
119 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_bluetoothGattCharacteristic,
120 "setValue", "(Ljava/land/String;)Z");
121 jstring str_responseData = (*env)->NewStringUTF(env, responseData);
122 jboolean jni_boolean_setValue = (*env)->CallBooleanMethod(env,
123 jni_obj_bluetoothGattCharacteristic, jni_mid_setValue, str_responseData);
125 return jni_obj_bluetoothGattCharacteristic;
128 jboolean sendData(JNIEnv *env, jobject device, jobject responseData)
133 LOGI("[BLE Server] device is null");
139 LOGI("[BLE Server] responseData is null");
143 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
144 "android/bluetooth/BluetoothGattServer");
146 jmethodID jni_mid_notifyCharacteristicChanged =
147 (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, "notifyCharacteristicChanged",
148 "(Landroid/bluetooth/BluetoothDevice;Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z");
149 jboolean jni_boolean_notifyCharacteristicChanged = (*env)->CallBooleanMethod(env,
150 gBluetoothGattServer, jni_mid_notifyCharacteristicChanged, device, responseData,
153 if (!jni_boolean_notifyCharacteristicChanged)
159 jboolean sendResponse(JNIEnv *env, jobject device, jint requestId, jint status, jint offset)
162 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
163 "android/bluetooth/BluetoothGattServer");
164 jmethodID jni_mid_sendResponse = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
165 "sendResponse", "(Landroid/bluetooth/BluetoothDevice;III)Z");
166 (*env)->CallVoidMethod(env, gBluetoothGattServer, jni_mid_sendResponse, device, requestId,
168 LOGI("[BLE Server] sendResponse");
172 void startAdvertize(JNIEnv *env, jobject advertiseCallback)
175 jclass jni_cid_AdvertiseSettings = (*env)->FindClass(env,
176 "android/bluetooth/le/AdvertiseSettings$Builder");
178 jmethodID jni_mid_AdvertiseSettings = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
181 jobject jni_AdvertiseSettings = (*env)->NewObject(env, jni_cid_AdvertiseSettings,
182 jni_mid_AdvertiseSettings);
183 if (!jni_AdvertiseSettings)
185 LOGI("[BLE Server] jni_AdvertiseSettings is null");
189 jmethodID jni_mid_setConnectable = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
190 "setConnectable", "(Z)Landroid/bluetooth/le/AdvertiseSettings$Builder;");
192 jobject jni_obj_setConnectable = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
193 jni_mid_setConnectable, JNI_TRUE);
194 if (!jni_obj_setConnectable)
196 LOGI("[BLE][Server] jni_obj_setConnectable is null");
200 jmethodID jni_mid_setTimeout = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings, "setTimeout",
201 "(I)Landroid/bluetooth/le/AdvertiseSettings$Builder;");
203 jobject jni_obj_setTimeout = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
204 jni_mid_setTimeout, 10000);
205 if (!jni_obj_setTimeout)
207 LOGI("[BLE][Server] jni_obj_setTimeout is null");
211 jclass jni_cid_AdvertiseDataBuilder = (*env)->FindClass(env,
212 "android/bluetooth/le/AdvertiseData$Builder");
214 jmethodID jni_mid_AdvertiseDataBuilder = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
217 jobject jni_AdvertiseDataBuilder = (*env)->NewObject(env, jni_cid_AdvertiseDataBuilder,
218 jni_mid_AdvertiseDataBuilder);
219 if (!jni_AdvertiseDataBuilder)
221 LOGI("[BLE Server] jni_AdvertiseDataBuilder is null");
225 jobject jni_obj_serviceUUID = getUuidFromString(env, OIC_GATT_SERVICE_UUID);
226 jobject jni_ParcelUuid = getParcelUuid(env, jni_obj_serviceUUID);
227 jmethodID jni_mid_addServiceUuid = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
229 "(Landroid/os/ParcelUuid;)Landroid/bluetooth/le/AdvertiseData$Builder;");
231 jobject jni_obj_addServiceUuid = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
232 jni_mid_addServiceUuid, jni_ParcelUuid);
233 if (!jni_obj_addServiceUuid)
235 LOGI("[BLE Server] jni_obj_addServiceUuid is null");
239 jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter");
240 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
241 "getDefaultAdapter", "()Landroid/bluetooth/BluetoothAdapter;");
243 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
244 jni_mid_getDefaultAdapter);
245 if (!jni_obj_BTAdapter)
247 LOGI("[BLE Server] jni_obj_BTAdapter is null");
251 jmethodID jni_mid_getBluetoothLeAdvertiser = (*env)->GetMethodID(env, jni_cid_BTAdapter,
252 "getBluetoothLeAdvertiser", "()Landroid/bluetooth/le/BluetoothLeAdvertiser;");
254 jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
255 jni_mid_getBluetoothLeAdvertiser);
256 if (!jni_obj_getBluetoothLeAdvertiser)
258 LOGI("[BLE Server] jni_obj_getBluetoothLeAdvertiser is null");
262 jmethodID jni_mid_build_LeAdvertiseSettings = (*env)->GetMethodID(env,
263 jni_cid_AdvertiseSettings, "build", "()Landroid/bluetooth/le/AdvertiseSettings;");
265 jobject jni_obj_build_LeAdvertiseSettings = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
266 jni_mid_build_LeAdvertiseSettings);
267 if (!jni_obj_build_LeAdvertiseSettings)
269 LOGI("[BLE Server] jni_obj_build_LeAdvertiseSettings is null");
273 jmethodID jni_mid_build_LeAdvertiseData = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
274 "build", "()Landroid/bluetooth/le/AdvertiseData;");
276 jobject jni_obj_build_LeAdvertiseData = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
277 jni_mid_build_LeAdvertiseData);
278 if (!jni_obj_build_LeAdvertiseData)
280 LOGI("[BLE Server] jni_obj_build_LeAdvertiseData is null");
284 jclass jni_cid_leAdvertiser = (*env)->FindClass(env,
285 "android/bluetooth/le/BluetoothLeAdvertiser");
287 jmethodID jni_mid_startAdvertising =
288 (*env)->GetMethodID(env, jni_cid_leAdvertiser, "startAdvertising",
289 "(Landroid/bluetooth/le/AdvertiseSettings;Landroid/bluetooth/le/AdvertiseData;Landroid/bluetooth/le/AdvertiseCallback;)V");
291 (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_startAdvertising,
292 jni_obj_build_LeAdvertiseSettings, jni_obj_build_LeAdvertiseData, advertiseCallback);
294 LOGI("[BLE Server] jni start Advertising");
297 jobject openGattServer(JNIEnv *env)
300 jclass jni_cid_context = (*env)->FindClass(env, "android/content/Context");
301 jfieldID jni_fid_bluetoothService = (*env)->GetStaticFieldID(env, jni_cid_context,
302 "BLUETOOTH_SERVICE", "Ljava/lang/String;");
303 jobject jni_obj_bluetoothService = (*env)->GetStaticObjectField(env, jni_cid_context,
304 jni_fid_bluetoothService);
306 jmethodID jni_mid_getSystemService = (*env)->GetMethodID(env, jni_cid_context,
307 "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
308 jobject jni_obj_bluetoothManager = (*env)->CallObjectMethod(env, gContext,
309 jni_mid_getSystemService, jni_obj_bluetoothService);
311 jclass jni_cid_bluetoothManager = (*env)->FindClass(env, "android/bluetooth/BluetoothManager");
312 jmethodID jni_mid_openGattServer =
313 (*env)->GetMethodID(env, jni_cid_bluetoothManager, "openGattServer",
314 "(Landroid/content/Context;Landroid/bluetooth/BluetoothGattServerCallback;)Landroid/bluetooth/BluetoothGattServer;");
315 jobject jni_obj_bluetoothGattServer = (*env)->CallObjectMethod(env, jni_obj_bluetoothManager,
316 jni_mid_openGattServer, gContext, gBluetoothGattServerCallback);
318 return jni_obj_bluetoothGattServer;
321 jobject createGattService(JNIEnv *env)
324 jclass jni_cid_bluetoothGattService = (*env)->FindClass(env,
325 "android/bluetooth/BluetoothGattService");
326 jmethodID jni_mid_bluetoothGattService = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
327 "<init>", "(Ljava/util/UUID;I)V");
329 // service uuid object
330 jobject jni_obj_serviceUUID = getUuidFromString(env, OIC_GATT_SERVICE_UUID);
332 // service type object
333 jfieldID jni_fid_serviceType = (*env)->GetStaticFieldID(env, jni_cid_bluetoothGattService,
334 "SERVICE_TYPE_PRIMARY", "I");
335 jobject jni_obj_serviceType = (*env)->GetStaticObjectField(env, jni_cid_bluetoothGattService,
336 jni_fid_serviceType);
338 jobject jni_bluetoothGattService = (*env)->NewObject(env, jni_cid_bluetoothGattService,
339 jni_mid_bluetoothGattService, jni_obj_serviceUUID, jni_obj_serviceType);
340 if (!jni_bluetoothGattService)
342 LOGI("[BLE Server] fail to create gatt service instance!");
346 jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env,
347 "android/bluetooth/BluetoothGattCharacteristic");
348 jmethodID jni_mid_bluetoothGattCharacteristic = (*env)->GetMethodID(env,
349 jni_cid_bluetoothGattCharacteristic, "<init>", "(Ljava/util/UUID;II)V");
351 // characteristic uuid for response
352 jobject jni_obj_readUuid = getUuidFromString(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
354 // characteristic properties
355 jfieldID jni_fid_readProperties = (*env)->GetStaticFieldID(env,
356 jni_cid_bluetoothGattCharacteristic, "PROPERTY_READ", "I");
357 jobject jni_obj_readProperties = (*env)->GetStaticObjectField(env,
358 jni_cid_bluetoothGattCharacteristic, jni_fid_readProperties);
360 // characteristic permissions
361 jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env,
362 jni_cid_bluetoothGattCharacteristic, "PERMISSION_READ", "I");
363 jobject jni_obj_readPermissions = (*env)->GetStaticObjectField(env,
364 jni_cid_bluetoothGattCharacteristic, jni_fid_readPermissions);
366 jobject jni_readCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
367 jni_mid_bluetoothGattCharacteristic, jni_obj_readUuid, jni_obj_readProperties,
368 jni_obj_readPermissions);
369 if (!jni_readCharacteristic)
371 LOGI("[BLE Server] fail to create Response Characteristic");
375 jobject jni_obj_writeUuid = getUuidFromString(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
377 // characteristic properties
378 jfieldID jni_fid_writeProperties = (*env)->GetStaticFieldID(env,
379 jni_cid_bluetoothGattCharacteristic, "PROPERTY_WRITE", "I");
380 jobject jni_obj_writeProperties = (*env)->GetStaticObjectField(env,
381 jni_cid_bluetoothGattCharacteristic, jni_fid_writeProperties);
383 // characteristic permissions
384 jfieldID jni_fid_writePermissions = (*env)->GetStaticFieldID(env,
385 jni_cid_bluetoothGattCharacteristic, "PERMISSION_WRITE", "I");
386 jobject jni_obj_writePermissions = (*env)->GetStaticObjectField(env,
387 jni_cid_bluetoothGattCharacteristic, jni_fid_writePermissions);
389 jobject jni_writeCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
390 jni_mid_bluetoothGattCharacteristic, jni_obj_writeUuid, jni_obj_writeProperties,
391 jni_obj_writePermissions);
392 if (!jni_writeCharacteristic)
394 LOGI("[BLE Server] fail to create Request Characteristic");
398 jmethodID jni_mid_addCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
399 "addCharacteristic", "(Landroid/bluetooth/BluetoothGattCharacteristic;)Z");
400 jboolean jni_boolean_addReadCharacteristic = (*env)->CallBooleanMethod(env,
401 jni_bluetoothGattService, jni_mid_addCharacteristic, jni_readCharacteristic);
402 if (jni_boolean_addReadCharacteristic == JNI_FALSE)
404 LOGI("[BLE Server] fail to add jni_boolean_addReadCharacteristic!!");
408 jboolean jni_boolean_addWriteCharacteristic = (*env)->CallBooleanMethod(env,
409 jni_bluetoothGattService, jni_mid_addCharacteristic, jni_writeCharacteristic);
410 if (jni_boolean_addWriteCharacteristic == JNI_FALSE)
412 LOGI("[BLE Server] fail to add jni_boolean_addReadCharacteristic!!");
416 LOGI("[BLE Server] jni gatt characteristic added!!");
417 return jni_bluetoothGattService;
420 void startGattServer(JNIEnv *env, jobject gattServerCallback)
423 gBluetoothGattServerCallback = (*env)->NewGlobalRef(env, gattServerCallback);
426 jobject bluetoothGattServer = openGattServer(env);
428 gBluetoothGattServer = (*env)->NewGlobalRef(env, bluetoothGattServer);
429 LOGI("[BLE Server] Bluetooth Gatt Server started!!");
431 // get bluetooth gatt service
432 jobject bluetoothGattService = createGattService(env);
434 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
435 "android/bluetooth/BluetoothGattServer");
436 jmethodID jni_mid_addService = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
437 "addService", "(Landroid/bluetooth/BluetoothGattService;)Z");
438 jboolean jni_boolean_addService = (*env)->CallBooleanMethod(env, bluetoothGattServer,
439 jni_mid_addService, bluetoothGattService);
441 LOGI("[BLE Server] jni gatt service added!!");
444 void connect(JNIEnv *env, jobject bluetoothDevice)
447 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
448 "android/bluetooth/BluetoothGattServer");
449 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, "connect",
450 "(Landroid/bluetooth/BluetoothDevice;Z)Z");
451 jboolean jni_boolean_connect = (*env)->CallBooleanMethod(env, gBluetoothGattServer,
452 jni_mid_connect, bluetoothDevice, JNI_FALSE);
453 LOGI("[BLE Server] connection requested!!");
456 void disconnect(JNIEnv *env, jobject bluetoothDevice)
459 jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
460 "android/bluetooth/BluetoothGattServer");
461 jmethodID jni_mid_cancelConnection = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
462 "cancelConnection", "(Landroid/bluetooth/BluetoothDevice;)V");
463 (*env)->CallVoidMethod(env, gBluetoothGattServer, jni_mid_cancelConnection, bluetoothDevice);
464 LOGI("[BLE Server] disconnection requested!!");