diff --git a/app/src/main/java/com/shayu/phonelive/AppContext.java b/app/src/main/java/com/shayu/phonelive/AppContext.java index 128f680e6..8708a0a1f 100644 --- a/app/src/main/java/com/shayu/phonelive/AppContext.java +++ b/app/src/main/java/com/shayu/phonelive/AppContext.java @@ -150,8 +150,7 @@ public class AppContext extends CommonAppContext { RongcloudIMManager.addRongcloudIMOnReceiveMessageListener(); //初始化融云 RongcloudIMManager.initRongIM(this); - //添加融云连接状态监听 - RongcloudIMManager.setIMStatusListener(); + //监听im消息 diff --git a/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java b/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java index 5736848df..fa5d990e0 100644 --- a/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java +++ b/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java @@ -13,6 +13,8 @@ import com.yunbao.common.bean.IMLoginModel; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.manager.base.BaseCacheManager; +import com.yunbao.common.manager.imrongcloud.MessageIMManager; +import com.yunbao.common.manager.imrongcloud.RongcloudIMManager; import java.util.Map; @@ -99,11 +101,15 @@ public class IMLoginManager extends BaseCacheManager { * 退出登录 */ public void logout() { + //添加融云连接状态监听 + RongcloudIMManager.removeIMStatusListener(); //删除用户登录信息 deleteByKey(KEY_USER_INFO); //用户对象置空 userInfo = null; manager = null; + RongcloudIMManager.logoutIM(); + MessageIMManager.get(context).logout(); } } diff --git a/common/src/main/java/com/yunbao/common/manager/InstructorRemarkManager.java b/common/src/main/java/com/yunbao/common/manager/InstructorRemarkManager.java index 68ba76ab4..e015845d9 100644 --- a/common/src/main/java/com/yunbao/common/manager/InstructorRemarkManager.java +++ b/common/src/main/java/com/yunbao/common/manager/InstructorRemarkManager.java @@ -11,6 +11,7 @@ import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.manager.base.BaseCacheManager; +import java.util.HashMap; import java.util.Map; /** @@ -38,6 +39,9 @@ public class InstructorRemarkManager extends BaseCacheManager { instructorRemarkMap = JSON.parseObject(getString(KEY_INSTRUCTOR_REMARK), new TypeReference>() { }); } + if (instructorRemarkMap == null) { + instructorRemarkMap = new HashMap<>(); + } return instructorRemarkMap; } diff --git a/common/src/main/java/com/yunbao/common/manager/imrongcloud/MessageIMManager.java b/common/src/main/java/com/yunbao/common/manager/imrongcloud/MessageIMManager.java index 8d1e0e73c..dd1f125b9 100644 --- a/common/src/main/java/com/yunbao/common/manager/imrongcloud/MessageIMManager.java +++ b/common/src/main/java/com/yunbao/common/manager/imrongcloud/MessageIMManager.java @@ -34,6 +34,15 @@ public class MessageIMManager { number = 0; } + public void logout() { + number = 0; + imNumber = 0; + systemNumber = 0; + //发送通知 + unreadMessagesHandler.post(essagesRunnable); + manager = null; + } + /** * 获取单利 */ @@ -85,6 +94,8 @@ public class MessageIMManager { try { if (!TextUtils.isEmpty(number) && Integer.parseInt(number) > 0) { systemNumber = Integer.parseInt(number); + }else { + systemNumber = 0; } } catch (NumberFormatException e) { systemNumber = 0; @@ -125,6 +136,8 @@ public class MessageIMManager { try { if (!TextUtils.isEmpty(number) && Integer.parseInt(number) > 0) { systemNumber = Integer.parseInt(number); + }else { + systemNumber = 0; } } catch (NumberFormatException e) { systemNumber = 0; @@ -148,7 +161,7 @@ public class MessageIMManager { //整合未读消息数目并且发送出去 private final Runnable essagesRunnable = () -> { number = imNumber + systemNumber; - EventBus.getDefault().postSticky(new MessageIMEvent().setNumber(number)); + EventBus.getDefault().post(new MessageIMEvent().setNumber(number)); }; } diff --git a/common/src/main/java/com/yunbao/common/manager/imrongcloud/RongcloudIMManager.java b/common/src/main/java/com/yunbao/common/manager/imrongcloud/RongcloudIMManager.java index 399475ef6..d781963dc 100644 --- a/common/src/main/java/com/yunbao/common/manager/imrongcloud/RongcloudIMManager.java +++ b/common/src/main/java/com/yunbao/common/manager/imrongcloud/RongcloudIMManager.java @@ -10,13 +10,19 @@ import androidx.annotation.NonNull; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.CircleCrop; import com.bumptech.glide.request.RequestOptions; +import com.yunbao.common.CommonAppConfig; +import com.yunbao.common.bean.BaseModel; import com.yunbao.common.bean.IMLoginModel; import com.yunbao.common.manager.IMLoginManager; +import org.greenrobot.eventbus.EventBus; + +import cn.rongcloud.rtc.api.RCRTCEngine; import io.rong.imkit.GlideKitImageEngine; import io.rong.imkit.IMCenter; import io.rong.imkit.RongIM; import io.rong.imkit.config.RongConfigCenter; +import io.rong.imlib.RongCoreClient; import io.rong.imlib.RongIMClient; import io.rong.imlib.model.Conversation; import io.rong.imlib.model.Message; @@ -107,7 +113,8 @@ public class RongcloudIMManager { public void onSuccess(String s) { //连接成功,如果 onDatabaseOpened() 时没有页面跳转,也可在此时进行跳转。 Log.e(CLASSNAME, "onSuccess:" + s); - + //添加融云连接状态监听 + RongcloudIMManager.setIMStatusListener(); } @Override @@ -145,6 +152,10 @@ public class RongcloudIMManager { RongIM.setConnectionStatusListener(connectionStatusListener); } + public static void removeIMStatusListener() { + RongIM.setConnectionStatusListener(null); + } + /** * 监听 IM 连接状态,可根据连接状态进行不同业务处理 */ @@ -159,6 +170,7 @@ public class RongcloudIMManager { break; //用户账号在其它设备登录,此设备被踢下线 case KICKED_OFFLINE_BY_OTHER_CLIENT: +// EventBus.getDefault().post(new BaseModel()); break; //连接暂时挂起(多是由于网络问题导致),SDK 会在合适时机进行自动重连 case SUSPEND: diff --git a/live/build.gradle b/live/build.gradle index c9272badb..989609960 100644 --- a/live/build.gradle +++ b/live/build.gradle @@ -1 +1 @@ -apply plugin: 'com.android.library' apply plugin: 'img-optimizer' apply plugin: 'kotlin-android' android { compileSdkVersion rootProject.ext.android.compileSdkVersion buildToolsVersion rootProject.ext.android.buildToolsVersion aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false packagingOptions { pickFirst "lib/armeabi/libyuvutils.so" pickFirst "lib/arm64-v8a/libyuvutils.so" pickFirst "lib/armeabi-v7a/libyuvutils.so" pickFirst "lib/armeabi/libyuvtools.so" pickFirst "lib/arm64-v8a/libyuvtools.so" pickFirst "lib/armeabi-v7a/libyuvtools.so" exclude "lib/arm64-v8a/libmmcv_api_handgesture.so" exclude "lib/arm64-v8a/libmmcv_api_express.so" exclude "lib/arm64-v8a/libMediaEncoder.so" exclude "lib/arm64-v8a/libarcore_sdk_c.so" exclude "lib/arm64-v8a/libmediadecoder.so" exclude "lib/arm64-v8a/libMediaMuxer.so" exclude "lib/arm64-v8a/libarcore_sdk_jni.so" exclude "lib/arm64-v8a/libMediaUtils.so" exclude "lib/arm64-v8a/libcosmosffmpeg.so" } defaultConfig { minSdkVersion rootProject.ext.android.minSdkVersion targetSdkVersion rootProject.ext.android.targetSdkVersion versionCode rootProject.ext.android.versionCode versionName rootProject.ext.android.versionName manifestPlaceholders = rootProject.ext.manifestPlaceholders ndk { abiFilters "armeabi-v7a", "arm64-v8a" } javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName()] } } } aaptOptions { cruncherEnabled = false useNewCruncher = false } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } kotlinOptions { allWarningsAsErrors = true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } repositories { flatDir { dirs 'libs', '../libs' } mavenCentral() } dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) //socket.io implementation('io.socket:socket.io-client:1.0.0') { exclude group: 'org.json', module: 'json' } //common implementation project(path: ':common') annotationProcessor rootProject.ext.dependencies["arouter-compiler"] //工具 api rootProject.ext.dependencies["blank-utilcode"] implementation 'com.eightbitlab:blurview:1.6.6' implementation files('libs/beautysdk-202202241203.aar') implementation 'com.google.code.gson:gson:2.8.6' implementation "com.getkeepsafe.relinker:relinker:1.4.4" } \ No newline at end of file +apply plugin: 'com.android.library' apply plugin: 'img-optimizer' apply plugin: 'kotlin-android' android { compileSdkVersion rootProject.ext.android.compileSdkVersion buildToolsVersion rootProject.ext.android.buildToolsVersion aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false packagingOptions { pickFirst "lib/armeabi/libyuvutils.so" pickFirst "lib/arm64-v8a/libyuvutils.so" pickFirst "lib/armeabi-v7a/libyuvutils.so" pickFirst "lib/armeabi/libyuvtools.so" pickFirst "lib/arm64-v8a/libyuvtools.so" pickFirst "lib/armeabi-v7a/libyuvtools.so" exclude "lib/arm64-v8a/libmmcv_api_handgesture.so" exclude "lib/arm64-v8a/libmmcv_api_express.so" exclude "lib/arm64-v8a/libMediaEncoder.so" exclude "lib/arm64-v8a/libarcore_sdk_c.so" exclude "lib/arm64-v8a/libmediadecoder.so" exclude "lib/arm64-v8a/libMediaMuxer.so" exclude "lib/arm64-v8a/libarcore_sdk_jni.so" exclude "lib/arm64-v8a/libMediaUtils.so" exclude "lib/arm64-v8a/libcosmosffmpeg.so" } defaultConfig { minSdkVersion rootProject.ext.android.minSdkVersion targetSdkVersion rootProject.ext.android.targetSdkVersion versionCode rootProject.ext.android.versionCode versionName rootProject.ext.android.versionName manifestPlaceholders = rootProject.ext.manifestPlaceholders ndk { abiFilters "armeabi-v7a", "arm64-v8a" } javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName()] } } } aaptOptions { cruncherEnabled = false useNewCruncher = false } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } kotlinOptions { allWarningsAsErrors = true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } repositories { flatDir { dirs 'libs', '../libs' } mavenCentral() } dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.0.0' implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) //socket.io implementation('io.socket:socket.io-client:1.0.0') { exclude group: 'org.json', module: 'json' } //common implementation project(path: ':common') annotationProcessor rootProject.ext.dependencies["arouter-compiler"] //工具 api rootProject.ext.dependencies["blank-utilcode"] implementation 'com.eightbitlab:blurview:1.6.6' implementation files('libs/beautysdk-202202241203.aar') implementation 'com.google.code.gson:gson:2.8.6' implementation "com.getkeepsafe.relinker:relinker:1.4.4" } \ No newline at end of file diff --git a/live/src/main/AndroidManifest.xml b/live/src/main/AndroidManifest.xml index 41f237ebe..e0f0cc711 100644 --- a/live/src/main/AndroidManifest.xml +++ b/live/src/main/AndroidManifest.xml @@ -82,7 +82,7 @@ + android:windowSoftInputMode="adjustResize|stateHidden"> listener) { + super(listener); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + super.onBindViewHolder(holder, position); + Message.MessageDirection messageDirection = mDataList.get(position).getMessage().getMessageDirection(); + Message.SentStatus sentStatus = mDataList.get(position).getMessage().getSentStatus(); + ImageView readReceipt = holder.getConvertView().findViewById(R.id.rc_read_receipt); + ImageView readReceiptNew = holder.getConvertView().findViewById(R.id.rc_read_receipt_new); + if (readReceipt.getVisibility() == View.VISIBLE) { + readReceipt.setVisibility(View.GONE); + readReceiptNew.setBackgroundResource(R.mipmap.icon_message_read); + } else { + if (messageDirection.equals(Message.MessageDirection.SEND)&&sentStatus.equals(Message.SentStatus.SENT)) + readReceiptNew.setBackgroundResource(R.mipmap.icon_message_unread); + } + } +} diff --git a/live/src/main/java/com/yunbao/live/views/InputPanelViewHolder.java b/live/src/main/java/com/yunbao/live/views/InputPanelViewHolder.java index 447fcb90c..31fb17e7a 100644 --- a/live/src/main/java/com/yunbao/live/views/InputPanelViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/InputPanelViewHolder.java @@ -78,10 +78,22 @@ public class InputPanelViewHolder extends LinearLayout implements View.OnClickLi inputPanelView.findViewById(R.id.lt_photo_button).setOnClickListener(this); inputPanelView.findViewById(R.id.lt_choospic_button).setOnClickListener(this); inputPanelView.findViewById(R.id.lt_video_button).setOnClickListener(this); - - + editBtn.setOnFocusChangeListener(focusChangeListener); } + //输入框焦点监听事件 + View.OnFocusChangeListener focusChangeListener = new OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (!hasFocus) { + //失去焦点 + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editBtn, InputMethodManager.SHOW_FORCED); + imm.hideSoftInputFromWindow(editBtn.getWindowToken(), 0); //强制隐藏键盘 + } + } + }; + @Override public void onClick(View v) { int id = v.getId(); @@ -188,7 +200,7 @@ public class InputPanelViewHolder extends LinearLayout implements View.OnClickLi } public void afterTextChanged(Editable s) { - editBtn.clearFocus(); + } }; diff --git a/live/src/main/java/com/yunbao/live/views/PDLiveConversationFragment.java b/live/src/main/java/com/yunbao/live/views/PDLiveConversationFragment.java new file mode 100644 index 000000000..535041dca --- /dev/null +++ b/live/src/main/java/com/yunbao/live/views/PDLiveConversationFragment.java @@ -0,0 +1,18 @@ +package com.yunbao.live.views; + +import com.yunbao.live.dialog.PDLiveMessageListAdapter; + +import io.rong.imkit.conversation.ConversationFragment; +import io.rong.imkit.conversation.MessageListAdapter; + +/** + * 聊天详情页面 + */ +public class PDLiveConversationFragment extends ConversationFragment { + @Override + protected MessageListAdapter onResolveAdapter() { + return new PDLiveMessageListAdapter(this); + } + + +} diff --git a/main/src/main/res/layout/rc_conversationlist_item.xml b/live/src/main/res/layout/rc_conversationlist_item.xml similarity index 77% rename from main/src/main/res/layout/rc_conversationlist_item.xml rename to live/src/main/res/layout/rc_conversationlist_item.xml index 25f1ecbe9..8a781ed44 100644 --- a/main/src/main/res/layout/rc_conversationlist_item.xml +++ b/live/src/main/res/layout/rc_conversationlist_item.xml @@ -11,18 +11,18 @@ @@ -35,8 +35,8 @@ @@ -69,23 +69,36 @@ app:layout_constraintStart_toEndOf="@+id/rc_conversation_portrait_rl" app:layout_constraintTop_toTopOf="parent" /> - + app:layout_constraintTop_toBottomOf="@+id/rc_conversation_title"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/live/src/main/res/mipmap-xxxhdpi/icon_message_read.png b/live/src/main/res/mipmap-xxxhdpi/icon_message_read.png new file mode 100644 index 000000000..57d802c40 Binary files /dev/null and b/live/src/main/res/mipmap-xxxhdpi/icon_message_read.png differ diff --git a/live/src/main/res/mipmap-xxxhdpi/icon_message_unread.png b/live/src/main/res/mipmap-xxxhdpi/icon_message_unread.png new file mode 100644 index 000000000..15d73986c Binary files /dev/null and b/live/src/main/res/mipmap-xxxhdpi/icon_message_unread.png differ diff --git a/main/src/main/java/com/yunbao/main/activity/MainActivity.java b/main/src/main/java/com/yunbao/main/activity/MainActivity.java index 46f96389d..de627156a 100644 --- a/main/src/main/java/com/yunbao/main/activity/MainActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/MainActivity.java @@ -41,6 +41,7 @@ import com.yunbao.common.CommonAppConfig; import com.yunbao.common.Constants; import com.yunbao.common.activity.AbsActivity; import com.yunbao.common.adapter.ViewPagerAdapter; +import com.yunbao.common.bean.BaseModel; import com.yunbao.common.bean.ChatRemarksBean; import com.yunbao.common.bean.ConfigBean; import com.yunbao.common.bean.LiveSvgGiftBean; @@ -1032,7 +1033,7 @@ public class MainActivity extends AbsActivity implements MainAppBarLayoutListene } //消息中心 - @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) + @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageIMEvent(MessageIMEvent event) { messageNumber = event.getNumber(); if (event.getNumber() > 0) { @@ -1054,4 +1055,16 @@ public class MainActivity extends AbsActivity implements MainAppBarLayoutListene v_table_redpoint_me.setVisibility(View.GONE); } } + + /** + * 用户被踢下线 + * + * @param model + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void userSignOut(BaseModel model) { +// IMLoginManager.get(mContext).logout(); +// CommonAppConfig.getInstance().clearLoginInfo(); +// LoginActivity.forward(); + } } diff --git a/main/src/main/java/com/yunbao/main/utils/PDLiveCustomConversationProvider.java b/main/src/main/java/com/yunbao/main/utils/PDLiveCustomConversationProvider.java index 0a65a0ea6..11332fbf7 100644 --- a/main/src/main/java/com/yunbao/main/utils/PDLiveCustomConversationProvider.java +++ b/main/src/main/java/com/yunbao/main/utils/PDLiveCustomConversationProvider.java @@ -4,6 +4,7 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import java.util.List; @@ -13,6 +14,7 @@ import io.rong.imkit.utils.RouteUtils; import io.rong.imkit.widget.adapter.IViewProviderListener; import io.rong.imkit.widget.adapter.ViewHolder; import io.rong.imlib.model.Conversation; +import io.rong.imlib.model.Message; import io.rong.imlib.model.UserInfo; /** @@ -23,7 +25,6 @@ public class PDLiveCustomConversationProvider extends BaseConversationProvider { public boolean isItemViewType(BaseUiConversation item) { //根据业务需要,判断 item 是该模板需要处理的会话时,返回 true, 否则返回 false //此处以自定义私聊会话模板为例 - Log.e("PDLiveCustomConversat","-+++++++++++++++++++++++++++++++++"); return item.mCore.getConversationType().equals(Conversation.ConversationType.PRIVATE); } @@ -31,20 +32,23 @@ public class PDLiveCustomConversationProvider extends BaseConversationProvider { public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //根据业务需要,自定义处理 Log.e("PDLiveCustomConversat","------------------------------------------"+viewType); -// View view = LayoutInflater.from(parent.getContext()).inflate(layout.rc_conversationlist_item, parent, false); return super.onCreateViewHolder(parent, viewType); } @Override public void bindViewHolder(ViewHolder holder, BaseUiConversation uiConversation, int position, List list, IViewProviderListener listener) { - for (BaseUiConversation conversation:list){ -// UserInfo userInfo = conversation.mCore.getLatestMessage().getUserInfo(); -//// Log.e("PDLiveCustomConversat","getName****************************"+userInfo.getName()); -// Log.e("PDLiveCustomConversat","getPortraitUri****************************"+userInfo.getPortraitUri().toString()); - } + //根据业务需要,自定义处理 - Log.e("PDLiveCustomConversat","****************************"); super.bindViewHolder(holder, uiConversation, position, list, listener); + if ( list.size()>0){ + Message.ReceivedStatus receivedStatus = list.get(position).mCore.getReceivedStatus(); + ImageView readReceipt = holder.itemView.findViewById(com.yunbao.live.R.id.rc_read_receipt_new); + if (receivedStatus.isRead()) { + readReceipt.setBackgroundResource(com.yunbao.live.R.mipmap.icon_message_read); + }else { + readReceipt.setBackgroundResource(com.yunbao.live.R.mipmap.icon_message_unread); + } + } } }