編輯:關於Android編程
想在聊天中發 小視頻?gif 動圖? 發紅包? 發 自定義表情? 沒有問題!在融雲統統都可以實現! 以上不管是 小視頻 還是 gif 還是 紅包 或者是 自定義表情 歸根結底都是數據的傳輸 文件的傳輸. 後綴無非是 .png .gif .mp4 .amr 等 所以我們只要掌握了文件發送上面的所有需求都能根據文件消息衍生實現。 那我們就來趕緊切入正題看看文件消息的實現和文件消息的收發吧 Let’s Go!
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(收消息情況下此為內部Uri,需要通過ResourceManager.getInstance().getFile(new Resource(Uri))方式才能獲取到真實地址)。
*/
public Uri getThumUri() {
return mThumUri;
}
/**
*
* @return true / false
*/
public boolean isFull() {
return mIsFull;
}
/**
* 設置發送原圖標志位。
*
*/
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;
}
/**
* 獲取網絡圖片地址(http://)。
*
* @return 網絡圖片地址(http://)。
*/
public Uri getRemoteUri() {
return mRemoteUri;
}
/**
* 設置網絡圖片地址(http://)。
*
* @param remoteUri 網絡圖片地址(http://)。
*/
public void setRemoteUri(Uri remoteUri) {
this.mRemoteUri = remoteUri;
}
/**
* 設置需要傳遞的Base64數據
*
* @param base64 base64數據。
*/
public void setBase64(String base64) {
mBase64 = base64;
}
/**
* 獲取需要傳遞的Base64數據。
*
* @return base64數據。
*/
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;
}
/**
* 構造函數。
*
* @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;
}
/**
* 將類的數據寫入外部提供的 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中構造一個實現了Parcelable的類的實例處理。
*/
public static final Creator CREATOR = new Creator() {
@Override
public FileMessage createFromParcel(Parcel source) {
return new FileMessage(source);
}
@Override
public FileMessage[] newArray(int size) {
return new FileMessage[size];
}
};
}
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 {
/**
* 初始化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;
}
}
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);
}
});
}
}
}
RongIM.registerMessageType(FileMessage.class);
RongIM.registerMessageTemplate(newFileMessageProvider());
點擊消息的監聽內判斷文件消息
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);
}
}
實現效果 和 實現原理 還有大概代碼都已經在上方分享,但是代碼建議大家不要全部 copy 有些東西還是需要自己理解後親自去實現. 例如上傳和下載的方法實現 這個是和你 服務端 或者 雲存儲交互的邏輯, 最後也希望這篇文章能夠幫助大家! End~
某些參數總是同時出現,可能好幾個方法都使用這樣一組參數,為了避免參數列表過長,同時也為了避免重復代碼, 我們可以將這些參數提煉為參數對象,原來傳入參數的地方使用這個參數對
在做項目開發時,有個這樣的需求:就中間的那個支付明細,要求點擊時能收縮,這個功能非常簡單,從界面來看,用LinearLayout或TableLayout來做,沒啥難度,但
上一篇文章中我們講解了android app中的升級更新操作,app的升級更新操作算是App的標配了,升級操作就是獲取App的升級信息,更新操作是下載,安裝,更新app,
本篇博客給大家分享一個效果比較好的側滑菜單的Demo,實現點擊左邊菜單切換Fragment。效果如下: 主Activity代碼:package com.infz