Images can be sent throught conversation system

This commit is contained in:
Pierre 2017-12-25 13:08:03 +01:00
parent b45c7d1fd9
commit bae12c79dc
6 changed files with 212 additions and 9 deletions

View File

@ -2,18 +2,24 @@ package org.communiquons.android.comunic.client.data;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap;
import android.os.Build; import android.os.Build;
import android.support.annotation.NonNull;
import android.text.Html; import android.text.Html;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Base64;
import android.util.Log; import android.util.Log;
import android.util.Patterns; import android.util.Patterns;
import org.communiquons.android.comunic.client.R; import org.communiquons.android.comunic.client.R;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.security.MessageDigest; import java.security.MessageDigest;
@ -191,6 +197,48 @@ public class Utilities {
return count; 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 * Prepare a string sent through the API to be shown in a TextView element
* *
@ -265,5 +313,4 @@ public class Utilities {
} }
} }
} }

View File

@ -83,9 +83,10 @@ public class ConversationMessagesHelper {
* *
* @param convID Target conversation ID * @param convID Target conversation ID
* @param message The message to send * @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 * @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 //Make an API request
APIRequestParameters params = new APIRequestParameters(mContext, APIRequestParameters params = new APIRequestParameters(mContext,
@ -93,6 +94,10 @@ public class ConversationMessagesHelper {
params.addParameter("conversationID", ""+convID); params.addParameter("conversationID", ""+convID);
params.addParameter("message", message); params.addParameter("message", message);
//Include image (if any)
if(image != null)
params.addParameter("image", "data:image/png;base64," + image);
try { try {
new APIRequest().exec(params); new APIRequest().exec(params);
return true; return true;

View File

@ -1,6 +1,12 @@
package org.communiquons.android.comunic.client.fragments; package org.communiquons.android.comunic.client.fragments;
import android.app.AlertDialog;
import android.app.Fragment; 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.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; 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.DatabaseHelper;
import org.communiquons.android.comunic.client.data.UsersInfo.GetUsersHelper; 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.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.ConversationMessage;
import org.communiquons.android.comunic.client.data.conversations.ConversationMessageAdapter; 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.ConversationMessagesHelper;
import org.communiquons.android.comunic.client.data.conversations.ConversationRefreshRunnable; import org.communiquons.android.comunic.client.data.conversations.ConversationRefreshRunnable;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import static android.app.Activity.RESULT_OK;
/** /**
* Conversation fragment * Conversation fragment
* *
@ -38,6 +49,11 @@ import java.util.ArrayList;
public class ConversationFragment extends Fragment public class ConversationFragment extends Fragment
implements ConversationRefreshRunnable.onMessagesChangeListener { implements ConversationRefreshRunnable.onMessagesChangeListener {
/**
* Pick image request number
*/
public static final int PICK_PHOTO = 1;
/** /**
* Debug tag * Debug tag
*/ */
@ -98,6 +114,16 @@ public class ConversationFragment extends Fragment
*/ */
private ImageButton send_button; 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 * 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 @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@ -151,14 +190,31 @@ public class ConversationFragment extends Fragment
//Get new messages input fields //Get new messages input fields
new_message_content = view.findViewById(R.id.fragment_conversation_newmessage_content); 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); send_button = view.findViewById(R.id.fragment_conversation_newmessage_send);
//Make send button lives
send_button.setOnClickListener(new View.OnClickListener() { send_button.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
send_message(); 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 @Override
@ -248,13 +304,86 @@ public class ConversationFragment extends Fragment
convMessAdapter.notifyDataSetChanged(); 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 * This method is called when the user click on the "send_message" button
*/ */
private void send_message(){ private void send_message(){
//Check message length //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.makeText(getActivity(), R.string.conversation_message_err_too_short,
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
return; return;
@ -271,7 +400,9 @@ public class ConversationFragment extends Fragment
@Override @Override
protected Boolean doInBackground(Void... params) { 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 @Override
@ -294,9 +425,12 @@ public class ConversationFragment extends Fragment
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} }
//Remove previous message in case of succes //Remove previous message in case of success
if(success){ if(success){
new_message_content.setText(""); new_message_content.setText("");
//Remove image
remove_picked_image();
} }
//Make the "send" button available again //Make the "send" button available again

View File

@ -27,10 +27,18 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/fragment_conversation_new_message_placeholder"/> android:hint="@string/fragment_conversation_new_message_placeholder"/>
<ImageButton
android:id="@+id/fragment_conversation_newmessage_pickimage"
android:layout_width="@dimen/fragment_conversation_buttons_width"
android:layout_height="@dimen/fragment_conversation_buttons_height"
android:src="@android:drawable/ic_menu_gallery"
android:scaleType="fitCenter"
android:contentDescription="@string/conversation_message_add_image"/>
<ImageButton <ImageButton
android:id="@+id/fragment_conversation_newmessage_send" android:id="@+id/fragment_conversation_newmessage_send"
android:layout_width="wrap_content" android:layout_width="@dimen/fragment_conversation_buttons_width"
android:layout_height="wrap_content" android:layout_height="@dimen/fragment_conversation_buttons_height"
android:src="@android:drawable/ic_menu_send" android:src="@android:drawable/ic_menu_send"
android:contentDescription="@string/conversation_message_send"/> android:contentDescription="@string/conversation_message_send"/>

View File

@ -6,4 +6,8 @@
<!-- Dimensions for the conversation list --> <!-- Dimensions for the conversation list -->
<dimen name="fragment_conversations_list_icon_width">20dp</dimen> <dimen name="fragment_conversations_list_icon_width">20dp</dimen>
<dimen name="fragment_conversations_list_icon_height">20dp</dimen> <dimen name="fragment_conversations_list_icon_height">20dp</dimen>
<!-- Dimension for the conversation fragment -->
<dimen name="fragment_conversation_buttons_height">50dp</dimen>
<dimen name="fragment_conversation_buttons_width">50dp</dimen>
</resources> </resources>

View File

@ -32,7 +32,7 @@
<string name="action_friends_respond_request">Respond request</string> <string name="action_friends_respond_request">Respond request</string>
<string name="action_friends_deny_request">Deny</string> <string name="action_friends_deny_request">Deny</string>
<string name="popup_respond_friendship_request_title">Respond to the request</string> <string name="popup_respond_friendship_request_title">Respond to the request</string>
<string name="popup_respond_friendship_request_message">Do you want to accept or deny this friendship request ?</string> <string name="popup_respond_friendship_request_message">Do you want to accept or deny this friendship request ?</string>
<string name="fragment_conversationslist_err_get_list">An error occurred while retrieving conversations list !</string> <string name="fragment_conversationslist_err_get_list">An error occurred while retrieving conversations list !</string>
<string name="conversations_members_number">%d members</string> <string name="conversations_members_number">%d members</string>
<string name="date_now">now</string> <string name="date_now">now</string>
@ -54,7 +54,12 @@
<string name="fragment_conversation_err_load_message">Could not load messages!</string> <string name="fragment_conversation_err_load_message">Could not load messages!</string>
<string name="fragment_conversation_message_image">Conversation message image</string> <string name="fragment_conversation_message_image">Conversation message image</string>
<string name="conversation_message_send">Send</string> <string name="conversation_message_send">Send</string>
<string name="conversation_message_err_too_short">The length of the message is too short !</string> <string name="conversation_message_err_too_short">The message is too short !</string>
<string name="conversation_message_err_send">The message could not be sent! Please check your message and try again…</string> <string name="conversation_message_err_send">The message could not be sent! Please check your message and try again…</string>
<string name="fragment_conversation_new_message_placeholder">New message…</string> <string name="fragment_conversation_new_message_placeholder">New message…</string>
<string name="conversation_message_add_image">Add an image</string>
<string name="conversation_message_remove_image_popup_title">Remove image</string>
<string name="conversation_message_remove_image_popup_message">Do you want to remove selected image ?</string>
<string name="conversation_message_remove_image_popup_confirm">Yes</string>
<string name="conversation_message_remove_image_popup_cancel">No</string>
</resources> </resources>