diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/Utilities.java b/app/src/main/java/org/communiquons/android/comunic/client/data/Utilities.java
index 799b791..0e09321 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/data/Utilities.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/data/Utilities.java
@@ -2,18 +2,24 @@ package org.communiquons.android.comunic.client.data;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Bitmap;
import android.os.Build;
+import android.support.annotation.NonNull;
import android.text.Html;
import android.text.TextUtils;
+import android.util.Base64;
import android.util.Log;
import android.util.Patterns;
import org.communiquons.android.comunic.client.R;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
@@ -191,6 +197,48 @@ public class Utilities {
return count;
}
+ /**
+ * Read an InputStream into a string
+ *
+ * @param is The input stream
+ * @return The string
+ */
+ public static String isToString(InputStream is){
+
+ try {
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ StringBuilder stringBuilder = new StringBuilder();
+ String line;
+
+ while((line = bufferedReader.readLine()) != null){
+ stringBuilder.append(line);
+ }
+ bufferedReader.close();
+
+ //Return the result
+ return stringBuilder.toString();
+
+ } catch (IOException e){
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Convert a Bitmap into a base64-encoded string
+ *
+ * @param bitmap The bitmap to convert
+ * @return Encoded string
+ */
+ public static String bitmapToBase64(@NonNull Bitmap bitmap){
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.PNG, 80, byteArrayOutputStream);
+ byte[] byteArray = byteArrayOutputStream.toByteArray();
+
+ return Base64.encodeToString(byteArray, Base64.DEFAULT);
+ }
+
+
/**
* Prepare a string sent through the API to be shown in a TextView element
*
@@ -265,5 +313,4 @@ public class Utilities {
}
}
-
}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/conversations/ConversationMessagesHelper.java b/app/src/main/java/org/communiquons/android/comunic/client/data/conversations/ConversationMessagesHelper.java
index 899b50c..95d0207 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/data/conversations/ConversationMessagesHelper.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/data/conversations/ConversationMessagesHelper.java
@@ -83,9 +83,10 @@ public class ConversationMessagesHelper {
*
* @param convID Target conversation ID
* @param message The message to send
+ * @param image Base64 encoded image to include with the message (can be null)
* @return true in case of success / false else
*/
- public boolean sendMessage(int convID, String message){
+ public boolean sendMessage(int convID, String message, @Nullable String image){
//Make an API request
APIRequestParameters params = new APIRequestParameters(mContext,
@@ -93,6 +94,10 @@ public class ConversationMessagesHelper {
params.addParameter("conversationID", ""+convID);
params.addParameter("message", message);
+ //Include image (if any)
+ if(image != null)
+ params.addParameter("image", "data:image/png;base64," + image);
+
try {
new APIRequest().exec(params);
return true;
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/fragments/ConversationFragment.java b/app/src/main/java/org/communiquons/android/comunic/client/fragments/ConversationFragment.java
index a454b2c..ef499e4 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/fragments/ConversationFragment.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/fragments/ConversationFragment.java
@@ -1,6 +1,12 @@
package org.communiquons.android.comunic.client.fragments;
+import android.app.AlertDialog;
import android.app.Fragment;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -19,13 +25,18 @@ import org.communiquons.android.comunic.client.data.Account.AccountUtils;
import org.communiquons.android.comunic.client.data.DatabaseHelper;
import org.communiquons.android.comunic.client.data.UsersInfo.GetUsersHelper;
import org.communiquons.android.comunic.client.data.UsersInfo.UserInfo;
+import org.communiquons.android.comunic.client.data.Utilities;
import org.communiquons.android.comunic.client.data.conversations.ConversationMessage;
import org.communiquons.android.comunic.client.data.conversations.ConversationMessageAdapter;
import org.communiquons.android.comunic.client.data.conversations.ConversationMessagesHelper;
import org.communiquons.android.comunic.client.data.conversations.ConversationRefreshRunnable;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
import java.util.ArrayList;
+import static android.app.Activity.RESULT_OK;
+
/**
* Conversation fragment
*
@@ -38,6 +49,11 @@ import java.util.ArrayList;
public class ConversationFragment extends Fragment
implements ConversationRefreshRunnable.onMessagesChangeListener {
+ /**
+ * Pick image request number
+ */
+ public static final int PICK_PHOTO = 1;
+
/**
* Debug tag
*/
@@ -98,6 +114,16 @@ public class ConversationFragment extends Fragment
*/
private ImageButton send_button;
+ /**
+ * Conversation add image button
+ */
+ private ImageButton pick_image_button;
+
+ /**
+ * New message selected image
+ */
+ private Bitmap new_message_bitmap = null;
+
/**
* Get user helper
*/
@@ -125,6 +151,19 @@ public class ConversationFragment extends Fragment
}
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ switch (requestCode) {
+
+ //If the response if for the photos
+ case PICK_PHOTO :
+ pick_image_callback(resultCode, data);
+ break;
+ }
+ }
+
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -151,14 +190,31 @@ public class ConversationFragment extends Fragment
//Get new messages input fields
new_message_content = view.findViewById(R.id.fragment_conversation_newmessage_content);
+ pick_image_button = view.findViewById(R.id.fragment_conversation_newmessage_pickimage);
send_button = view.findViewById(R.id.fragment_conversation_newmessage_send);
+ //Make send button lives
send_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
send_message();
}
});
+
+ //Make pick image button lives
+ pick_image_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ pick_image();
+ }
+ });
+ pick_image_button.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ confirm_remove_picked_image();
+ return true;
+ }
+ });
}
@Override
@@ -248,13 +304,86 @@ public class ConversationFragment extends Fragment
convMessAdapter.notifyDataSetChanged();
}
+ /**
+ * This method is called when the user request to add an image to a message
+ */
+ private void pick_image(){
+ Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
+ photoPickerIntent.setType("image/*");
+ startActivityForResult(photoPickerIntent, PICK_PHOTO);
+ }
+
+ /**
+ * This method is called to confirm to remove a previously picked image
+ */
+ private void confirm_remove_picked_image(){
+ new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.conversation_message_remove_image_popup_title)
+ .setMessage(R.string.conversation_message_remove_image_popup_message)
+
+ .setNegativeButton(R.string.conversation_message_remove_image_popup_cancel, null)
+
+ .setPositiveButton(R.string.conversation_message_remove_image_popup_confirm,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ remove_picked_image();
+ }
+ })
+
+ .show();
+ }
+
+ /**
+ * Handles image picker callback
+ *
+ * @param resultCode The result code of the request
+ * @param data The data passed with the intent
+ */
+ private void pick_image_callback(int resultCode, Intent data){
+ //Continue in case of success
+ if(resultCode == RESULT_OK){
+ try {
+
+ Uri imageUri = data.getData();
+ InputStream imageStream = getActivity().getContentResolver()
+ .openInputStream(imageUri);
+ new_message_bitmap = BitmapFactory.decodeStream(imageStream);
+
+ //Append image
+ pick_image_button.setImageBitmap(new_message_bitmap);
+
+
+ } catch (FileNotFoundException e){
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Remove a previously picked image in the new message form
+ */
+ private void remove_picked_image(){
+
+ //Clean bitmap
+ if(new_message_bitmap != null){
+ new_message_bitmap.recycle();
+ new_message_bitmap = null;
+ }
+
+ //Reset image button
+ pick_image_button.setImageBitmap(null);
+ pick_image_button.setImageDrawable(getActivity().getResources().
+ getDrawable(android.R.drawable.ic_menu_gallery, getActivity().getTheme()));
+ }
+
/**
* This method is called when the user click on the "send_message" button
*/
private void send_message(){
//Check message length
- if(new_message_content.length() < 3){
+ if(new_message_content.length() < 3 && new_message_bitmap == null){
Toast.makeText(getActivity(), R.string.conversation_message_err_too_short,
Toast.LENGTH_SHORT).show();
return;
@@ -271,7 +400,9 @@ public class ConversationFragment extends Fragment
@Override
protected Boolean doInBackground(Void... params) {
- return convMessHelper.sendMessage(conversation_id, message_content);
+ String message_image = new_message_bitmap == null ?
+ null : Utilities.bitmapToBase64(new_message_bitmap);
+ return convMessHelper.sendMessage(conversation_id, message_content, message_image);
}
@Override
@@ -294,9 +425,12 @@ public class ConversationFragment extends Fragment
Toast.LENGTH_SHORT).show();
}
- //Remove previous message in case of succes
+ //Remove previous message in case of success
if(success){
new_message_content.setText("");
+
+ //Remove image
+ remove_picked_image();
}
//Make the "send" button available again
diff --git a/app/src/main/res/layout/fragment_conversation.xml b/app/src/main/res/layout/fragment_conversation.xml
index c364774..2ff6f55 100644
--- a/app/src/main/res/layout/fragment_conversation.xml
+++ b/app/src/main/res/layout/fragment_conversation.xml
@@ -27,10 +27,18 @@
android:layout_height="wrap_content"
android:hint="@string/fragment_conversation_new_message_placeholder"/>
+
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index a8f336c..3ae54e2 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -6,4 +6,8 @@
20dp
20dp
+
+
+ 50dp
+ 50dp
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d5f097c..4779808 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -32,7 +32,7 @@
Respond request
Deny
Respond to the request
- Do you want to accept or deny this friendship request ?
+ Do you want to accept or deny this friendship request ?
An error occurred while retrieving conversations list !
%d members
now
@@ -54,7 +54,12 @@
Could not load messages!
Conversation message image
Send
- The length of the message is too short !
+ The message is too short !
The message could not be sent! Please check your message and try again…
New message…
+ Add an image
+ Remove image
+ Do you want to remove selected image ?
+ Yes
+ No