日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

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

 WindySky 2016-04-25

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


先來看看效果:

pic


接下來這邊會把是實現(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 此類是 文件消息模板 負責消息在會話界面 UI 的展示 SendFileProvider 此類是發(fā)送文件消息的入口
以上是三個最主要的邏輯代碼類, 先大概說下用途. 還有一些細節(jié)代碼.后續(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;
    }
    /**
     * 設置消息附加信息
     *
     * @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;
    }
    /**
     * 設置發(fā)送原圖標志位。
     *
         */
    public void setIsFull(boolean isFull) {
        this.mIsFull = isFull;
    }
    /**
     * 設置縮略圖Uri。
     *
     * @param thumUri 縮略圖地址
     */
    public void setThumUri(Uri thumUri) {
        this.mThumUri = thumUri;
    }
    /**
     * 獲取本地圖片地址(file:///)。
     *
     * @return 本地圖片地址(file:///)。
     */
    public Uri getLocalUri() {
        return mLocalUri;
    }
    /**
     * 設置本地圖片地址(file:///)。
     *
     * @param localUri 本地圖片地址(file:///).
     */
    public void setLocalUri(Uri localUri) {
        this.mLocalUri = localUri;
    }
    /**
     * 獲取網(wǎng)絡圖片地址(http://)。
     *
     * @return 網(wǎng)絡圖片地址(http://)。
     */
    public Uri getRemoteUri() {
        return mRemoteUri;
    }
    /**
     * 設置網(wǎng)絡圖片地址(http://)。
     *
     * @param remoteUri 網(wǎng)絡圖片地址(http://)。
     */
    public void setRemoteUri(Uri remoteUri) {
        this.mRemoteUri = remoteUri;
    }
    /**
     * 設置需要傳遞的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;
    }
    /**
     * 設置是否上傳失敗。
     *
     * @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 一個標志位,表明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 對象如何被寫入的附加標志,可能是 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 負責控制 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() 可以獲取)
     */
    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:

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

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) 這個是和你 服務端 或者 云存儲交互的邏輯, 最后也希望這篇文章能夠幫助大家! End~

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多