融云知识点
Posted jielundewode
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了融云知识点相关的知识,希望对你有一定的参考价值。
1.为选择图片发送界面加上返回
融云自带的选择发送图片界面没有返回按钮,为了app界面统一完整需要加上:
首先,连接融云服务器之前:
//扩展功能自定义
InputProvider.ExtendProvider[] provider = {
new MyImageInputProvider(RongContext.getInstance()),//图片
new CameraInputProvider(RongContext.getInstance())//相机
};
RongIM.getInstance().resetInputExtensionProvider(Conversation.ConversationType.PRIVATE, provider);
RongIM.getInstance().resetInputExtensionProvider(Conversation.ConversationType.GROUP, provider);
自定义一个ImageProvider,实现打开自定义Activity界面的功能:
public class MyImageInputProvider extends ImageInputProvider {
public MyImageInputProvider(RongContext context) {
super(context);
}
public void onPluginClick(View view) {
Intent intent = new Intent();
intent.setClass(view.getContext(), SelPicActivity_.class);
this.startActivityForResult(intent, 23);
}
}
自定义一个SelPicActivity,主要代码还是来自于sdk的io.rong.imkit.tools.SelectPictureActivity,主要是添加一个返回按钮
2.聊天图片可滑动切换
融云目前没有类似qq那样的可滑动切换查看聊天发送的图片,首先需要监听发送消息及接收的消息,如果是图片就保存到数据库中。
/**
* 设置接收消息的监听器。
* 需要注意的是其应该放在连接融云服务器之前。
*/
RongIM.setOnReceiveMessageListener(new MyReceiveMsgListener(app));
/**
* 设置发送消息的监听器。
* 需要注意的是其应该放在连接融云服务器之后。
*/
RongIM.getInstance().setSendMessageListener(new MySendMessageListener(app));
接下来看接口实现:
/**
* Desc:融云接受消息监听(connect方法之前调用)
*/
public class MyReceiveMsgListener implements RongIMClient.OnReceiveMessageListener {
ParentsApp app;
public MyReceiveMsgListener(ParentsApp app) {
this.app = app;
}
@Override
public boolean onReceived(Message message, int i) {
if (message.getContent() instanceof ImageMessage) {
ImageMessage m = (ImageMessage) message.getContent();
ImPhoto photo = new ImPhoto(message.getMessageId(), message.getTargetId(), m.getRemoteUri().toString());
ImPhoto.save(app, photo);
}
return false;
}
}
/**
* Desc:融云发送消息监听(connect方法之后)
*/
public class MySendMessageListener implements RongIM.OnSendMessageListener {
private ParentsApp app;
public MySendMessageListener(ParentsApp app) {
this.app = app;
}
public Message onSend(Message message) {
if (message.getContent() instanceof ImageMessage) {
ImageMessage m = (ImageMessage) message.getContent();
if (m.getLocalUri() != null) {
ImPhoto photo = new ImPhoto(message.getMessageId(), message.getTargetId(), m.getLocalUri().toString());
ImPhoto.save(app, photo);
} else if (m.getRemoteUri() != null) {
ImPhoto photo = new ImPhoto(message.getMessageId(), message.getTargetId(), m.getRemoteUri().toString());
ImPhoto.save(app, photo);
}
//
// LogUtils.e(m.getLocalUri().toString());
// LogUtils.e(message.getMessageId() + "???????");
}
return message;
}
@Override
public boolean onSent(Message message, RongIM.SentMessageErrorCode sentMessageErrorCode) {
if (message.getContent() instanceof ImageMessage) {
ImageMessage m = (ImageMessage) message.getContent();
ImPhoto photo = new ImPhoto(message.getMessageId(), message.getTargetId(), m.getRemoteUri().toString());
ImPhoto.save(app, photo);
LogUtils.e(m.getRemoteUri().toString());
LogUtils.e(message.getMessageId() + "-*---------");
}
return true;
}
}
来看一个ImPhoto的实现(用了xutils的DbUtils保存到数据库,很简单,不再赘述),也很简单
/**
* Desc:聊天信息中的图片
*/
@Table(name = "chat_photo")
public class ImPhoto implements Parcelable {
public static final Parcelable.Creator<ImPhoto> CREATOR = new Parcelable.Creator<ImPhoto>() {
@Override
public ImPhoto createFromParcel(Parcel source) {
return new ImPhoto(source);
}
@Override
public ImPhoto[] newArray(int size) {
return new ImPhoto[size];
}
};
@Column(name = "id", isId = true, autoGen = false)
public int id;
@Column(name = "imid")
public String imid;//谁的聊天记录中的图片
@Column(name = "url")
public String url;
public ImPhoto() {
}
public ImPhoto(int id, String imid, String url) {
this.id = id;
this.imid = imid;
this.url = url;
}
protected ImPhoto(Parcel in) {
this.id = in.readInt();
this.imid = in.readString();
this.url = in.readString();
}
public static void save(Context context, ImPhoto photo) {
DbManager dbManager = DbUtils.getDb(context);
try {
dbManager.saveOrUpdate(photo);
List<ImPhoto> imPhotos = dbManager.findAll(ImPhoto.class);
int count = imPhotos.size();
if (count > 100) {
for (int i = 0; i < count - 30; ++i) {
dbManager.deleteById(ImPhoto.class, imPhotos.get(i).getId());
}
}
} catch (DbException e) {
e.printStackTrace();
}
}
public static Map<Integer, List<ImPhoto>> getPhotos(Context context, int id) {
DbManager dbManager = DbUtils.getDb(context);
try {
Map<Integer, List<ImPhoto>> res = new HashMap<>();
List<ImPhoto> imPhotos = dbManager.findAll(ImPhoto.class);
if (imPhotos == null || imPhotos.size() == 0) {
return null;
}
int count = imPhotos.size();
for (int i = 0; i < count; ++i) {
if (imPhotos.get(i).getId() == id) {
res.put(i, imPhotos);
break;
}
}
return res;
} catch (DbException e) {
return null;
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getImid() {
return imid;
}
public void setImid(String imid) {
this.imid = imid;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.imid);
dest.writeString(this.url);
}
}
接下来最关键的,定义聊天内容点击事件
public class MyConversationBehaviorListener implements RongIM.ConversationBehaviorListener {
/**
* 当点击用户头像后执行。
*
* @param context 上下文。
* @param conversationType 会话类型。
* @param userInfo 被点击的用户的信息。
* @return 如果用户自己处理了点击后的逻辑,则返回 true,否则返回 false,false 走融云默认处理方式。
*/
@Override
public boolean onUserPortraitClick(Context context, Conversation.ConversationType conversationType, UserInfo userInfo) {
if (conversationType != Conversation.ConversationType.GROUP)
return false;
String imid = userInfo.getUserId();
// if (Integer.parseInt(imid.substring(2)) != ((TeacherApp) context).getTeacher().id) {
RongIM.getInstance().startPrivateChat(context, imid, userInfo.getName() + "\n" + "聊天");
// }
return true;
}
/**
* 当长按用户头像后执行。
*
* @param context 上下文。
* @param conversationType 会话类型。
* @param userInfo 被点击的用户的信息。
* @return 如果用户自己处理了点击后的逻辑,则返回 true,否则返回 false,false 走融云默认处理方式。
*/
@Override
public boolean onUserPortraitLongClick(Context context, Conversation.ConversationType conversationType, UserInfo userInfo) {
// AddFriendsInfoActivity_.intent(context).extra("imId", userInfo.getUserId()).extra("showAddBtn", false).start();
return false;
}
/**
* 当点击消息时执行。
*
* @param context 上下文。
* @param view 触发点击的 View。
* @param message 被点击的消息的实体信息。
* @return 如果用户自己处理了点击后的逻辑,则返回 true, 否则返回 false, false 走融云默认处理方式。
*/
@Override
public boolean onMessageClick(Context context, View view, Message message) {
if (message.getContent() instanceof ImageMessage) {
Map<Integer, List<ImPhoto>> result = ImPhoto.getPhotos(context, message.getMessageId());
if (result == null) {
startSingleBrowser(context, message);
return true;
}
Set<Map.Entry<Integer, List<ImPhoto>>> entry = result.entrySet();
if (entry == null || entry.size() == 0) {
startSingleBrowser(context, message);
return true;
}
Map.Entry<Integer, List<ImPhoto>> dd = entry.iterator().next();
if (dd.getKey() >= dd.getValue().size()) {
startSingleBrowser(context, message);
return true;
}
PhotoActivity_.intent(context).flags(Intent.FLAG_ACTIVITY_NEW_TASK)
.extra("pos", dd.getKey())
.extra("photos", (ArrayList<ImPhoto>) dd.getValue())
.start();
}
return false;
}
void startSingleBrowser(Context context, Message message) {
ImageMessage imageMessage = (ImageMessage) message.getContent();
Intent intent = new Intent(context, PhotoActivity2_.class);
intent.putExtra("photo", imageMessage.getLocalUri() == null ? imageMessage.getRemoteUri() : imageMessage.getLocalUri());
if (imageMessage.getThumUri() != null)
intent.putExtra("thumbnail", imageMessage.getThumUri());
context.startActivity(intent);
}
/**
* 当长按消息时执行。
*
* @param context 上下文。
* @param view 触发点击的 View。
* @param message 被长按的消息的实体信息。
* @return 如果用户自己处理了长按后的逻辑,则返回 true,否则返回 false,false 走融云默认处理方式。
*/
@Override
public boolean onMessageLongClick(Context context, View view, Message message) {
// if (message.getContent() instanceof ImageMessage) {
// popWindow(context, view);
// sendJpg(message);
// return true;
// }
return false;
}
/**
* 当点击链接消息时执行。
*
* @param context 上下文。
* @param link 被点击的链接。
* @return 如果用户自己处理了点击后的逻辑处理,则返回 true, 否则返回 false, false 走融云默认处理方式。
*/
@Override
public boolean onMessageLinkClick(Context context, String link) {
return false;
}
}
在连接融云服务器之前,调用这个接口:
/**
* 设置会话列表界面操作的监听器。
*/
RongIM.setConversationBehaviorListener(new MyConversationBehaviorListener());
最后编写图片浏览Activity
@EActivity(R.layout.activity_image_browser)
public class PhotoActivity extends BaseActivity {
@App
ParentsApp app;
@Extra("pos")
int pos;
@Extra("photos")
ArrayList<ImPhoto> imPhotos;
@ViewById(R.id.tv_title)
TextView title;
@ViewById(R.id.vp)
ViewPager viewPager;
@AfterViews
void init() {
initViews();
ImagePagerAdapter adapter = new ImagePagerAdapter();
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(pos);
}
private void initViews() {
title.setText("照片查看");
}
@Click({R.id.back, R.id.tv})
public void back() {
finish();
}
@Override
public void onSuccess() {
}
/**
* @Description: 图片适配器
*/
public class ImagePagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return imPhotos.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
PhotoView view = new PhotoView(app);
view.enable();
view.setScaleType(ImageView.ScaleType.FIT_CENTER);
view.setBackgroundColor(getResources().getColor(R.color.black));
Glide.with(PhotoActivity.this)
.load(imPhotos.get(position).getUrl())
.error(R.drawable.default_error)
.placeholder(R.drawable.default_error)
.skipMemoryCache(true)
.dontTransform()
.into(view);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
布局文件
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<include
android:id="@+id/title"
layout="@layout/title_layout"/>
<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/title"/>
</RelativeLayout>
3.为好友加上头像
融云只提供聊天管道,好友关系需要自己维护,下面示例下为好友加上背景。
首先获取好友之后,需要将其保存到融云用户中:
void refreshIm(ImFriend im, DbManager dbUtils) {
try {
ImFriend friend = dbUtils.findById(ImFriend.class, im.getImid());
if (friend == null) {
dbUtils.save(im);
} else {
dbUtils.update(im);
if (TextUtils.isEmpty(im.getPicSrc())) {
if (!TextUtils.isEmpty(friend.getPicSrc())) {
//注意新的头像添加后通知融云刷新下用户信息
RongIM.getInstance().refreshUserInfoCache(new UserInfo(im.getImid(), im.getFriendName(), null));
}
} else {
if (!im.getPicSrc().equals(friend.getPicSrc()))
RongIM.getInstance().refreshUserInfoCache(new UserInfo(im.getImid(), im.getFriendName(), Uri.parse(im.getPicSrc())));
}
}
} catch (DbException e) {
LogUtils.e("保存imFriend失败");
}
}
接下来设置用户提供者(在连接融云服务器之前):
RongIM.setUserInfoProvider(new RongIM.UserInfoProvider() {
@Override
public UserInfo getUserInfo(String s) {
try {
ImFriend imFriend = dbUtils.findById(ImFriend.class, s);
if (imFriend != null) {
UserInfo userInfo;
if (imFriend.getPicSrc() == null) {
userInfo = new UserInfo(imFriend.getImid(), imFriend.getFriendName(), null);
} else
userInfo = new UserInfo(imFriend.getImid(), imFriend.getFriendName(), Uri.parse(imFriend.getPicSrc()));
// LogUtils.e("返回了");
RongIM.getInstance().refreshUserInfoCache(userInfo);
return userInfo;
}
} catch (DbException e) {
}
// LogUtils.e("获取联系人信息:" + s);
return getInfo(s);
}
}, true);
如果群组也有头像:
RongIM.getInstance().setGroupInfoProvider(new RongIM.GroupInfoProvider() {
@Override
public Group getGroupInfo(String groupId) {
try {
ImGroup imGroup = dbUtils.findById(ImGroup.class, groupId);
if (imGroup == null)
return null;
//暂时没有班级头像,传null
Group group = new Group(imGroup.id, imGroup.name, null);
return group;
} catch (DbException e) {
LogUtils.e("数据库查找群信息失败");
return null;
}
}
}, true);
private UserInfo getInfo(final String s) {
final DbManager dbUtils = DbUtils.getDb(app);
info = null;
requestFlag = false;
//执行到此处说明本地没有缓存,请求网络
OkHttpUtils
.get()
.url(Constants.GET_IM_INFO_URL)
.addParams("IMID", s)
.addParams("Token", CommonUtils.getParent(app).getToken())
.tag(MainActivity.this)
.build()
.execute(new StringCallback() {
@Override
public void onError(Request request, Exception e) {
requestFlag = true;
CommonUtils.showNoNet(app);
}
@Override
public void onResponse(String response) {
try {
JSONObject object = new JSONObject(response);
ImFriend imFriend = new ImFriend(s, object.getString("Name"), object.getString("PicSrc"));
if (imFriend.getPicSrc() == null) {
info = new UserInfo(imFriend.getImid(), imFriend.getFriendName(), null);
} else
info = new UserInfo(imFriend.getImid(), imFriend.getFriendName(), Uri.parse(imFriend.getPicSrc()));
RongIM.getInstance().refreshUserInfoCache(info);
dbUtils.saveOrUpdate(imFriend);
RongIM.getInstance().refreshUserInfoCache(info);
} catch (Exception e) {
}
requestFlag = true;
}
});
while (!requestFlag) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
}
}
return info;
}
填充用户头像与群组头像逻辑基本一致。
4.群组聊天实现@功能
直接上源码,懒得写了:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/layout_title"
android:layout_width="match_parent"
android:layout_height="132px"
android:background="@color/status_color">
<ImageView
android:id="@+id/back"
android:layout_width="40px"
android:layout_height="40px"
android:layout_centerVertical="true"
android:layout_marginLeft="20px"
android:src="@drawable/btn_back"
app:layout_auto_basewidth="height"/>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/back"
android:gravity="center"
android:text="返回"
android:textColor="@color/white"
android:textSize="46px"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textColor="@color/white"
android:textSize="45px"/>
<TextView
android:id="@+id/tv_title2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_title"
android:layout_centerHorizontal="true"
android:layout_marginTop="10px"
android:text="聊天"
android:textColor="@color/white"
android:textSize="30px"/>
</RelativeLayout>
<ImageView
android:id="@+id/img_user_info"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:scaleType="fitCenter"
android:src="@drawable/ctp"
app:layout_auto_basewidth="height"/>
</RelativeLayout>
<fragment
android:id="@+id/conversation"
android:name="io.rong.imkit.fragment.ConversationFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
import android.content.Intent;
import android.net.Uri;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.beisai.utils.LogUtils;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.OnActivityResult;
import org.androidannotations.annotations.ViewById;
import java.util.Locale;
import io.rong.imkit.RongContext;
import io.rong.imkit.RongIM;
import io.rong.imkit.fragment.ConversationFragment;
import io.rong.imkit.widget.provider.TextInputProvider;
import io.rong.imlib.model.Conversation;
@EActivity(R.layout.activity_conversation)
public class ConversationActivity extends BaseActivity {
@ViewById(R.id.img_user_info)
ImageView imgInfo;
/*显示聊天人姓名:王大狗*/
@ViewById(R.id.tv_title)
TextView mTitle;
/*副标题,显示:王二狗的妈妈*/
@ViewById(R.id.tv_title2)
TextView mTitle2;
// /**
// * 刚刚创建完讨论组后获得讨论组的id 为targetIds,需要根据 为targetIds 获取 targetId
// */
// private String mTargetIds;
/**
* 目标 Id
*/
private String mTargetId;
/**
* 会话类型
*/
private Conversation.ConversationType mConversationType;
private String chatType;
private String sInput;
@AfterViews
void init() {
getIntentDate(getIntent());
}
/**
* 展示如何从 Intent 中得到 融云会话页面传递的 Uri
*/
private void getIntentDate(Intent intent) {
chatType = intent.getData().getLastPathSegment();//获得当前会话类型
if (chatType.equals("group")) {
imgInfo.setVisibility(View.GONE);
mTitle.setText(intent.getData().getQueryParameter("title"));
mTitle2.setText("群聊");
} else {
imgInfo.setVisibility(View.VISIBLE);
String[] title = intent.getData().getQueryParameter("title").split("\n");
mTitle.setText(title[0]);
try {
mTitle2.setText(title[1]);
} catch (Exception e) {
mTitle2.setText("聊天");
}
}
checkTextInputEditTextChanged();
mTargetId = intent.getData().getQueryParameter("targetId");
// mTargetIds = intent.getData().getQueryParameter("targetIds");
mConversationType = Conversation.ConversationType.valueOf(intent.getData().getLastPathSegment().toUpperCase(Locale.getDefault
()));
enterFragment(mConversationType, mTargetId);
}
String beforeText;
String onTextChange;
/**
* 检测输入框变化
*/
public void checkTextInputEditTextChanged() {
TextInputProvider textInputProvider = new TextInputProvider(RongContext.getInstance());
RongIM.setPrimaryInputProvider(textInputProvider);
textInputProvider.setEditTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
LogUtils.e("beforeTextChanged------>" + s);
beforeText = s.toString();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
LogUtils.e("onTextChanged------>" + s);
onTextChange = s.toString();
}
@Override
public void afterTextChanged(Editable s) {
LogUtils.e("after------>" + s);
if (TextUtils.isEmpty(beforeText) ||beforeText.equals(onTextChange)) {
return;
}
sInput = s.toString();
if ("group".equals(getIntent().getData().getLastPathSegment())) {
if (s.toString().endsWith("@")) {
AtActivity_.intent(ConversationActivity.this)
.parcelableArrayListExtra("member", getIntent().getParcelableArrayListExtra("member"))
.extra("classId", mTargetId.substring(2))
.startForResult(61);
}
}
}
});
}
@OnActivityResult(61)
void onResult(int resultCode, @OnActivityResult.Extra String txt) {
TextInputProvider textInputProvider = (TextInputProvider) RongContext.getInstance().getPrimaryInputProvider();
if (resultCode == RESULT_OK) {
//重置文本框数据
textInputProvider.setEditTextContent(sInput + txt);
}
//else {
//textInputProvider.setEditTextContent(sInput + " ");
// }
}
/**
* 加载会话页面 ConversationFragment
*
* @param mConversationType 会话类型
* @param mTargetId 目标 Id
*/
private void enterFragment(Conversation.ConversationType mConversationType, String mTargetId) {
ConversationFragment fragment = (ConversationFragment) getSupportFragmentManager().findFragmentById(R.id.conversation);
Uri uri = Uri.parse("rong://" + getApplicationInfo().packageName).buildUpon()
.appendPath("conversation").appendPath(mConversationType.getName().toLowerCase())
.appendQueryParameter("targetId", mTargetId).build();
fragment.setUri(uri);
}
}
AtActivity不贴了,就是展示群组成员,选择好后回调即可。
以上是关于融云知识点的主要内容,如果未能解决你的问题,请参考以下文章