想在聊天中發(fā) 小視頻?gif 動圖? 發(fā)紅包? 發(fā) 自定義表情? 沒有問題!在融云統(tǒng)統(tǒng)都可以實現(xiàn)! 以上不管是 小視頻 還是 gif 還是 紅包 或者是 自定義表情 歸根結(jié)底都是數(shù)據(jù)的傳輸 文件的傳輸. 后綴無非是 .png .gif .mp4 .amr 等 所以我們只要掌握了文件發(fā)送上面的所有需求都能根據(jù)文件消息衍生實現(xiàn)。 那我們就來趕緊切入正題看看文件消息的實現(xiàn)和文件消息的收發(fā)吧 Let’s Go!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | <code class = "hljs java" > package io.rong.message; import android.annotation.SuppressLint; import android.net.Uri; import android.os.Parcel; import android.text.TextUtils; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import io.rong.common.ParcelUtils; import io.rong.imlib.MessageTag; import io.rong.imlib.model.MessageContent; import io.rong.imlib.model.UserInfo; /** * Created by Bob on 15/12/24. */ @SuppressLint ( "ParcelCreator" ) @MessageTag (value = "RC:FileMsg" , flag = MessageTag.ISCOUNTED | MessageTag.ISPERSISTED, messageHandler = FileMessageHandler. class ) public class FileMessage extends MessageContent { private Uri mThumUri; private Uri mLocalUri; private Uri mRemoteUri; private boolean mUpLoadExp = false ; private String mBase64; boolean mIsFull; protected String extra; /** * 獲取消息附加信息 * * @return 附加信息 */ public String getExtra() { return extra; } /** * 設(shè)置消息附加信息 * * @param extra 附加信息 */ public void setExtra(String extra) { this .extra = extra; } public FileMessage( byte [] data) { String jsonStr = new String(data); try { JSONObject jsonObj = new JSONObject(jsonStr); if (jsonObj.has( "fileUri" )) { String uri = jsonObj.optString( "fileUri" ); if (!TextUtils.isEmpty(uri)) setRemoteUri(Uri.parse(uri)); if (getRemoteUri() != null && getRemoteUri().getScheme() != null && getRemoteUri().getScheme().equals( "file" )) { setLocalUri(getRemoteUri()); } } if (jsonObj.has( "content" )) { setBase64(jsonObj.optString( "content" )); } if (jsonObj.has( "extra" )) { setExtra(jsonObj.optString( "extra" )); } if (jsonObj.has( "exp" )) { setUpLoadExp( true ); } if (jsonObj.has( "isFull" )) { setIsFull(jsonObj.optBoolean( "isFull" )); } if (jsonObj.has( "user" )) { setUserInfo(parseJsonToUserInfo(jsonObj.getJSONObject( "user" ))); } } catch (JSONException e) { Log.e( "JSONException" , e.getMessage()); } } public FileMessage() { } private FileMessage(Uri thumbUri, Uri localUri) { mThumUri = thumbUri; mLocalUri = localUri; } private FileMessage(Uri thumbUri, Uri localUri, boolean original) { mThumUri = thumbUri; mLocalUri = localUri; mIsFull = original; } /** * 生成FileMessage對象。 * */ public static FileMessage obtain(Uri thumUri, Uri localUri) { return new FileMessage(thumUri, localUri); } /** * 生成FileMessage對象。 * */ public static FileMessage obtain(Uri thumUri, Uri localUri, boolean isFull) { return new FileMessage(thumUri, localUri, isFull); } /** * 生成FileMessage對象。 * * @return ImageMessage對象實例。 */ public static FileMessage obtain() { return new FileMessage(); } /** * 獲取縮略圖Uri。 * * @return 縮略圖Uri(收消息情況下此為內(nèi)部Uri,需要通過ResourceManager.getInstance().getFile(new Resource(Uri))方式才能獲取到真實地址)。 */ public Uri getThumUri() { return mThumUri; } /** * * @return true / false */ public boolean isFull() { return mIsFull; } /** * 設(shè)置發(fā)送原圖標(biāo)志位。 * */ public void setIsFull( boolean isFull) { this .mIsFull = isFull; } /** * 設(shè)置縮略圖Uri。 * * @param thumUri 縮略圖地址 */ public void setThumUri(Uri thumUri) { this .mThumUri = thumUri; } /** * 獲取本地圖片地址(file:///)。 * * @return 本地圖片地址(file:///)。 */ public Uri getLocalUri() { return mLocalUri; } /** * 設(shè)置本地圖片地址(file:///)。 * * @param localUri 本地圖片地址(file:///). */ public void setLocalUri(Uri localUri) { this .mLocalUri = localUri; } /** * 獲取網(wǎng)絡(luò)圖片地址(http://)。 * * @return 網(wǎng)絡(luò)圖片地址(http://)。 */ public Uri getRemoteUri() { return mRemoteUri; } /** * 設(shè)置網(wǎng)絡(luò)圖片地址(http://)。 * * @param remoteUri 網(wǎng)絡(luò)圖片地址(http://)。 */ public void setRemoteUri(Uri remoteUri) { this .mRemoteUri = remoteUri; } /** * 設(shè)置需要傳遞的Base64數(shù)據(jù) * * @param base64 base64數(shù)據(jù)。 */ public void setBase64(String base64) { mBase64 = base64; } /** * 獲取需要傳遞的Base64數(shù)據(jù)。 * * @return base64數(shù)據(jù)。 */ public String getBase64() { return mBase64; } /** * 是否上傳失敗。 * * @return 是否上傳失敗。 */ public boolean isUpLoadExp() { return mUpLoadExp; } /** * 設(shè)置是否上傳失敗。 * * @param upLoadExp 上傳是否失敗。 */ public void setUpLoadExp( boolean upLoadExp) { this .mUpLoadExp = upLoadExp; } @Override public byte [] encode() { JSONObject jsonObj = new JSONObject(); try { if (!TextUtils.isEmpty(mBase64)) { jsonObj.put( "content" , mBase64); } else { Log.d( "ImageMessage" , "base64 is null" ); } if (mRemoteUri != null ) { jsonObj.put( "fileUri" , mRemoteUri.toString()); } else if (getLocalUri() != null ) { jsonObj.put( "fileUri" , getLocalUri().toString()); } if (mUpLoadExp) { jsonObj.put( "exp" , true ); } jsonObj.put( "isFull" , mIsFull); if (!TextUtils.isEmpty(getExtra())) jsonObj.put( "extra" , getExtra()); if (getJSONUserInfo() != null ) jsonObj.putOpt( "user" , getJSONUserInfo()); } catch (JSONException e) { Log.e( "JSONException" , e.getMessage()); } mBase64 = null ; return jsonObj.toString().getBytes(); } /** * 描述了包含在 Parcelable 對象排列信息中的特殊對象的類型。 * * @return 一個標(biāo)志位,表明Parcelable對象特殊對象類型集合的排列。 */ @Override public int describeContents() { return 0 ; } /** * 構(gòu)造函數(shù)。 * * @param in 初始化傳入的 Parcel。 */ public FileMessage(Parcel in) { setExtra(ParcelUtils.readFromParcel(in)); mLocalUri = ParcelUtils.readFromParcel(in, Uri. class ); mRemoteUri = ParcelUtils.readFromParcel(in, Uri. class ); mThumUri = ParcelUtils.readFromParcel(in, Uri. class ); setUserInfo(ParcelUtils.readFromParcel(in, UserInfo. class )); mIsFull = ParcelUtils.readIntFromParcel(in) == 1 ; } /** * 將類的數(shù)據(jù)寫入外部提供的 Parcel 中。 * * @param dest 對象被寫入的 Parcel。 * @param flags 對象如何被寫入的附加標(biāo)志,可能是 0 或 PARCELABLE_WRITE_RETURN_VALUE。 */ @Override public void writeToParcel(Parcel dest, int flags) { ParcelUtils.writeToParcel(dest, getExtra()); ParcelUtils.writeToParcel(dest, mLocalUri); ParcelUtils.writeToParcel(dest, mRemoteUri); ParcelUtils.writeToParcel(dest, mThumUri); ParcelUtils.writeToParcel(dest, getUserInfo()); ParcelUtils.writeToParcel(dest, mIsFull ? 1 : 0 ); } /** * 讀取接口,目的是要從Parcel中構(gòu)造一個實現(xiàn)了Parcelable的類的實例處理。 */ public static final Creator<filemessage> CREATOR = new Creator<filemessage>() { @Override public FileMessage createFromParcel(Parcel source) { return new FileMessage(source); } @Override public FileMessage[] newArray( int size) { return new FileMessage[size]; } }; }</filemessage></filemessage></code> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | <code class = "language-java hljs " > package io.rong.app.message.provider; import android.content.Context; import android.text.Spannable; import android.text.SpannableString; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.sea_monster.resource.Resource; import io.rong.app.R; import io.rong.imkit.RongContext; import io.rong.imkit.model.ProviderTag; import io.rong.imkit.model.UIMessage; import io.rong.imkit.widget.AsyncImageView; import io.rong.imkit.widget.provider.IContainerItemProvider; import io.rong.imlib.model.Message; import io.rong.message.FileMessage; /** * Created by Bob on 15/12/24. */ @ProviderTag (messageContent = FileMessage. class , showPortrait = true , showProgress = true , centerInHorizontal = false ) public class FileMessageProvider extends IContainerItemProvider.MessageProvider<filemessage> { /** * 初始化View */ @Override public View newView(Context context, ViewGroup group) { View view = LayoutInflater.from(context).inflate(R.layout.de_item_file_message, group, false ); ViewHolder holder = new ViewHolder(); holder.message = (TextView) view.findViewById(R.id.rc_msg); holder.img = (AsyncImageView) view.findViewById(R.id.rc_img); view.setTag(holder); return view; } @Override public void bindView(View v, int position, FileMessage content, UIMessage message) { final ViewHolder holder = (ViewHolder) v.getTag(); if (message.getMessageDirection() == Message.MessageDirection.SEND) { v.setBackgroundResource(io.rong.imkit.R.drawable.rc_ic_bubble_no_right); } else { v.setBackgroundResource(io.rong.imkit.R.drawable.rc_ic_bubble_no_left); } holder.img.setResource(content.getThumUri() == null null : new Resource(content.getThumUri())); int progress = message.getProgress(); Message.SentStatus status = message.getSentStatus(); if (status.equals(Message.SentStatus.SENDING) && progress < 100 ) { if (progress == 0 ) holder.message.setText(RongContext.getInstance().getResources().getString(io.rong.imkit.R.string.rc_waiting)); else holder.message.setText(progress + "%" ); holder.message.setVisibility(View.VISIBLE); } else { holder.message.setVisibility(View.GONE); } } @Override public Spannable getContentSummary(FileMessage data) { return new SpannableString(RongContext.getInstance() .getResources() .getString(R.string.de_plugins_file)); } @Override public void onItemClick(View view, int position, FileMessage content, UIMessage message) { } @Override public void onItemLongClick(View view, int position, FileMessage content, UIMessage message) { } class ViewHolder { AsyncImageView img; TextView message; } }</filemessage></code> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | <code class = "hljs java" > package io.rong.app.message.provider; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.net.Uri; import android.util.Log; import android.view.View; import android.widget.Toast; import java.io.File; import io.rong.imkit.RongContext; import io.rong.imkit.RongIM; import io.rong.imkit.widget.provider.InputProvider; import io.rong.imlib.RongIMClient; import io.rong.imlib.model.Conversation; import io.rong.imlib.model.Message; import io.rong.message.FileMessage; /** * Created by AMing on 15/12/24. * Company RongCloud */ public class SendFileProvider extends InputProvider.ExtendProvider { private static final String TAG = SendFileProvider. class .getSimpleName(); private Context context; /** * 實例化適配器。 * * @param context 融云IM上下文。(通過 RongContext.getInstance() 可以獲?。?/code> */ public SendFileProvider(RongContext context) { super (context); this .context = context; } @Override public Drawable obtainPluginDrawable(Context context) { return context.getResources().getDrawable(io.rong.imkit.R.drawable.rc_ic_picture); } @Override public CharSequence obtainPluginTitle(Context context) { return "文件" ; } @Override public void onPluginClick(View view) { // Intent intent = new Intent(Intent.ACTION_GET_CONTENT); // intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE); // startActivityForResult(intent, 1); Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.setType( "file/*" ); startActivityForResult(i, 1 ); } @Override public void onActivityResult( int requestCode, int resultCode, Intent data) { super .onActivityResult(requestCode, resultCode, data); if (data != null ) { if (data.getData().getScheme().equals( "file" )) { String s = data.getData().getPath(); Uri uri = data.getData(); File file = new File(s); if (file.exists()) { Log.e( "file" , "f是文件且存在" ); Conversation conversation = getCurrentConversation(); sendFile(conversation.getConversationType(),conversation.getTargetId(),file,uri); } else { Toast.makeText(context, "文件不存在" ,Toast.LENGTH_SHORT); } } } } private void sendFile(Conversation.ConversationType conversationType, String id, File file,Uri uri) { if (RongIM.getInstance()!= null && RongIM.getInstance().getRongIMClient() != null ) { //TODO 文件消息 Log.e( "tag" , "" ); // Uri localUri = Uri.parse("file:///sdcard/bob/bob.zip"); FileMessage fileMessage = FileMessage.obtain(uri,uri); // ImageMessage fileMessage = ImageMessage.obtain(themUri,localUri); RongIM.getInstance().getRongIMClient().sendImageMessage(Conversation.ConversationType.PRIVATE, id, fileMessage, null , null , new RongIMClient.SendImageMessageCallback() { @Override public void onAttached(Message message) { Log.e(TAG, "-------------onAttached--------" ); } @Override public void onError(Message message, RongIMClient.ErrorCode code) { Log.e(TAG, "----------------onError-----" + code); } @Override public void onSuccess(Message message) { Log.e(TAG, "------------------onSuccess---" ); } @Override public void onProgress(Message message, int progress) { Log.e(TAG, "-----------------onProgress----" + progress); } }); } } } </code> |
1 2 3 4 5 6 7 8 9 10 11 | <code class = "language-java hljs " > if (message.getContent() instanceof FileMessage) { FileMessage fileMessage = (FileMessage) message.getContent(); if (message.getMessageDirection().equals(io.rong.imlib.model.Message.MessageDirection.RECEIVE)) { Intent intent = new Intent(context, FileActivity. class ); intent.putExtra( "photo" , fileMessage.getLocalUri() == null fileMessage.getRemoteUri() : fileMessage.getLocalUri()); if (fileMessage.getThumUri() != null ) intent.putExtra( "thumbnail" , fileMessage.getThumUri()); context.startActivity(intent); } }</code> |
實現(xiàn)效果 和 實現(xiàn)原理 還有大概代碼都已經(jīng)在上方分享,但是代碼建議大家不要全部 copy 有些東西還是需要自己理解后親自去實現(xiàn). 例如上傳和下載的方法實現(xiàn) 這個是和你 服務(wù)端 或者 云存儲交互的邏輯, 最后也希望這篇文章能夠幫助大家! End~