Updated Android Sample App for block-wise transfer
authorjihwan.seo <jihwan.seo@samsung.com>
Wed, 9 Sep 2015 13:04:19 +0000 (22:04 +0900)
committerPatrick Lankswert <patrick.lankswert@intel.com>
Fri, 11 Sep 2015 19:02:10 +0000 (19:02 +0000)
- To add big data from sample app for block-wise transfer.
- this change is came from Change 1371.
  https://gerrit.iotivity.org/gerrit/#/c/1373/

Change-Id: I983f106a5d0b750457da46865d81b0efb5ebd3fc
Signed-off-by: jihwan.seo <jihwan.seo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2423
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Patrick Lankswert <patrick.lankswert@intel.com>
resource/csdk/connectivity/samples/android/casample/sampleService/src/main/AndroidManifest.xml
resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/FileChooser.java [new file with mode: 0644]
resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/MainActivity.java
resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/RMInterface.java
resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c
resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/org_iotivity_ca_service_RMInterface.h
resource/csdk/connectivity/samples/android/casample/sampleService/src/main/res/layout/activity_main.xml

index 4848fee..40963c5 100755 (executable)
@@ -32,6 +32,6 @@
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
-
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 </manifest>
-
diff --git a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/FileChooser.java b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/FileChooser.java
new file mode 100644 (file)
index 0000000..d2e50d8
--- /dev/null
@@ -0,0 +1,135 @@
+package org.iotivity.ca.service;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.os.Environment;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager.LayoutParams;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Arrays;
+
+public class FileChooser {
+    private static final String PARENT_DIR = "..";
+
+    private final Activity activity;
+    private ListView list;
+    private Dialog dialog;
+    private File currentPath;
+
+    // filter on file extension
+    private String extension = null;
+    public void setExtension(String extension) {
+        this.extension = (extension == null) ? null :
+                extension.toLowerCase();
+    }
+
+    // file selection event handling
+    public interface FileSelectedListener {
+        void fileSelected(File file);
+    }
+    public FileChooser setFileListener(FileSelectedListener fileListener) {
+        this.fileListener = fileListener;
+        return this;
+    }
+    private FileSelectedListener fileListener;
+
+    public FileChooser(Activity activity) {
+        this.activity = activity;
+        dialog = new Dialog(activity);
+        list = new ListView(activity);
+        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override public void onItemClick(AdapterView<?> parent, View view, int which, long id) {
+                String fileChosen = (String) list.getItemAtPosition(which);
+                File chosenFile = getChosenFile(fileChosen);
+                if (chosenFile.isDirectory()) {
+                    refresh(chosenFile);
+                } else {
+                    if (fileListener != null) {
+                        fileListener.fileSelected(chosenFile);
+                    }
+                    dialog.dismiss();
+                }
+            }
+        });
+        dialog.setContentView(list);
+        dialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+        refresh(Environment.getExternalStorageDirectory());
+    }
+
+    public void showDialog() {
+        dialog.show();
+    }
+
+
+    /**
+     * Sort, filter and display the files for the given path.
+     */
+    private void refresh(File path) {
+        this.currentPath = path;
+        if (path.exists()) {
+            File[] dirs = path.listFiles(new FileFilter() {
+                @Override public boolean accept(File file) {
+                    return (file.isDirectory() && file.canRead());
+                }
+            });
+            File[] files = path.listFiles(new FileFilter() {
+                @Override public boolean accept(File file) {
+                    if (!file.isDirectory()) {
+                        if (!file.canRead()) {
+                            return false;
+                        } else if (extension == null) {
+                            return true;
+                        } else {
+                            return file.getName().toLowerCase().endsWith(extension);
+                        }
+                    } else {
+                        return false;
+                    }
+                }
+            });
+
+            // convert to an array
+            int i = 0;
+            String[] fileList;
+            if (path.getParentFile() == null) {
+                fileList = new String[dirs.length + files.length];
+            } else {
+                fileList = new String[dirs.length + files.length + 1];
+                fileList[i++] = PARENT_DIR;
+            }
+            Arrays.sort(dirs);
+            Arrays.sort(files);
+            for (File dir : dirs) { fileList[i++] = dir.getName(); }
+            for (File file : files ) { fileList[i++] = file.getName(); }
+
+            // refresh the user interface
+            dialog.setTitle(currentPath.getPath());
+            list.setAdapter(new ArrayAdapter(activity,
+                   android.R.layout.simple_list_item_1, fileList) {
+                       @Override public View getView(int pos, View view, ViewGroup parent) {
+                           view = super.getView(pos, view, parent);
+                           ((TextView) view).setSingleLine(true);
+                           return view;
+                       }
+                   });
+        }
+    }
+
+
+    /**
+     * Convert a relative filename into an actual File object.
+     */
+    private File getChosenFile(String fileChosen) {
+        if (fileChosen.equals(PARENT_DIR)) {
+            return currentPath.getParentFile();
+        } else {
+            return new File(currentPath, fileChosen);
+        }
+    }
+}
index 4582e9c..35a2d25 100755 (executable)
@@ -14,8 +14,12 @@ import android.widget.Button;
 import android.widget.EditText;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
+import android.widget.Toast;
+import java.io.File;
 
 import org.iotivity.ca.sample_service.R;
+import org.iotivity.ca.service.FileChooser;
+import org.iotivity.ca.service.FileChooser.FileSelectedListener;
 
 public class MainActivity extends Activity {
 
@@ -122,6 +126,8 @@ public class MainActivity extends Activity {
 
     private Button mRecv_btn = null;
 
+    private Button mBig_btn = null;
+
     private Handler mLogHandler = null;
 
     /**
@@ -144,6 +150,7 @@ public class MainActivity extends Activity {
     int uninterestedNetwork = 0;
     private boolean isSendResponseSetting = false;
     private boolean isSendRequestToAllSetting = false;
+    private boolean isBigData = false;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -195,6 +202,8 @@ public class MainActivity extends Activity {
         mResponse_Notify_setting_btn = (Button) findViewById(R.id.btn_Request_setting_for_server);
         mGetNetworkInfo_btn = (Button) findViewById(R.id.btn_get_network_info);
         mRecv_btn = (Button) findViewById(R.id.btn_receive);
+        mBig_btn = (Button) findViewById(R.id.btn_big_data);
+        mBig_btn.setOnClickListener(mSelectLargeDataButtonHandler);
 
         mResponse_btn.setOnClickListener(mSendResponseHandler);
         mNotify_btn.setOnClickListener(mNotifyHandler);
@@ -391,7 +400,7 @@ public class MainActivity extends Activity {
             DLog.v(TAG, "SendRequest click");
             if ( selectedNetwork != -1) {
                 RM.RMSendRequest(mReqData_ed.getText().toString(), null,
-                    selectedNetwork, isSecured, msgType);
+                    selectedNetwork, isSecured, msgType, false);
             }
             else {
                 DLog.v(TAG, "Please Select Network Type");
@@ -457,6 +466,15 @@ public class MainActivity extends Activity {
         }
     };
 
+    private OnClickListener mSelectLargeDataButtonHandler = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+
+            isBigData = true;
+            checkSendNetworkType("Select Send Network Type");
+        }
+    };
+
     private void checkInterestedNetwork(String title) {
 
         AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
@@ -675,7 +693,7 @@ public class MainActivity extends Activity {
 
                         if (selectedNetworkType == Network.IP.ordinal()) {
                             selectedNetwork = CA_IP;
-                            DLog.v(TAG, "Selected Network is CA_IP");
+                            DLog.v(TAG, "Selected Network is IP");
                         } else if (selectedNetworkType == Network.LE.ordinal()) {
                             selectedNetwork = CA_LE;
                             DLog.v(TAG, "Selected Network is LE");
@@ -687,10 +705,32 @@ public class MainActivity extends Activity {
                             selectedNetwork = -1;
                         }
 
-                        if (isSendRequestToAllSetting != true) {
-                            checkMsgSecured("Select DTLS Type");
+                        if (isBigData)
+                        {
+                            new FileChooser(MainActivity.this).setFileListener(new FileSelectedListener() {
+                                public void fileSelected(final File file) {
+                                    if (selectedNetwork != -1) {
+
+                                        String path = file.getAbsolutePath();
+                                        Log.d(TAG, "File Path: " + path);
+
+                                        RM.RMSendRequest(mReqData_ed.getText().toString(), path,
+                                                         selectedNetwork, isSecured, msgType, true);
+                                    } else {
+                                        Toast.makeText(getApplicationContext(),
+                                                       "Request Setting Fisrt!!", Toast.LENGTH_LONG).show();
+                                    }
+                                }
+                            } ).showDialog();
+                            isBigData = false;
+                        } else {
+                            if (isSendRequestToAllSetting != true) {
+                                checkMsgSecured("Select DTLS Type");
+                            }
                         }
+
                         isSendRequestToAllSetting = false;
+                        isBigData = false;
                     }
                 }).show();
     }
@@ -717,4 +757,4 @@ public class MainActivity extends Activity {
             mNotification_ed.setText(sb.toString());
         }
     }
-}
+}
\ No newline at end of file
index 0c9db02..39608c5 100755 (executable)
@@ -26,7 +26,7 @@ public class RMInterface {
     public native void RMFindResource(String uri);
 
     public native void RMSendRequest(String uri, String payload,
-            int selectedNetwork, int isSecured, int msgType);
+            int selectedNetwork, int isSecured, int msgType, boolean isBigData);
 
     public native void RMSendReqestToAll(String uri, int selectedNetwork);
 
index ce5f039..b9cd82a 100644 (file)
@@ -4,6 +4,7 @@
 #include <dlfcn.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
 #include "cainterface.h"
 #include "cacommon.h"
@@ -30,6 +31,9 @@
 #define RESOURCE_URI_LENGTH 14
 #define OPTION_INFO_LENGTH 1024
 #define NETWORK_INFO_LENGTH 1024
+#define BIG_PAYLOAD_LENGTH 1024
+#define RECEIVED_FILE_NAME_PREFIX_LENGTH 7
+#define RECEIVED_FILE_NAME_LENGTH 14
 
 typedef struct
 {
@@ -48,6 +52,9 @@ static CAResult_t get_remote_address(const char *address);
 static void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t *flags);
 static void delete_global_references(JNIEnv *env, jobject obj);
 static int get_address_set(const char *pAddress, addressSet_t* outAddress);
+bool read_file(const char* name, char** bytes, size_t* length);
+uint32_t gettodaydate();
+void saveFile(const char *payload, size_t payloadSize);
 
 uint16_t g_localSecurePort = SECURE_DEFAULT_PORT;
 CATransportAdapter_t g_selectedNwType = CA_ADAPTER_IP;
@@ -59,6 +66,8 @@ static const char COAPS_PREFIX[] = "coaps://";
 static const uint16_t COAP_PREFIX_LEN = sizeof(COAP_PREFIX) - 1;
 static const uint16_t COAPS_PREFIX_LEN = sizeof(COAPS_PREFIX) - 1;
 
+static const char RECEIVED_FILE_PATH[] = "/storage/emulated/0/Download/%d%s.txt";
+
 static const char SECURE_INFO_DATA[]
                                    = "{\"oc\":[{\"href\":\"%s\",\"prop\":{\"rt\":[\"core.led\"],"
                                      "\"if\":[\"oic.if.baseline\"],\"obs\":1,\"sec\":1,\"port\":"
@@ -298,7 +307,8 @@ Java_org_iotivity_ca_service_RMInterface_RMRegisterHandler(JNIEnv *env, jobject
 JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMSendRequest(JNIEnv *env, jobject obj, jstring uri,
                                                        jstring payload, jint selectedNetwork,
-                                                       jint isSecured, jint msgType)
+                                                       jint isSecured, jint msgType,
+                                                       jboolean isBigData)
 {
     LOGI("selectedNetwork - %d", selectedNetwork);
     if (!env || !obj)
@@ -307,11 +317,6 @@ Java_org_iotivity_ca_service_RMInterface_RMSendRequest(JNIEnv *env, jobject obj,
         return;
     }
 
-    if (!payload)
-    {
-        LOGE("payload is NULL");
-    }
-
     if (!uri)
     {
         LOGE("Invalid input parameter : uri");
@@ -367,37 +372,75 @@ Java_org_iotivity_ca_service_RMInterface_RMSendRequest(JNIEnv *env, jobject obj,
     requestData.token = token;
     requestData.tokenLength = tokenLength;
 
-    if (1 == isSecured)
+    size_t payloadLength = 0;
+    if (isBigData)
     {
-        uint32_t length = sizeof(SECURE_INFO_DATA) + strlen(resourceURI);
-        requestData.payload = (CAPayload_t) malloc(length);
-        if (NULL == requestData.payload)
+        const char* path = NULL;
+        if (payload)
         {
-            LOGE("Memory allocation failed!");
-            // destroy token
-            CADestroyToken(token);
-            // destroy remote endpoint
-            CADestroyEndpoint(endpoint);
-            return;
+            path = (*env)->GetStringUTFChars(env, payload, NULL);
+            if(path)
+            {
+                char* bigData = NULL;
+                bool result = read_file(path, &bigData, &payloadLength);
+                if (!result)
+                {
+                    LOGE("read has failed");
+                    (*env)->ReleaseStringUTFChars(env, payload, path);
+                    return;
+                }
+                (*env)->ReleaseStringUTFChars(env, payload, path);
+
+                requestData.payload = (CAPayload_t) malloc(payloadLength);
+                if (NULL == requestData.payload)
+                {
+                    LOGE("Memory allocation failed!");
+                    // destroy token
+                    CADestroyToken(token);
+                    // destroy remote endpoint
+                    CADestroyEndpoint(endpoint);
+                    return;
+                }
+                memcpy(requestData.payload, bigData, payloadLength);
+                requestData.payloadSize = payloadLength;
+            }
         }
-        snprintf((char *) requestData.payload, length, SECURE_INFO_DATA, resourceURI, g_localSecurePort);
-        requestData.payloadSize = length;
     }
     else
     {
-        uint32_t length = sizeof(NORMAL_INFO_DATA) + strlen(resourceURI);
-        requestData.payload = (CAPayload_t) malloc(length);
-        if (NULL == requestData.payload)
+        if (isSecured)
         {
-            LOGE("Memory allocation failed!");
-            // destroy token
-            CADestroyToken(token);
-            // destroy remote endpoint
-            CADestroyEndpoint(endpoint);
-            return;
+            payloadLength = sizeof(SECURE_INFO_DATA) + strlen(resourceURI);
+            requestData.payload = (CAPayload_t) malloc(payloadLength);
+            if (NULL == requestData.payload)
+            {
+                LOGE("Memory allocation failed!");
+                // destroy token
+                CADestroyToken(token);
+                // destroy remote endpoint
+                CADestroyEndpoint(endpoint);
+                return;
+            }
+            snprintf((char *) requestData.payload, payloadLength, SECURE_INFO_DATA,
+                     resourceURI, g_localSecurePort);
+            requestData.payloadSize = payloadLength;
+        }
+        else
+        {
+            payloadLength = sizeof(NORMAL_INFO_DATA) + strlen(resourceURI);
+            requestData.payload = (CAPayload_t) malloc(payloadLength);
+            if (NULL == requestData.payload)
+            {
+                LOGE("Memory allocation failed!");
+                // destroy token
+                CADestroyToken(token);
+                // destroy remote endpoint
+                CADestroyEndpoint(endpoint);
+                return;
+            }
+            snprintf((char *) requestData.payload, payloadLength, NORMAL_INFO_DATA, resourceURI);
+            requestData.payloadSize = payloadLength;
         }
-        snprintf((char *) requestData.payload, length, NORMAL_INFO_DATA, resourceURI);
-        requestData.payloadSize = length;
     }
 
     requestData.type = messageType;
@@ -1023,7 +1066,14 @@ void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestI
             memcpy(clonePayload, requestInfo->info.payload, len);
             clonePayload[len] = '\0';
 
-            callback("Data: ", clonePayload);
+            if (len > BIG_PAYLOAD_LENGTH)
+            {
+                saveFile(clonePayload, len);
+            }
+            else
+            {
+                callback("Data: ", clonePayload);
+            }
             free(clonePayload);
         }
     }
@@ -1168,7 +1218,14 @@ void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* respon
             memcpy(clonePayload, responseInfo->info.payload, len);
             clonePayload[len] = '\0';
 
-            callback("Data: ", clonePayload);
+            if (len > BIG_PAYLOAD_LENGTH)
+            {
+                saveFile(clonePayload, len);
+            }
+            else
+            {
+                callback("Data: ", clonePayload);
+            }
             free(clonePayload);
         }
     }
@@ -1584,3 +1641,104 @@ void delete_global_references(JNIEnv *env, jobject obj)
 
     (*env)->DeleteGlobalRef(env, g_responseListenerObject);
 }
+
+
+bool read_file(const char* name, char** bytes, size_t* length)
+{
+    if (NULL == name)
+    {
+        LOGE("parameter is null");
+        return false;
+    }
+
+    FILE* file;
+    char* buffer;
+    size_t fileLen;
+
+    // Open file
+    file = fopen(name, "rt");
+    if (!file)
+    {
+        fprintf(stderr, "Unable to open file %s", name);
+        return false;
+    }
+
+    // Get file length
+    fseek(file, 0, SEEK_END);
+    fileLen = ftell(file);
+    fseek(file, 0, SEEK_SET);
+
+    LOGI("file size: %d", fileLen);
+
+    // Allocate memory
+    buffer = calloc(1, sizeof(char) * fileLen + 1);
+    if (!buffer)
+    {
+        fprintf(stderr, "Memory error!");
+        fclose(file);
+        return false;
+    }
+
+    // Read file contents into buffer
+    fread(buffer, fileLen, 1, file);
+    fclose(file);
+
+    LOGI("file bytes: %s", buffer);
+
+    *bytes = buffer;
+    *length = fileLen;
+
+    return true;
+}
+
+void saveFile(const char *payload, size_t payloadSize)
+{
+    // 1. get day
+    uint32_t day = gettodaydate();
+
+    // 2. get time
+    time_t current_time;
+    struct tm * time_info;
+    char timeString[RECEIVED_FILE_NAME_PREFIX_LENGTH];
+
+    time(&current_time);
+    time_info = localtime(&current_time);
+
+    strftime(timeString, sizeof(timeString), "%H%M%S", time_info);
+
+    uint32_t path_length = strlen(RECEIVED_FILE_PATH) + RECEIVED_FILE_NAME_LENGTH + 1;
+    char* path = calloc(1, sizeof(char) * path_length);
+    if (path != NULL)
+    {
+        sprintf(path, RECEIVED_FILE_PATH, day, timeString);
+        LOGI("received file path: %s", path);
+
+        FILE *fp = fopen(path, "wt");
+        fwrite(payload, 1, payloadSize, fp);
+        fclose(fp);
+
+        callback("File Path: ", path);
+    }
+    else
+    {
+        LOGE("path Out of memory");
+    }
+}
+
+uint32_t gettodaydate()
+{
+    uint32_t ldate;
+    time_t clock;
+    struct tm *date;
+
+    clock = time(0);
+    date = localtime(&clock);
+    ldate = date->tm_year * 100000;
+    ldate += (date->tm_mon + 1) * 1000;
+    ldate += date->tm_mday * 10;
+    ldate += date->tm_wday;
+    ldate += 190000000;
+    ldate /= 10;
+
+    return(ldate);
+}
index 6f60059..b2a5d66 100644 (file)
@@ -54,7 +54,7 @@ JNIEXPORT void JNICALL Java_org_iotivity_ca_service_RMInterface_RMRegisterHandle
  * Signature: (Ljava/lang/String;Ljava/lang/String;III)V
  */
 JNIEXPORT void JNICALL Java_org_iotivity_ca_service_RMInterface_RMSendRequest
-  (JNIEnv *, jobject, jstring, jstring, jint, jint, jint);
+  (JNIEnv *, jobject, jstring, jstring, jint, jint, jint, jboolean);
 
 /*
  * Class:     org_iotivity_ca_service_RMInterface
index 7c35a9d..69642b6 100755 (executable)
                 android:layout_toRightOf="@id/btn_receive"
                 android:text="@string/get_network_info" />
 
+            <Button
+                android:id="@+id/btn_big_data"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toRightOf="@id/btn_get_network_info"
+                android:text="big data" />
+
         </RelativeLayout>
     </RelativeLayout>
 
             android:layout_height="wrap_content" />
     </ScrollView>
 
-</RelativeLayout>
+</RelativeLayout>
\ No newline at end of file