免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
融云如何實現(xiàn)文件發(fā)送(高級進階)

想在聊天中發(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!


先來看看效果:


接下來這邊會把是實現(xiàn)原理 和 實現(xiàn)代碼給大家分享

實現(xiàn)原理:

消息需要自定義消息類型 使用融云的消息收發(fā)通道 UI展示 需要使用到 融云消息模板 可以自定義UI展示樣式 利用 后臺存儲 或者 云存儲(此處示例七牛) 上傳的文件 再給予這個文件一個 可下載的公網(wǎng)路徑(例:http://xxx & https://xxx) 發(fā)消息其實就是把本地文件上傳(你需要有個 upLoadFile 類似的方法), 以及上傳進度提示 收到消息 用戶點擊消息 此時就是獲取消息體中包含的 retomeUrl 然后去下載 (你需要有個 downLoadFile 類似的方法) 下載下來以后對文件然后根據(jù)自身 App 邏輯需求自行處理

實現(xiàn)代碼:

FileMessage 此類是 文件消息 實體類 繼承自融云 MessageContent FileMessageProvider 此類是 文件消息模板 負(fù)責(zé)消息在會話界面 UI 的展示 SendFileProvider 此類是發(fā)送文件消息的入口
以上是三個最主要的邏輯代碼類, 先大概說下用途. 還有一些細(xì)節(jié)代碼.后續(xù)會跟上代碼再做詳細(xì)分享

FileMessage

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>

自定義消息類里面主要做了消息的持久序列化 和 消息包含的內(nèi)容和成員, 例如上傳文件我肯定需要知道文件的本地路徑,例如發(fā)送紅包消息我們需要知道紅包的金額


FileMessageProvider

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>

FileMessageProvider 負(fù)責(zé)控制 UI 展示樣式的類 此處就用一個文件樣式做展示,如果是發(fā)紅包可能資源圖片就會換成紅包樣式的圖片,還有上傳進度的 UI 展示也在本類


SendFileProvider

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 themUri = Uri.parse("file:///sdcard/bob/bob.zip" );
//            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>

本類是發(fā)送文件的入口類,需要提醒的是. 此處代碼中是直接開啟的 Android 系統(tǒng)的文件管理器,在某些基于 Android 自定義的機型里面打開沒有文件 建議用 Android原生機型 三星小米也都沒有問題. 這里自己可以自定義掃描過濾寫自定義的文件管理器


Ohter Code:

三個核心類分享完了 我們再來說說其他相關(guān)代碼

application 類中注冊消息類型 和 注冊消息模板. 這步簡單但是很容易忘記
1
2
3
<code class="language-java hljs ">RongIM.registerMessageType(FileMessage.class);
RongIM.registerMessageTemplate(newFileMessageProvider());</code>
點擊消息的監(jiān)聽內(nèi)判斷文件消息
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>

此處判斷是文件消息然后跳轉(zhuǎn)至下載頁面下載


總結(jié):

實現(xiàn)效果 和 實現(xiàn)原理 還有大概代碼都已經(jīng)在上方分享,但是代碼建議大家不要全部 copy 有些東西還是需要自己理解后親自去實現(xiàn). 例如上傳和下載的方法實現(xiàn) 這個是和你 服務(wù)端 或者 云存儲交互的邏輯, 最后也希望這篇文章能夠幫助大家! End~

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android 讀取doc文件
系出名門Android(9) - 數(shù)據(jù)庫支持(SQLite), - - JavaEye技術(shù)...
使用ContentProvider提供數(shù)據(jù)源(一)ListView中顯示圖片
教你如何開關(guān)Android的APN網(wǎng)絡(luò) - Android - mobile - JavaEye論壇
android 瀏覽器 打開本地html文件的方法
判斷Android系統(tǒng)net和wap接入點的開發(fā)實例
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服