add new BLE scan through android public API (upper than API level 21)
authorjihwanseo <jihwan.seo@samsung.com>
Mon, 12 Dec 2016 11:25:38 +0000 (20:25 +0900)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Wed, 15 Feb 2017 00:13:02 +0000 (00:13 +0000)
since previous scan api - startLeScan() was deprecated in API level 21.
we should use startScan(List, ScanSettings, ScanCallback).
https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html

Change-Id: Ife58de26f1b132c260b94a6d0ba5c6aa17d1e7f3
Signed-off-by: jihwan.seo <jihwan.seo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/17005
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
java/iotivity-android/src/main/java/org/iotivity/ca/CaLeClientInterface.java
resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c
resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.h
resource/csdk/connectivity/src/bt_le_adapter/android/caleutils.c
resource/csdk/connectivity/src/bt_le_adapter/android/caleutils.h
resource/csdk/connectivity/src/bt_le_adapter/android/org_iotivity_ca_CaLeClientInterface.h

index c3f5262..2b44f99 100644 (file)
@@ -38,6 +38,16 @@ import android.content.Intent;
 import android.content.IntentFilter;
 import android.util.Log;
 
+// For using bluetooth.le APIs
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
+import android.os.ParcelUuid;
+import java.util.Iterator;
+import android.os.Build;
+
 public class CaLeClientInterface {
 
     private static String SERVICE_UUID = "ADE3D529-C784-4F63-A987-EB69F70EE816";
@@ -46,7 +56,7 @@ public class CaLeClientInterface {
     private static volatile boolean isLeClientInitialized = false;
 
     private CaLeClientInterface(Context context) {
-        caLeRegisterLeScanCallback(mLeScanCallback);
+        getLeScanCallback();
         caLeRegisterGattCallback(mGattCallback);
         synchronized(CaLeClientInterface.class) {
             mContext = context;
@@ -57,10 +67,12 @@ public class CaLeClientInterface {
         }
     }
 
-
-
     public static void getLeScanCallback() {
-        caLeRegisterLeScanCallback(mLeScanCallback);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            caLeRegisterLeScanCallbackForV21(mLeScanCallbackForV21);
+        } else {
+            caLeRegisterLeScanCallback(mLeScanCallback);
+        }
     }
 
     public static void getLeGattCallback() {
@@ -82,13 +94,20 @@ public class CaLeClientInterface {
         }
     }
 
+    // register scan callback instance into le adapter.
     private native static void caLeRegisterLeScanCallback(BluetoothAdapter.LeScanCallback callback);
 
+    // register scan callback instance for level 21 into le adapter.
+    private native static void caLeRegisterLeScanCallbackForV21(ScanCallback callback);
+
     private native static void caLeRegisterGattCallback(BluetoothGattCallback callback);
 
     // BluetoothAdapter.LeScanCallback
     private native static void caLeScanCallback(BluetoothDevice device);
 
+    // scan failed callback for ca layer
+    private native static void caLeScanFailedCallback(int errorCode);
+
     // BluetoothGattCallback
     private native static void caLeGattConnectionStateChangeCallback(
             BluetoothGatt gatt, int status, int newState);
@@ -142,29 +161,58 @@ public class CaLeClientInterface {
     private native static void caLeGattMtuChangedCallback(BluetoothGatt gatt, int mtu,
                                                           int status);
 
-    // Callback
+    // Le Scan Callback which lower than API 21
     private static BluetoothAdapter.LeScanCallback mLeScanCallback =
                    new BluetoothAdapter.LeScanCallback() {
 
         @Override
         public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
+            filteringScanResult(device, scanRecord);
+        }
+    };
 
-            try {
-                List<UUID> uuids = getUuids(scanRecord);
-                for (UUID uuid : uuids) {
-                    Log.d(TAG, "UUID : " + uuid.toString());
-                    if(uuid.toString().contains(SERVICE_UUID.toLowerCase())) {
-                        Log.d(TAG, "we found that has the Device");
-                        Log.d(TAG, "scanned device address : " + device.getAddress());
-                        caLeScanCallback(device);
-                    }
-                }
-            } catch(UnsatisfiedLinkError e) {
+    // Le Scan Callback which upper than API 21
+    private static ScanCallback mLeScanCallbackForV21 = new ScanCallback() {
+        @Override
+        public void onScanResult(int callbackType, ScanResult result) {
+            super.onScanResult(callbackType, result);
+            Log.d(TAG, "onScanResult from ScanCallback");
+            filteringScanResult(result.getDevice(), result.getScanRecord().getBytes());
+        }
 
+        @Override
+        public void onBatchScanResults(List<ScanResult> results) {
+            super.onBatchScanResults(results);
+            Iterator<ScanResult> itr = results.iterator();
+            while (itr.hasNext()) {
+                filteringScanResult(itr.next().getDevice(),
+                        itr.next().getScanRecord().getBytes());
             }
         }
+
+        @Override
+        public void onScanFailed(int errorCode) {
+            super.onScanFailed(errorCode);
+            caLeScanFailedCallback(errorCode);
+        }
     };
 
+    private static void filteringScanResult(BluetoothDevice device, byte[] scanRecord) {
+        try {
+            List<UUID> uuids = getUuids(scanRecord);
+            for (UUID uuid : uuids) {
+                Log.d(TAG, "UUID : " + uuid.toString());
+                if(uuid.toString().contains(SERVICE_UUID.toLowerCase())) {
+                    Log.d(TAG, "we found that has the Device");
+                    Log.d(TAG, "scanned device address : " + device.getAddress());
+                    caLeScanCallback(device);
+                }
+            }
+        } catch(UnsatisfiedLinkError e) {
+            e.printStackTrace();
+        }
+    }
+
     private static List<UUID> getUuids(final byte[] scanRecord) {
         List<UUID> uuids = new ArrayList<UUID>();
 
index 56cc314..95860df 100644 (file)
@@ -55,6 +55,9 @@
 #define GATT_REQUEST_NOT_SUPPORTED          6
 #define GATT_WRITE_NOT_PERMITTED            3
 
+#define BLE_SCAN_API_LEVEL (21)
+#define BLE_MIN_API_LEVEL  (18)
+
 static ca_thread_pool_t g_threadPoolHandle = NULL;
 
 JavaVM *g_jvm;
@@ -109,8 +112,10 @@ static CALEScanState_t g_curScanningStep = BLE_SCAN_NONE;
 static CALEScanState_t g_nextScanningStep = BLE_SCAN_ENABLE;
 
 static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
+static int32_t g_jniIntSdk = -1;
 
 static bool g_setHighQoS = true;
+static bool g_setFullScanFlag = true;
 
 /**
  * check if retry logic for connection routine has to be stopped or not.
@@ -420,8 +425,8 @@ CAResult_t CALEClientInitialize()
         isAttached = true;
     }
 
-    CAResult_t ret = CALECheckPlatformVersion(env, 18);
-    if (CA_STATUS_OK != ret)
+    g_jniIntSdk = CALEGetBuildVersion(env);
+    if (g_jniIntSdk < BLE_MIN_API_LEVEL)
     {
         OIC_LOG(ERROR, TAG, "it is not supported");
 
@@ -429,11 +434,10 @@ CAResult_t CALEClientInitialize()
         {
             (*g_jvm)->DetachCurrentThread(g_jvm);
         }
-
-        return ret;
+        return CA_STATUS_FAILED;
     }
 
-    ret = CALEClientInitGattMutexVaraibles();
+    CAResult_t ret = CALEClientInitGattMutexVaraibles();
     if (CA_STATUS_OK != ret)
     {
         OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!");
@@ -1362,11 +1366,31 @@ CAResult_t CALEClientStartScan()
     // scan gatt server with UUID
     if (g_leScanCallback && g_uuidList)
     {
-#ifdef UUID_SCAN
-        ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
-#else
-        ret = CALEClientStartScanImpl(env, g_leScanCallback);
-#endif
+        if (g_jniIntSdk >= BLE_SCAN_API_LEVEL)
+        {
+            if (!g_setFullScanFlag)
+            {
+                //new uuid scan with callback
+                ret = CALEClientStartScanWithUUIDImplForV21(env, g_uuidList, g_leScanCallback);
+            }
+            else
+            {
+                //new full scan with callback
+                ret = CALEClientStartScanImplForV21(env, g_leScanCallback);
+            }
+        }
+        else
+        {
+            if (!g_setFullScanFlag)
+            {
+                ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
+            }
+            else
+            {
+                ret = CALEClientStartScanImpl(env, g_leScanCallback);
+            }
+        }
+
         if (CA_STATUS_OK != ret)
         {
             if (CA_ADAPTER_NOT_ENABLED == ret)
@@ -1390,6 +1414,7 @@ CAResult_t CALEClientStartScan()
 
 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
 {
+    OIC_LOG(DEBUG, TAG, "CALEClientStartScanImpl IN");
     VERIFY_NON_NULL(callback, TAG, "callback is null");
     VERIFY_NON_NULL(env, TAG, "env is null");
 
@@ -1462,8 +1487,113 @@ CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
     return CA_STATUS_OK;
 }
 
+CAResult_t CALEClientStartScanImplForV21(JNIEnv *env, jobject callback)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientStartScanImplForV21 IN");
+    VERIFY_NON_NULL(callback, TAG, "callback is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    if (!CALEIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
+    }
+
+    CAResult_t res = CA_STATUS_FAILED;
+    // get default bt adapter class
+    jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
+    if (!jni_cid_BTAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
+        CACheckJNIException(env);
+        return CA_STATUS_FAILED;
+    }
+
+    jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
+                                                                    "getDefaultAdapter",
+                                                                    "()Landroid/bluetooth/"
+                                                                    "BluetoothAdapter;");
+    if (!jni_mid_getDefaultAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        return CA_STATUS_FAILED;
+    }
+
+    jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
+                                                               jni_mid_getDefaultAdapter);
+    if (!jni_obj_BTAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        return CA_STATUS_FAILED;
+    }
+
+    // get bluetoothLeScanner class
+    jclass jni_cid_leScanner = (*env)->FindClass(env, CLASSPATH_LE_SCANNER);
+    if (!jni_cid_leScanner)
+    {
+        OIC_LOG(ERROR, TAG, "getState From leScanner: jni_cid_leScanner is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        return CA_STATUS_FAILED;
+    }
+
+    // get remote bt adapter method
+    jmethodID jni_mid_getBluetoothLeScanner = (*env)->GetMethodID(env, jni_cid_BTAdapter,
+                                                                  "getBluetoothLeScanner",
+                                                                  "()Landroid/bluetooth/"
+                                                                  "le/BluetoothLeScanner;");
+    if (!jni_mid_getBluetoothLeScanner)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeScanner is null");
+        CACheckJNIException(env);
+        goto error_exit;
+    }
+
+    // get startScan(ScanCallback callback) method
+    jmethodID jni_mid_startScan = (*env)->GetMethodID(env, jni_cid_leScanner, "startScan",
+                                                      "(Landroid/bluetooth/le/ScanCallback;)V");
+    if (!jni_mid_startScan)
+    {
+        OIC_LOG(ERROR, TAG, "startScan: jni_mid_startScan is null");
+        CACheckJNIException(env);
+        goto error_exit;
+    }
+
+    // gat le scanner object
+    jobject jni_obj_leScanner = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
+                                                         jni_mid_getBluetoothLeScanner);
+    if (!jni_obj_leScanner)
+    {
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_leScanner is null");
+        CACheckJNIException(env);
+        goto error_exit;
+    }
+
+    // call startScan method
+    OIC_LOG(INFO, TAG, "CALL API - startScan(for level21)");
+    (*env)->CallVoidMethod(env, jni_obj_leScanner, jni_mid_startScan, callback);
+    if (CACheckJNIException(env))
+    {
+        OIC_LOG(INFO, TAG, "startScan has failed");
+        (*env)->DeleteLocalRef(env, jni_obj_leScanner);
+        goto error_exit;
+    }
+    res = CA_STATUS_OK;
+    (*env)->DeleteLocalRef(env, jni_obj_leScanner);
+
+error_exit:
+    (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+    (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+    (*env)->DeleteLocalRef(env, jni_cid_leScanner);
+    return res;
+}
+
 CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
 {
+    OIC_LOG(DEBUG, TAG, "CALEClientStartScanWithUUIDImpl IN");
     VERIFY_NON_NULL(callback, TAG, "callback is null");
     VERIFY_NON_NULL(uuids, TAG, "uuids is null");
     VERIFY_NON_NULL(env, TAG, "env is null");
@@ -1536,6 +1666,379 @@ CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobj
     return CA_STATUS_OK;
 }
 
+CAResult_t CALEClientStartScanWithUUIDImplForV21(JNIEnv *env, jobjectArray uuids, jobject callback)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientStartScanWithUUIDImplForV21 IN");
+    VERIFY_NON_NULL(callback, TAG, "callback is null");
+    VERIFY_NON_NULL(uuids, TAG, "uuids is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    if (!CALEIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
+    }
+
+    // get bluetoothLeScanner class
+    jclass jni_cid_leScanner = (*env)->FindClass(env, CLASSPATH_LE_SCANNER);
+    if (!jni_cid_leScanner)
+    {
+        OIC_LOG(ERROR, TAG, "getState From leScanner: jni_cid_leScanner is null");
+        CACheckJNIException(env);
+        return CA_STATUS_FAILED;
+    }
+
+    // get startScan(with UUID) method
+    jmethodID jni_mid_startScan = (*env)->GetMethodID(env, jni_cid_leScanner,
+                                                      "startScan",
+                                                      "(Ljava/util/List;"
+                                                      "Landroid/bluetooth/le/ScanSettings;"
+                                                      "Landroid/bluetooth/le/ScanCallback;"
+                                                      ")V");
+    if (!jni_mid_startScan)
+    {
+        OIC_LOG(ERROR, TAG, "startScan: jni_mid_startScan is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_leScanner);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_cid_leScanner);
+
+    // get scanfilter.Builder class id
+    jclass jni_cid_scanfilterBuilder = (*env)->FindClass(env,
+                                                         "android/bluetooth/le/"
+                                                         "ScanFilter$Builder");
+    if (!jni_cid_scanfilterBuilder)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_cid_scanfilterBuilder is null");
+        CACheckJNIException(env);
+        return CA_STATUS_FAILED;
+    }
+
+    // get scanfilter.Builder(ctor) method id
+    jmethodID jni_mid_scanfilterBuilderCtor = (*env)->GetMethodID(env, jni_cid_scanfilterBuilder,
+                                                                  "<init>", "()V");
+    if (!jni_mid_scanfilterBuilderCtor)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_cid_scanfilterBuilderCtor is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    // call scanfilter.Builder()
+    jobject jni_obj_scanfilterBuilder = (*env)->NewObject(env, jni_cid_scanfilterBuilder,
+                                                          jni_mid_scanfilterBuilderCtor);
+    if (!jni_obj_scanfilterBuilder)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_scanfilterBuilder is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    // get scanfilter.Builder.setServiceUuid method id
+    jmethodID jni_mid_setServiceUuid = (*env)->GetMethodID(env, jni_cid_scanfilterBuilder,
+                                                           "setServiceUuid",
+                                                           "(Landroid/os/ParcelUuid;)Landroid/"
+                                                           "bluetooth/le/ScanFilter$Builder;");
+    if (!jni_mid_setServiceUuid)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_mid_setServiceUuid is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    // get scanfilter.Builder.build method id
+    jmethodID jni_mid_build_scanfilterBuilder = (*env)->GetMethodID(env,
+                                                                    jni_cid_scanfilterBuilder,
+                                                                    "build",
+                                                                    "()Landroid/bluetooth/le/"
+                                                                    "ScanFilter;");
+    if (!jni_mid_build_scanfilterBuilder)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_mid_build_scanfilterBuilder is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder);
+
+    // call ParcelUuid.fromSting(uuid)
+    jobject jni_obj_parcelUuid = CALEGetParcelUuidFromString(env, OIC_GATT_SERVICE_UUID);
+    if (!jni_obj_parcelUuid)
+    {
+        OIC_LOG(ERROR, TAG, "scanSettings: jni_obj_parcelUuid is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    // call setServiceUuid(uuid)
+    jobject jni_obj_setServiceUuid = (*env)->CallObjectMethod(env,
+                                                              jni_obj_scanfilterBuilder,
+                                                              jni_mid_setServiceUuid,
+                                                              jni_obj_parcelUuid);
+    if (!jni_obj_setServiceUuid)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_setServiceUuid is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder);
+        (*env)->DeleteLocalRef(env, jni_obj_parcelUuid);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_obj_parcelUuid);
+    (*env)->DeleteLocalRef(env, jni_obj_setServiceUuid);
+
+    // call build()
+    jobject jni_obj_scanfilter = (*env)->CallObjectMethod(env,
+                                                          jni_obj_scanfilterBuilder,
+                                                          jni_mid_build_scanfilterBuilder);
+    if (!jni_obj_scanfilter)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_scanfilter is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder);
+
+    // get scanSettings.Builder class id
+    jclass jni_cid_scanSettingsBuilder = (*env)->FindClass(env,
+                                                          "android/bluetooth/le/"
+                                                          "ScanSettings$Builder");
+    if (!jni_cid_scanSettingsBuilder)
+    {
+        OIC_LOG(ERROR, TAG, "scanSettings: jni_cid_scanSettingsBuilder is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        return CA_STATUS_FAILED;
+    }
+
+    // get scanSettings.Builder(ctor) method id
+    jmethodID jni_mid_scanSettingsBuilderCtor = (*env)->GetMethodID(env, jni_cid_scanSettingsBuilder,
+                                                                    "<init>", "()V");
+    if (!jni_mid_scanSettingsBuilderCtor)
+    {
+        OIC_LOG(ERROR, TAG, "scanSettings: jni_mid_scanSettingsBuilderCtor is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    // get scanSettings.Builder.setScanMode method id
+    jmethodID jni_mid_setScanMode = (*env)->GetMethodID(env, jni_cid_scanSettingsBuilder,
+                                                        "setScanMode",
+                                                         "(I)Landroid/"
+                                                         "bluetooth/le/ScanSettings$Builder;");
+    if (!jni_mid_setScanMode)
+    {
+        OIC_LOG(ERROR, TAG, "scanSettings: jni_mid_setScanMode is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    // get scanSettings.Builder.build method id
+    jmethodID jni_mid_build_scanSettings = (*env)->GetMethodID(env,
+                                                               jni_cid_scanSettingsBuilder,
+                                                               "build",
+                                                               "()Landroid/bluetooth/le/"
+                                                               "ScanSettings;");
+    if (!jni_mid_build_scanSettings)
+    {
+        OIC_LOG(ERROR, TAG, "scanSettings: jni_mid_build_scanSettings is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    // call scanSettings.Builder()
+    jobject jni_obj_scanSettingBuilder = (*env)->NewObject(env, jni_cid_scanSettingsBuilder,
+                                                           jni_mid_scanSettingsBuilderCtor);
+    if (!jni_obj_scanSettingBuilder)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_scanSettingBuilder is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder);
+
+    jclass jni_cid_arrayList = (*env)->FindClass(env, "java/util/ArrayList");
+    if (!jni_cid_arrayList)
+    {
+        OIC_LOG(ERROR, TAG, "ArrayList: jni_cid_arrayList is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    jmethodID jni_mid_arrayListCtor = (*env)->GetMethodID(env, jni_cid_arrayList, "<init>", "()V");
+    if (!jni_mid_arrayListCtor)
+    {
+        OIC_LOG(ERROR, TAG, "ArrayList: jni_mid_arrayListCtor is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_cid_arrayList);
+        (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    jmethodID jni_mid_arrayListAdd = (*env)->GetMethodID(env, jni_cid_arrayList,
+                                                         "add", "(Ljava/lang/Object;)Z");
+    if (!jni_mid_arrayListAdd)
+    {
+        OIC_LOG(ERROR, TAG, "ArrayList: jni_mid_arrayListAdd is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_cid_arrayList);
+        (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder);
+        return CA_STATUS_FAILED;
+    }
+
+    jobject jni_obj_filterList = (*env)->NewObject(env, jni_cid_arrayList, jni_mid_arrayListCtor);
+    if (!jni_obj_filterList)
+    {
+        OIC_LOG(ERROR, TAG, "ArrayList: jni_obj_filterList is null");
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_cid_arrayList);
+        (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_cid_arrayList);
+
+    jboolean jni_bool_arrayListIsAdded = (*env)->CallBooleanMethod(env, jni_obj_filterList,
+                                                                   jni_mid_arrayListAdd,
+                                                                   jni_obj_scanfilter);
+    if (!jni_bool_arrayListIsAdded)
+    {
+        OIC_LOG(ERROR, TAG, "ArrayList: jni_bool_arrayListIsAdded is null");
+        (*env)->DeleteLocalRef(env, jni_obj_filterList);
+        (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+        (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_obj_scanfilter);
+
+    // get ScanSettings.SCAN_MODE_BALANCED jint value
+    jint jni_int_scanBalancedMode = CALEGetConstantsValue(env, CLASSPATH_LE_SCANSETTINGS,
+                                                          "SCAN_MODE_BALANCED");
+    CACheckJNIException(env);
+
+    // call setScanMode(SCAN_MODE_BALANCED)
+    jobject jni_obj_setScanMode = (*env)->CallObjectMethod(env, jni_obj_scanSettingBuilder,
+                                                           jni_mid_setScanMode,
+                                                           jni_int_scanBalancedMode);
+    if (!jni_obj_setScanMode)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_setScanMode is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder);
+        (*env)->DeleteLocalRef(env, jni_obj_filterList);
+        return CA_STATUS_FAILED;
+    }
+
+    // call build
+    jobject jni_obj_scanSettings = (*env)->CallObjectMethod(env, jni_obj_scanSettingBuilder,
+                                                                 jni_mid_build_scanSettings);
+    if (!jni_obj_scanSettings)
+    {
+        OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_scanSettings is null");
+        (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder);
+        (*env)->DeleteLocalRef(env, jni_obj_filterList);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder);
+
+    CAResult_t res = CA_STATUS_FAILED;
+    // get default bt adapter class
+    jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
+    if (!jni_cid_BTAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
+        CACheckJNIException(env);
+        goto error_exit;
+    }
+
+    jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
+                                                                    "getDefaultAdapter",
+                                                                    "()Landroid/bluetooth/"
+                                                                    "BluetoothAdapter;");
+    if (!jni_mid_getDefaultAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        goto error_exit;
+    }
+
+    jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
+                                                               jni_mid_getDefaultAdapter);
+    if (!jni_obj_BTAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        goto error_exit;
+    }
+
+    // get remote bt adapter method
+    jmethodID jni_mid_getBluetoothLeScanner = (*env)->GetMethodID(env, jni_cid_BTAdapter,
+                                                                  "getBluetoothLeScanner",
+                                                                  "()Landroid/bluetooth/"
+                                                                  "le/BluetoothLeScanner;");
+    if (!jni_mid_getBluetoothLeScanner)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeScanner is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        goto error_exit;
+    }
+
+    // get le scanner object
+    jobject jni_obj_leScanner = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
+                                                         jni_mid_getBluetoothLeScanner);
+    if (!jni_obj_leScanner)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_leScanner is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        goto error_exit;
+    }
+    (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+    (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+
+    // call startScan method
+    OIC_LOG(INFO, TAG, "CALL API - startScanWithUUID(for level 21)");
+    (*env)->CallVoidMethod(env, jni_obj_leScanner, jni_mid_startScan, jni_obj_filterList,
+                           jni_obj_scanSettings, callback);
+    if (CACheckJNIException(env))
+    {
+        OIC_LOG(INFO, TAG, "startScan has failed");
+    }
+    else
+    {
+        res = CA_STATUS_OK;
+    }
+    (*env)->DeleteLocalRef(env, jni_obj_leScanner);
+
+error_exit:
+    (*env)->DeleteLocalRef(env, jni_obj_scanSettings);
+    (*env)->DeleteLocalRef(env, jni_obj_filterList);
+    return res;
+}
+
 jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
 {
     VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
@@ -1597,7 +2100,17 @@ CAResult_t CALEClientStopScan()
         isAttached = true;
     }
 
-    CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
+    CAResult_t ret = CA_STATUS_FAILED;
+
+    if (g_jniIntSdk >= BLE_SCAN_API_LEVEL)
+    {
+        ret = CALEClientStopScanImplForV21(env, g_leScanCallback);
+    }
+    else
+    {
+        ret = CALEClientStopScanImpl(env, g_leScanCallback);
+    }
+
     if (CA_STATUS_OK != ret)
     {
         if (CA_ADAPTER_NOT_ENABLED == ret)
@@ -1620,7 +2133,7 @@ CAResult_t CALEClientStopScan()
 
 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
 {
-    OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
+    OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl IN");
     VERIFY_NON_NULL(callback, TAG, "callback is null");
     VERIFY_NON_NULL(env, TAG, "env is null");
 
@@ -1663,7 +2176,7 @@ CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
         return CA_STATUS_FAILED;
     }
 
-    // gat bt adapter object
+    // get bt adapter object
     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
                                                                jni_mid_getDefaultAdapter);
     if (!jni_obj_BTAdapter)
@@ -1690,6 +2203,113 @@ CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
     return CA_STATUS_OK;
 }
 
+CAResult_t CALEClientStopScanImplForV21(JNIEnv *env, jobject callback)
+{
+    OIC_LOG(DEBUG, TAG, "CALEClientStopScanImplForV21 IN");
+    VERIFY_NON_NULL(callback, TAG, "callback is null");
+    VERIFY_NON_NULL(env, TAG, "env is null");
+
+    if (!CALEIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
+    }
+
+    // get default bt adapter class
+    jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
+    if (!jni_cid_BTAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
+        CACheckJNIException(env);
+        return CA_STATUS_FAILED;
+    }
+
+    jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
+                                                                    "getDefaultAdapter",
+                                                                    "()Landroid/bluetooth/"
+                                                                    "BluetoothAdapter;");
+    if (!jni_mid_getDefaultAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        return CA_STATUS_FAILED;
+    }
+
+    jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
+                                                               jni_mid_getDefaultAdapter);
+    if (!jni_obj_BTAdapter)
+    {
+        OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        return CA_STATUS_FAILED;
+    }
+
+    // get bluetoothLeScanner class
+    jclass jni_cid_leScanner = (*env)->FindClass(env, CLASSPATH_LE_SCANNER);
+    if (!jni_cid_leScanner)
+    {
+        OIC_LOG(ERROR, TAG, "getState From leScanner: jni_cid_leScanner is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        return CA_STATUS_FAILED;
+    }
+
+    // get remote bt adapter method
+    jmethodID jni_mid_getBluetoothLeScanner = (*env)->GetMethodID(env, jni_cid_BTAdapter,
+                                                                  "getBluetoothLeScanner",
+                                                                  "()Landroid/bluetooth/"
+                                                                  "le/BluetoothLeScanner;");
+    if (!jni_mid_getBluetoothLeScanner)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeScanner is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_cid_leScanner);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
+    // get stopScan(ScanCallback callback) method
+    jmethodID jni_mid_stopScan = (*env)->GetMethodID(env, jni_cid_leScanner, "stopScan",
+                                                      "(Landroid/bluetooth/le/ScanCallback;)V");
+    if (!jni_mid_stopScan)
+    {
+        OIC_LOG(ERROR, TAG, "stopScan: jni_mid_stopScan is null");
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_cid_leScanner);
+        return CA_STATUS_FAILED;
+    }
+    (*env)->DeleteLocalRef(env, jni_cid_leScanner);
+
+    // gat le scanner object
+    jobject jni_obj_leScanner = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
+                                                         jni_mid_getBluetoothLeScanner);
+    if (!jni_obj_leScanner)
+    {
+        OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_leScanner is null");
+        CACheckJNIException(env);
+        return CA_STATUS_FAILED;
+    }
+
+    // call stopScan method
+    OIC_LOG(INFO, TAG, "CALL API - stopScan for level 21");
+    (*env)->CallVoidMethod(env, jni_obj_leScanner, jni_mid_stopScan, callback);
+    if (CACheckJNIException(env))
+    {
+        OIC_LOG(INFO, TAG, "stopScan for level 21 has failed");
+        (*env)->DeleteLocalRef(env, jni_obj_leScanner);
+        return CA_STATUS_FAILED;
+    }
+
+    (*env)->DeleteLocalRef(env, jni_obj_leScanner);
+    return CA_STATUS_OK;
+}
+
 CAResult_t CALEClientDirectConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
 {
     OIC_LOG(DEBUG, TAG, "CALEClientDirectConnect");
@@ -4052,6 +4672,20 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env,
 }
 
 JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallbackForV21(JNIEnv *env,
+                                                                          jobject obj,
+                                                                          jobject callback)
+{
+    OIC_LOG(DEBUG, TAG, "caLeRegisterLeScanCallbackForV21");
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+    VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
+
+    g_leScanCallback = (*env)->NewGlobalRef(env, callback);
+    CACheckJNIException(env);
+}
+
+JNIEXPORT void JNICALL
 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
                                                                   jobject callback)
 {
@@ -4079,6 +4713,38 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject o
     }
 }
 
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeScanFailedCallback(JNIEnv *env, jobject obj,
+                                                                jint errorCode)
+{
+    VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+
+    switch (errorCode)
+    {
+        case 1:
+            OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_ALREADY_STARTED");
+            break;
+
+        case 2:
+            OIC_LOG(ERROR, TAG,
+                    "BLE scan has failed, error is SCAN_FAILED_APPLICATION_REGISTRATION_FAILED");
+            break;
+
+        case 3:
+            OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_INTERNAL_ERROR");
+            break;
+
+        case 4:
+            OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_FEATURE_UNSUPPORTED");
+            break;
+
+        default:
+            OIC_LOG(ERROR, TAG, "BLE scan has failed with unknown error");
+            break;
+    }
+}
+
 /*
  * Class:     org_iotivity_ca_jar_caleinterface
  * Method:    CALeGattConnectionStateChangeCallback
index 5e7fdbf..e05a0d4 100644 (file)
@@ -226,6 +226,14 @@ CAResult_t CALEClientStartScan();
 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback);
 
 /**
+ * start to scan whole bluetooth devices for android API level 21 (implement).
+ * @param[in]   env                   JNI interface pointer.
+ * @param[in]   callback              callback to receive device object by scanning.
+ * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CALEClientStartScanImplForV21(JNIEnv *env, jobject callback);
+
+/**
  * start to scan target bluetooth devices for service uuid (implement).
  * @param[in]   env                   JNI interface pointer.
  * @param[in]   uuids                 target UUID.
@@ -236,6 +244,16 @@ CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids,
                                            jobject callback);
 
 /**
+ * start to scan target bluetooth devices for service uuid for android API level 21 (implement).
+ * @param[in]   env                   JNI interface pointer.
+ * @param[in]   uuids                 target UUID.
+ * @param[in]   callback              callback to receive device object by scanning.
+ * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CALEClientStartScanWithUUIDImplForV21(JNIEnv *env, jobjectArray uuids,
+                                                 jobject callback);
+
+/**
  * get uuid object.
  * @param[in]   env                   JNI interface pointer.
  * @param[in]   uuid                  uuid.
@@ -258,6 +276,14 @@ CAResult_t CALEClientStopScan();
 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback);
 
 /**
+ * stop scan for android API level 21(implement).
+ * @param[in]   env                   JNI interface pointer.
+ * @param[in]   callback              callback to receive device object by scanning.
+ * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CALEClientStopScanImplForV21(JNIEnv *env, jobject callback);
+
+/**
  * connect to gatt server hosted.
  * @param[in]   env                   JNI interface pointer.
  * @param[in]   bluetoothDevice       bluetooth Device object.
index 7abefa6..c694152 100644 (file)
@@ -106,6 +106,50 @@ error_exit:
     return NULL;
 }
 
+jobject CALEGetParcelUuidFromString(JNIEnv *env, const char* uuid)
+{
+    VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+    VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
+
+    jclass jni_cid_ParcelUuid = (*env)->FindClass(env, "android/os/ParcelUuid");
+    if (!jni_cid_ParcelUuid)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_ParcelUuid is not available");
+        goto error_exit;
+    }
+
+    jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_ParcelUuid,
+                                                             "fromString",
+                                                             "(Ljava/lang/String;)"
+                                                             "Landroid/os/ParcelUuid;");
+    if (!jni_mid_fromString)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_fromString is not available");
+        goto error_exit;
+    }
+
+    jstring str_uuid = (*env)->NewStringUTF(env, uuid);
+    if (!str_uuid)
+    {
+        OIC_LOG(ERROR, TAG, "str_uuid is not available");
+        goto error_exit;
+    }
+
+    jobject jni_obj_parcelUuid = (*env)->CallStaticObjectMethod(env, jni_cid_ParcelUuid,
+                                                                jni_mid_fromString,
+                                                                str_uuid);
+    if (!jni_obj_parcelUuid)
+    {
+        OIC_LOG(ERROR, TAG, "Fail to get jni uuid object");
+        goto error_exit;
+    }
+
+    return jni_obj_parcelUuid;
+error_exit:
+    CACheckJNIException(env);
+    return NULL;
+}
+
 bool CALEIsBondedDevice(JNIEnv *env, jobject bluetoothDevice)
 {
     VERIFY_NON_NULL_RET(env, TAG, "env is null", false);
index b7812e9..fef040f 100644 (file)
@@ -52,7 +52,8 @@ static const char CLASSPATH_BT_GATT[] = "android/bluetooth/BluetoothGatt";
 static const char CLASSPATH_BT_ADAPTER[] = "android/bluetooth/BluetoothAdapter";
 static const char CLASSPATH_BT_DEVICE[] = "android/bluetooth/BluetoothDevice";
 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
-
+static const char CLASSPATH_LE_SCANNER[] = "android/bluetooth/le/BluetoothLeScanner";
+static const char CLASSPATH_LE_SCANSETTINGS[] = "android/bluetooth/le/ScanSettings";
 
 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
 static const char METHODID_BT_DEVICE[] = "()Landroid/bluetooth/BluetoothDevice;";
@@ -95,6 +96,14 @@ jobject CALEGetUuidFromString(JNIEnv *env, const char* uuid);
 jobject CALEGetParcelUuid(JNIEnv *env, jobject uuid);
 
 /**
+ * get parcel uuid object from uuid string value.
+ * @param[in]   env              JNI interface pointer.
+ * @param[in]   uuid             uuid (const char*).
+ * @return  parcel uuid object.
+ */
+jobject CALEGetParcelUuidFromString(JNIEnv *env, const char* uuid);
+
+/**
  * get address from a local device.
  * @param[in]   env              JNI interface pointer.
  * @return  local address.
index 2b9c21c..6d86fc2 100644 (file)
@@ -39,6 +39,15 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback
 
 /*
  * Class:     org_iotivity_ca_CaLeClientInterface
+ * Method:    caLeRegisterLeScanCallback
+ * Signature: (Landroid/bluetooth/le/ScanCallback;)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallbackForV21
+(JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     org_iotivity_ca_caLeClientInterface
  * Method:    caLeRegisterGattCallback
  * Signature: (Landroid/bluetooth/BluetoothGattCallback;)V
  */
@@ -57,6 +66,15 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback
 
 /*
  * Class:     org_iotivity_ca_CaLeClientInterface
+ * Method:    caLeScanFailedCallback
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeScanFailedCallback
+(JNIEnv *, jobject, jint);
+
+/*
+ * Class:     org_iotivity_ca_caLeClientInterface
  * Method:    caLeGattConnectionStateChangeCallback
  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
  */