1.集成
从官网下载SDK,这里以Rong_Cloud_Android_IMKit_SDK_v2_8_7_Stable_8d65c为例
首先导入IMKit和IMLib(IMKit以IMLib为基础)
Rong_Cloud_Android_IMKit_SDK_v2_8_7_Stable_8d65c\Rong_Cloud_Android_IMKit_SDK_v2_8_7_Stable\IMKit
在项目的Module下的libs下加入融云SDK中的Rong_Cloud_Android_IMKit_SDK_v2_8_7_Stable_8d65c\PushLib\pushDaemon\libs下的四个文件夹
在项目Module下的src\main\assets下加入融云SDK中的
Rong_Cloud_Android_IMKit_SDK_v2_8_7_Stable_8d65c\PushLib\pushDaemon\executable下的四个文件夹
2.配置
在IMLib的AndroidManifest.xml中替换融云的Key
<meta-data android:name="RONG_CLOUD_APP_KEY" android:value="" />在项目的Module的build.gradle中加入
compile project(':IMKit')
在settings.gradle中加入
include ':IMKit', ':IMLib'在项目Module中的AndroidManifest.xml中加入
<service android:name="io.rong.imlib.ipc.RongService" android:process=":ipc" /> <service android:name="io.rong.imlib.ReConnectService" /> <receiver android:name="io.rong.imlib.ConnectChangeReceiver" /> <receiver android:name="io.rong.imlib.HeartbeatReceiver" android:process=":ipc" /> <activity android:name="io.rong.imkit.tools.RongWebviewActivity" android:screenOrientation="portrait" /> <activity android:name="io.rong.imkit.widget.provider.TakingPicturesActivity" android:configChanges="orientation|keyboardHidden" android:screenOrientation="portrait" /> <receiver android:name=".util.im.NotificationReceiver" android:exported="true"> <intent-filter> <action android:name="io.rong.push.intent.MESSAGE_ARRIVED" /> <action android:name="io.rong.push.intent.MI_MESSAGE_ARRIVED" /> <action android:name="io.rong.push.intent.MESSAGE_CLICKED" /> <action android:name="io.rong.push.intent.MI_MESSAGE_CLICKED" /> </intent-filter> </receiver>
3.初始化
在Application中
RongIM.init(this); RongCloudEvent.init(this);
获取Token
public class RongIMUtil { // 融云文档提供: // 可搜索:关于 IMkit 中报“Rong SDK should not be initialized at subprocess”的解决方法 public static String getCurProcessName(final Context context) { int pid = android.os.Process.myPid(); ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); for (ActivityManager.RunningAppProcessInfo appProcess : activityManager.getRunningAppProcesses()) { if (appProcess.pid == pid) { return appProcess.processName; } } return null; } public static void connectRongIM(final Context context) { // 获取融云的Token final String imToken = PreferenceUtils.getStringValue(context, Preferences.RongYunToken, ""); if (StringUtil.isEmpty(imToken)) { final RongYunResponseHandler nextStep = new RongYunResponseHandler() { @Override public void next(final ValidateResult validateResult) { if (validateResult.isOK()) { PreferenceUtils.modifyStringValueInPreferences(context, Preferences.RongYunToken, validateResult.getData()); connect(validateResult.getData()); } } }; IHealthClient.getRongToken(nextStep, context); } else { connect(imToken); } } private static void connect(final String rongYunToken) { // 连接融云服务器。 try { RongIM.connect(rongYunToken, new RongIMClient.ConnectCallback() { @Override public void onTokenIncorrect() { } @Override public void onSuccess(final String s) { // 此处处理连接成功。 Log.d("RongYun", "Login successfully."); RongCloudEvent.getInstance().setOtherListener(); } @Override public void onError(final RongIMClient.ErrorCode errorCode) { // 此处处理连接错误。 Log.d("RongYun", "Login failed."); } }); } catch (final Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }设置监听
/** * 融云SDK事件监听处理。 把事件统一处理,开发者可直接复制到自己的项目中去使用。 * <p/> * 该类包含的监听事件有: * 1、会话列表界面操作的监听器: ConversationListBehaviorListener。 * 2、接收消息的监听器: OnReceiveMessageListener。 * 3、用户信息的提供者: UserInfoProvider。 * 4、群组信息的提供者: GroupUserInfoProvider。 * 5、GroupUserInfo提供者: GroupUserInfoProvider。 * 6、连接状态监听器,以获取连接相关状态: ConnectionStatusListener。 * 7、地理位置提供者: LocationProvider。 * 8、会话界面操作的监听器: ConversationBehaviorListener。 */ public final class RongCloudEvent implements RongIM.ConversationListBehaviorListener, RongIMClient.OnReceiveMessageListener, RongIM.UserInfoProvider, RongIM.GroupInfoProvider, RongIM.GroupUserInfoProvider, RongIMClient.ConnectionStatusListener, RongIM.LocationProvider, RongIM.ConversationBehaviorListener, RongIM.OnSendMessageListener{ private static final String TAG = RongCloudEvent.class.getSimpleName(); private static RongCloudEvent mRongCloudInstance; private final Context mContext; /** * 初始化 RongCloud. * * @param context * 上下文。 */ public static void init(final Context context) { if (mRongCloudInstance == null) { synchronized (RongCloudEvent.class) { if (mRongCloudInstance == null) { mRongCloudInstance = new RongCloudEvent(context); } } } } /** * 构造方法。 * * @param context * 上下文。 */ private RongCloudEvent(final Context context) { mContext = context; initDefaultListener(); } /** * RongIM.init(this) 后直接可注册的Listener。 */ private void initDefaultListener() { RongIM.setConversationBehaviorListener(this);//设置会话界面操作的监听器。 RongIM.setConversationListBehaviorListener(this);//设置会话列表界面操作的监听器 RongIM.setUserInfoProvider(this, true);// 设置用户信息提供者。 RongIM.setGroupInfoProvider(this, true);// 设置群组信息提供者。 RongIM.setLocationProvider(this);//设置地理位置提供者,不用位置的同学可以注掉此行代码 } /* * 连接成功注册。 <p/> 在RongIM-connect-onSuccess后调用。 */ public void setOtherListener() { RongIM.setOnReceiveMessageListener(this);// 设置发出消息接收监听器. RongIM.setConnectionStatusListener(this);// 设置连接状态监听器。 RongIM.setOnReceiveMessageListener(this);// 设置消息接收监听器。 setUserInfoEngineListener(); //用户信息提供者回调监听 // setGroupInfoEngineListener(); //群组信息提供者回调监听 } /** * 获取RongCloud 实例。 * * @return RongCloud。 */ public static RongCloudEvent getInstance() { return mRongCloudInstance; } @Override public void onChanged(ConnectionStatus connectionStatus) { switch (connectionStatus){ case KICKED_OFFLINE_BY_OTHER_CLIENT://用户账户在其他设备登录,本机会被踢掉线 ActivityUtil.reLogout(IHealthActivity.INSTANCE); break; } } @Override public boolean onUserPortraitClick(Context context, Conversation.ConversationType conversationType, UserInfo userInfo) { return false; } @Override public boolean onUserPortraitLongClick(Context context, Conversation.ConversationType conversationType, UserInfo userInfo) { return false; } @Override public boolean onMessageClick(Context context, View view, Message message) { return false; } @Override public boolean onMessageLinkClick(Context context, String s) { return false; } @Override public boolean onMessageLongClick(Context context, View view, Message message) { return false; } @Override public boolean onConversationPortraitClick(Context context, Conversation.ConversationType conversationType, String s) { return false; } @Override public boolean onConversationPortraitLongClick(Context context, Conversation.ConversationType conversationType, String s) { return false; } @Override public boolean onConversationLongClick(Context context, View view, UIConversation uiConversation) { return false; } @Override public boolean onConversationClick(Context context, View view, UIConversation uiConversation) { return false; } @Override public Group getGroupInfo(String s) { return GroupInfoEngine.getInstance(mContext).startEngine(s); } @Override public GroupUserInfo getGroupUserInfo(String s, String s1) { return null; } @Override public void onStartLocation(Context context, LocationCallback locationCallback) { } @Override public boolean onReceived(Message message, int i) { return false; } @Override public UserInfo getUserInfo(String s) { return UserInfoEngine.getInstance(mContext).startEngine(s); } @Override public Message onSend(Message message) { return null; } @Override public boolean onSent(Message message, RongIM.SentMessageErrorCode sentMessageErrorCode) { return false; } /** * 需要 rongcloud connect 成功后设置的 listener */ public void setUserInfoEngineListener() { UserInfoEngine.getInstance(mContext).setListener(new UserInfoEngine.UserInfoListener() { @Override public void onResult(UserInfo info) { if (info != null && RongIM.getInstance() != null) { RongIM.getInstance().refreshUserInfoCache(info); } } }); } /** * 需要 rongcloud connect 成功后设置的 listener */ public void setGroupInfoEngineListener() { GroupInfoEngine.getInstance(mContext).setListener(new GroupInfoEngine.GroupInfoListeners() { @Override public void onResult(Group info) { if (info != null && RongIM.getInstance() != null) { RongIM.getInstance().refreshGroupInfoCache(info); } } }); } }提供用户信息
/** * 用户信息提供者的异步请求类 * Created by AMing on 15/12/10. * Company RongCloud */ public class UserInfoEngine { private static UserInfoEngine instance; private UserInfoListener mListener; public static UserInfoEngine getInstance(Context context) { if (instance == null) { instance = new UserInfoEngine(context); } return instance; } private UserInfoEngine(Context context) { this.context = context; } private static Context context; private String userid; public String getUserid() { return userid; } public void setUserid(String userid) { this.userid = userid; } private UserInfo userInfo; public UserInfo getUserInfo() { return userInfo; } public void setUserInfo(UserInfo userInfo) { this.userInfo = userInfo; } public UserInfo startEngine(String userid) { setUserid(userid); ((IHealthApplication)context).getCircleService(context).tyeGetUserInfoByUid(userid,getGetUserInfoResponseHandler()); return getUserInfo(); } private ResponseHandler getGetUserInfoResponseHandler() { return new ResponseHandler() { @Override public void onRequestSucceeded(final Object data) { final JSONObject jsonObject = JSON.parseObject(data.toString()); final String uId = jsonObject.getString("userId"); final String uName = jsonObject.getString("userName"); final String uImg = jsonObject.getString("avatar"); userInfo = new UserInfo(uId, uName, Uri.parse(uImg)); if (mListener != null) { mListener.onResult(userInfo); } } @Override public void onRequestFailed(final Object data) { try { if ((Integer) data > -1) super.onLoginError(IHealthActivity.INSTANCE, data); } catch (final Exception ex) { PromptUtil.show(IHealthActivity.INSTANCE, data.toString()); } } }; } public void setListener(UserInfoListener listener) { this.mListener = listener; } public interface UserInfoListener { void onResult(UserInfo info); } }4.调用会话列表
if (RongIM.getInstance() != null){ Map<String, Boolean> map = new HashMap<>(); // 会话列表需要显示私聊会话, 第二个参数 true 代表私聊会话需要聚合显示 map.put(Conversation.ConversationType.PRIVATE.getName(), false); /* // 会话列表需要显示群组会话, 第二个参数 false 代表群组会话不需要聚合显示 map.put(Conversation.ConversationType.GROUP.getName(), false); */ RongIM.getInstance().startConversationList(getActivity(), map); }else { PromptUtil.show(getActivity(), "连接IM服务器异常"); }会话列表
public class ConversationListActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.conversationlist); } public void onTitleBackClicked(final View view) { onBackPressed(); } }
布局
<fragment android:id="@+id/conversationlist" android:name="io.rong.imkit.fragment.ConversationListFragment" android:layout_width="match_parent" android:layout_height="match_parent" />AndroidManifest.xml设置
<activity android:name=".controller.ConversationListActivity" android:screenOrientation="portrait" android:windowSoftInputMode="stateHidden|adjustResize"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="包名" android:pathPrefix="/conversationlist" android:scheme="rong" /> </intent-filter> </activity>5.启用会话界面
传入用户Id和name
personalUserID = data.toString(); if (!StringUtil.isEmpty(personalUserID)) { //启动会话界面 if (RongIM.getInstance() != null) { RongIM.getInstance().startPrivateChat(XX.this, personalUserID, residentName); } else { PromptUtil.show(ResidentDetailActivityNew.this, "连接IM服务器异常"); } }会话界面
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.conversation); Intent intent = getIntent(); if (intent == null || intent.getData() == null){ return; } mTargetId = intent.getData().getQueryParameter("targetId"); mConversationType = Conversation.ConversationType.valueOf(intent.getData().getLastPathSegment().toUpperCase(Locale.getDefault())); title = intent.getData().getQueryParameter("title");布局
<fragment android:id="@+id/conversation" android:name="io.rong.imkit.fragment.ConversationFragment" android:layout_width="match_parent" android:layout_height="match_parent" />AndroidManifest.xml设置
<activity android:name=".controller.ConversationActivity" android:screenOrientation="portrait" android:windowSoftInputMode="stateHidden|adjustResize"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="包名" android:pathPrefix="/conversation/" android:scheme="rong" /> </intent-filter> </activity>