From b5d499799a01448a1ecd1de4a8626f6704ce1bf4 Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Mon, 10 Aug 2015 16:45:43 +0200 Subject: [PATCH] Update download/upload images outside the chatfragment --- src/org/linphone/ChatFragment.java | 99 +++++++++------------- src/org/linphone/LinphoneManager.java | 117 +++++++++++++++++++++++++- src/org/linphone/ui/BubbleChat.java | 47 +++++++---- 3 files changed, 181 insertions(+), 82 deletions(-) diff --git a/src/org/linphone/ChatFragment.java b/src/org/linphone/ChatFragment.java index d5049aa98..0189ba6c5 100644 --- a/src/org/linphone/ChatFragment.java +++ b/src/org/linphone/ChatFragment.java @@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.IOException; + import android.graphics.Matrix; import java.util.ArrayList; import java.util.List; @@ -31,7 +31,6 @@ import org.linphone.compatibility.Compatibility; import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneBuffer; import org.linphone.core.LinphoneChatMessage; -import org.linphone.core.LinphoneChatMessage.LinphoneChatMessageListener; import org.linphone.core.LinphoneChatRoom; import org.linphone.core.LinphoneContent; import org.linphone.core.LinphoneCore; @@ -85,7 +84,7 @@ import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; -public class ChatFragment extends Fragment implements OnClickListener, LinphoneChatMessageListener { +public class ChatFragment extends Fragment implements OnClickListener, LinphoneChatMessage.LinphoneChatMessageListener { private static ChatFragment instance; private static final int ADD_PHOTO = 1337; @@ -113,9 +112,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC private ChatMessageAdapter adapter; private LinphoneCoreListenerBase mListener; - private ByteArrayOutputStream mDownloadedImageStream; private ByteArrayInputStream mUploadingImageStream; - private int mDownloadedImageStreamSize; private LinphoneChatMessage currentMessageInFileTransferUploadState; public static boolean isInstanciated() { @@ -127,7 +124,8 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC super.onCreate(savedInstanceState); instance = this; View view = inflater.inflate(R.layout.chat, container, false); - + + LinphoneManager.addListener(this); // Retain the fragment across configuration changes setRetainInstance(true); @@ -194,6 +192,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC progressBar.setProgress(0); currentMessageInFileTransferUploadState.cancelFileTransfer(); currentMessageInFileTransferUploadState = null; + LinphoneManager.getInstance().setUploadPendingFileMessage(null); } } }); @@ -283,7 +282,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC topBar.setVisibility(View.GONE); } contactPicture.setVisibility(View.GONE); - //scrollToEnd(); } public void hideKeyboardVisibleMode() { @@ -292,7 +290,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC if (isOrientationLandscape && topBar != null) { topBar.setVisibility(View.VISIBLE); } - //scrollToEnd(); } class ChatMessageAdapter extends BaseAdapter { @@ -327,7 +324,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC public View getView(int position, View convertView, ViewGroup parent) { LinphoneChatMessage message = history[position]; - BubbleChat bubble = new BubbleChat(context, message, ChatFragment.this); + BubbleChat bubble = new BubbleChat(context, message); View v = bubble.getView(); registerForContextMenu(v); @@ -453,6 +450,8 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC lc.removeListener(mListener); } + LinphoneManager.removeListener(this); + onSaveInstanceState(getArguments()); //Hide keybord @@ -479,6 +478,29 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC LinphoneActivity.instance().updateChatFragment(this); } + LinphoneManager.addListener(this); + + final LinphoneChatMessage msg = LinphoneManager.getInstance().getMessageUploadPending(); + if(msg != null){ + uploadLayout.setVisibility(View.VISIBLE); + textLayout.setVisibility(View.GONE); + if(msg.getFileTransferInformation() != null){ + progressBar.setProgress(msg.getFileTransferInformation().getRealSize()); + } + + cancelUpload.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + uploadLayout.setVisibility(View.GONE); + textLayout.setVisibility(View.VISIBLE); + progressBar.setProgress(0); + msg.cancelFileTransfer(); + LinphoneManager.getInstance().setUploadPendingFileMessage(null); + + } + }); + } + String draft = getArguments().getString("messageDraft"); message.setText(draft); @@ -504,13 +526,14 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC if (chatRoom != null && messageToSend != null && messageToSend.length() > 0 && isNetworkReachable) { LinphoneChatMessage message = chatRoom.createLinphoneChatMessage(messageToSend); - message.setListener(this); chatRoom.sendChatMessage(message); if (LinphoneActivity.isInstanciated()) { LinphoneActivity.instance().onMessageSent(sipUri, messageToSend); } + message.setListener(LinphoneManager.getInstance()); + invalidate(); Log.i("Sent message current status: " + message.getStatus()); } else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) { @@ -600,9 +623,12 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC content.setName(fileName); LinphoneChatMessage message = chatRoom.createFileTransferMessage(content); - message.setListener(ChatFragment.this); + message.setListener(LinphoneManager.getInstance()); message.setAppData(path); - + + LinphoneManager.getInstance().setUploadPendingFileMessage(message); + LinphoneManager.getInstance().setUploadingImageStream(mUploadingImageStream); + chatRoom.sendChatMessage(message); currentMessageInFileTransferUploadState = message; } @@ -703,32 +729,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC @Override public void onLinphoneChatMessageStateChanged(LinphoneChatMessage msg, State state) { - if (LinphoneActivity.isInstanciated() && state != LinphoneChatMessage.State.InProgress) { - if (msg != null) { - LinphoneActivity.instance().onMessageStateChanged(sipUri, msg.getText(), state.toInt()); - } - invalidate(); - } - - if (state == State.FileTransferDone) { - if (mDownloadedImageStream != null) { - byte[] bytes = mDownloadedImageStream.toByteArray(); - Bitmap bm = BitmapFactory.decodeByteArray(bytes, 0, mDownloadedImageStreamSize); - - String path = msg.getExternalBodyUrl(); - String fileName = path.substring(path.lastIndexOf("/") + 1); - String url = MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), bm, fileName, null); - if (url != null) { - msg.setAppData(url); - } - - mDownloadedImageStream = null; - mDownloadedImageStreamSize = 0; - } else if (mUploadingImageStream != null) { - mUploadingImageStream = null; - } - } - if (state == State.FileTransferDone || state == State.FileTransferError) { uploadLayout.setVisibility(View.GONE); textLayout.setVisibility(View.VISIBLE); @@ -740,33 +740,10 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC @Override public void onLinphoneChatMessageFileTransferReceived(LinphoneChatMessage msg, LinphoneContent content, LinphoneBuffer buffer) { - if (mDownloadedImageStream == null) { - mDownloadedImageStream = new ByteArrayOutputStream(); - mDownloadedImageStreamSize = 0; - } - - if (buffer != null && buffer.getSize() > 0) { - try { - mDownloadedImageStream.write(buffer.getContent()); - mDownloadedImageStreamSize += buffer.getSize(); - } catch (IOException e) { - Log.e(e); - } - } } @Override public void onLinphoneChatMessageFileTransferSent(LinphoneChatMessage msg, LinphoneContent content, int offset, int size, LinphoneBuffer bufferToFill) { - if (mUploadingImageStream != null && size > 0) { - byte[] data = new byte[size]; - int read = mUploadingImageStream.read(data, 0, size); - if (read > 0) { - bufferToFill.setContent(data); - bufferToFill.setSize(read); - } else { - Log.e("Error, upload task asking for more bytes(" + size + ") than available (" + mUploadingImageStream.available() + ")"); - } - } } @Override diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 028b13fcc..bfba1f193 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -22,13 +22,17 @@ import static android.media.AudioManager.MODE_RINGTONE; import static android.media.AudioManager.STREAM_RING; import static android.media.AudioManager.STREAM_VOICE_CALL; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.Timer; import java.util.TimerTask; @@ -36,6 +40,7 @@ import java.util.TimerTask; import org.linphone.compatibility.Compatibility; import org.linphone.core.CallDirection; import org.linphone.core.LinphoneAddress; +import org.linphone.core.LinphoneBuffer; import org.linphone.core.LinphoneCall; import org.linphone.core.LinphoneCall.State; import org.linphone.core.LinphoneCallParams; @@ -88,10 +93,12 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; +import android.os.Environment; import android.os.Handler; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.Vibrator; +import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.telephony.TelephonyManager; @@ -116,7 +123,7 @@ import android.widget.Toast; * @author Guillaume Beraudo * */ -public class LinphoneManager implements LinphoneCoreListener { +public class LinphoneManager implements LinphoneCoreListener, LinphoneChatMessage.LinphoneChatMessageListener { private static LinphoneManager instance; private Context mServiceContext; @@ -133,9 +140,21 @@ public class LinphoneManager implements LinphoneCoreListener { private ConnectivityManager mConnectivityManager; private Handler mHandler = new Handler(); private WakeLock mIncallWakeLock; + private static List mPendingChatFileMessage; + private static LinphoneChatMessage mUploadPendingFileMessage; public String wizardLoginViewDomain = null; + private static List simpleListeners = new ArrayList(); + public static void addListener(LinphoneChatMessage.LinphoneChatMessageListener listener) { + if (!simpleListeners.contains(listener)) { + simpleListeners.add(listener); + } + } + public static void removeListener(LinphoneChatMessage.LinphoneChatMessageListener listener) { + simpleListeners.remove(listener); + } + protected LinphoneManager(final Context c) { sExited = false; mServiceContext = c; @@ -156,6 +175,7 @@ public class LinphoneManager implements LinphoneCoreListener { mPowerManager = (PowerManager) c.getSystemService(Context.POWER_SERVICE); mConnectivityManager = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); mR = c.getResources(); + mPendingChatFileMessage = new ArrayList(); } private static final int LINPHONE_VOLUME_STREAM = STREAM_VOICE_CALL; @@ -170,6 +190,7 @@ public class LinphoneManager implements LinphoneCoreListener { private final String mPauseSoundFile; private final String mChatDatabaseFile; private final String mErrorToneFile; + private ByteArrayInputStream mUploadingImageStream; private Timer mTimer; @@ -213,6 +234,98 @@ public class LinphoneManager implements LinphoneCoreListener { return instance; } + public void addDownloadMessagePending(LinphoneChatMessage message){ + synchronized (mPendingChatFileMessage) { + mPendingChatFileMessage.add(message); + } + } + + public boolean isMessagePending(LinphoneChatMessage message){ + boolean messagePending = false; + synchronized (mPendingChatFileMessage) { + for (LinphoneChatMessage chat : mPendingChatFileMessage) { + if (chat.getStorageId() == message.getStorageId()) { + messagePending = true; + break; + } + } + } + return messagePending; + } + + public void removePendingMessage(LinphoneChatMessage message){ + synchronized (mPendingChatFileMessage) { + for (LinphoneChatMessage chat : mPendingChatFileMessage) { + if (chat.getStorageId() == message.getStorageId()) { + mPendingChatFileMessage.remove(chat); + } + break; + } + } + } + + public void setUploadPendingFileMessage(LinphoneChatMessage message){ + mUploadPendingFileMessage = message; + } + + public LinphoneChatMessage getMessageUploadPending(){ + return mUploadPendingFileMessage; + } + + public void setUploadingImageStream(ByteArrayInputStream array){ + this.mUploadingImageStream = array; + } + + + @Override + public void onLinphoneChatMessageStateChanged(LinphoneChatMessage msg, LinphoneChatMessage.State state) { + if (state == LinphoneChatMessage.State.FileTransferDone) { + if(msg.isOutgoing() && mUploadingImageStream != null){ + mUploadPendingFileMessage = null; + mUploadingImageStream = null; + } else { + File file = new File(Environment.getExternalStorageDirectory(), msg.getFileTransferInformation().getName()); + try { + String url = MediaStore.Images.Media.insertImage(getContext().getContentResolver(), file.getPath(), msg.getFileTransferInformation().getName(), null); + msg.setAppData(url); + file.delete(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + removePendingMessage(msg); + } + } + + for (LinphoneChatMessage.LinphoneChatMessageListener l: simpleListeners) { + l.onLinphoneChatMessageStateChanged(msg, state); + } + } + + @Override + public void onLinphoneChatMessageFileTransferReceived(LinphoneChatMessage msg, LinphoneContent content, LinphoneBuffer buffer) { + } + + @Override + public void onLinphoneChatMessageFileTransferSent(LinphoneChatMessage msg, LinphoneContent content, int offset, int size, LinphoneBuffer bufferToFill) { + if (mUploadingImageStream != null && size > 0) { + byte[] data = new byte[size]; + int read = mUploadingImageStream.read(data, 0, size); + if (read > 0) { + bufferToFill.setContent(data); + bufferToFill.setSize(read); + } else { + Log.e("Error, upload task asking for more bytes(" + size + ") than available (" + mUploadingImageStream.available() + ")"); + } + } + } + + @Override + public void onLinphoneChatMessageFileTransferProgressChanged(LinphoneChatMessage msg, LinphoneContent content, int offset, int total) { + for (LinphoneChatMessage.LinphoneChatMessageListener l: simpleListeners) { + l.onLinphoneChatMessageFileTransferProgressChanged(msg, content, offset, total); + } + } + private boolean isPresenceModelActivitySet() { LinphoneCore lc = getLcIfManagerNotDestroyedOrNull(); if (isInstanciated() && lc != null) { @@ -331,7 +444,6 @@ public class LinphoneManager implements LinphoneCoreListener { LinphoneManager.getLc().setVideoDevice(camId); } - public static interface AddressType { void setText(CharSequence s); CharSequence getText(); @@ -1097,7 +1209,6 @@ public class LinphoneManager implements LinphoneCoreListener { return distanceInCm < threshold; } - private static boolean sLastProximitySensorValueNearby; private static Set sProximityDependentActivities = new HashSet(); private static SensorEventListener sProximitySensorListener = new SensorEventListener() { diff --git a/src/org/linphone/ui/BubbleChat.java b/src/org/linphone/ui/BubbleChat.java index 7ff74ef65..8090d5b68 100644 --- a/src/org/linphone/ui/BubbleChat.java +++ b/src/org/linphone/ui/BubbleChat.java @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.ref.WeakReference; @@ -25,6 +26,7 @@ import java.util.Calendar; import java.util.HashMap; import java.util.Map.Entry; +import org.linphone.LinphoneManager; import org.linphone.R; import org.linphone.core.LinphoneChatMessage; import org.linphone.core.LinphoneChatMessage.State; @@ -42,6 +44,7 @@ import android.graphics.drawable.Drawable; import android.media.ThumbnailUtils; import android.net.Uri; import android.os.AsyncTask; +import android.os.Environment; import android.provider.MediaStore; import android.text.Html; import android.text.Spannable; @@ -100,17 +103,15 @@ public class BubbleChat { private RelativeLayout view; private ImageView statusView; private LinphoneChatMessage nativeMessage; - private LinphoneChatMessage.LinphoneChatMessageListener fileTransferListener; private Context mContext; private static final int SIZE_MAX = 512; @SuppressLint("InflateParams") - public BubbleChat(final Context context, LinphoneChatMessage message, LinphoneChatMessage.LinphoneChatMessageListener listener) { + public BubbleChat(final Context context, LinphoneChatMessage message) { if (message == null) { return; } nativeMessage = message; - fileTransferListener = listener; mContext = context; view = new RelativeLayout(context); @@ -153,22 +154,32 @@ public class BubbleChat { String appData = message.getAppData(); if (appData == null) { - download.setVisibility(View.VISIBLE); - download.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - v.setEnabled(false); - ProgressBar spinner = (ProgressBar) view.findViewById(R.id.spinner); - spinner.setVisibility(View.VISIBLE); - v.setVisibility(View.GONE); + if(LinphoneManager.getInstance().isMessagePending(nativeMessage)){ + download.setEnabled(false); + ProgressBar spinner = (ProgressBar) layout.findViewById(R.id.spinner); + spinner.setVisibility(View.VISIBLE); + download.setVisibility(View.GONE); + } else { + download.setVisibility(View.VISIBLE); + download.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + v.setEnabled(false); + ProgressBar spinner = (ProgressBar) view.findViewById(R.id.spinner); + spinner.setVisibility(View.VISIBLE); + v.setVisibility(View.GONE); - nativeMessage.setListener(fileTransferListener); - nativeMessage.downloadFile(); - } - }); + File file = new File(Environment.getExternalStorageDirectory(), nativeMessage.getFileTransferInformation().getName()); + nativeMessage.setListener(LinphoneManager.getInstance()); + nativeMessage.setFileTransferFilepath(file.getPath()); + nativeMessage.downloadFile(); + LinphoneManager.getInstance().addDownloadMessagePending(nativeMessage); + } + }); + } } else { - imageView.setVisibility(View.VISIBLE); - loadBitmap(appData, imageView); + imageView.setVisibility(View.VISIBLE); + loadBitmap(appData, imageView); } } else { TextView msgView = (TextView) layout.findViewById(R.id.message); @@ -325,7 +336,7 @@ public class BubbleChat { task.execute(path); } } - + private class BitmapWorkerTask extends AsyncTask { private final WeakReference imageViewReference; public String path;