From: jihwan.seo Date: Wed, 9 Sep 2015 13:04:19 +0000 (+0900) Subject: Updated Android Sample App for block-wise transfer X-Git-Tag: 1.2.0+RC1~1086^2~45 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=835c993d20a48687f5ff095e347e5831939c6e96;p=platform%2Fupstream%2Fiotivity.git Updated Android Sample App for block-wise transfer - 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 Reviewed-on: https://gerrit.iotivity.org/gerrit/2423 Tested-by: jenkins-iotivity Reviewed-by: Patrick Lankswert --- diff --git a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/AndroidManifest.xml b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/AndroidManifest.xml index 4848fee..40963c5 100755 --- a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/AndroidManifest.xml +++ b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/AndroidManifest.xml @@ -32,6 +32,6 @@ - + + - 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 index 0000000..d2e50d8 --- /dev/null +++ b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/FileChooser.java @@ -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); + } + } +} diff --git a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/MainActivity.java b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/MainActivity.java index 4582e9c..35a2d25 100755 --- a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/MainActivity.java +++ b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/MainActivity.java @@ -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 diff --git a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/RMInterface.java b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/RMInterface.java index 0c9db02..39608c5 100755 --- a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/RMInterface.java +++ b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/java/org/iotivity/ca/service/RMInterface.java @@ -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); diff --git a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c index ce5f039..b9cd82a 100644 --- a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c +++ b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c @@ -4,6 +4,7 @@ #include #include #include +#include #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(¤t_time); + time_info = localtime(¤t_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); +} diff --git a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/org_iotivity_ca_service_RMInterface.h b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/org_iotivity_ca_service_RMInterface.h index 6f60059..b2a5d66 100644 --- a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/org_iotivity_ca_service_RMInterface.h +++ b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/org_iotivity_ca_service_RMInterface.h @@ -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 diff --git a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/res/layout/activity_main.xml b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/res/layout/activity_main.xml index 7c35a9d..69642b6 100755 --- a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/res/layout/activity_main.xml +++ b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/res/layout/activity_main.xml @@ -239,6 +239,13 @@ android:layout_toRightOf="@id/btn_receive" android:text="@string/get_network_info" /> +