From d31af73479a8537ad9d0d0825c540799dc82b8b9 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Tue, 27 Dec 2022 10:03:05 +0800 Subject: [PATCH 001/118] =?UTF-8?q?PK=E7=BB=93=E6=9D=9F=E6=B6=88=E5=A4=B1P?= =?UTF-8?q?K=E6=9D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 ++-- .../java/com/yunbao/live/activity/LiveRyAnchorActivity.java | 5 +++++ .../com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/config.gradle b/config.gradle index ac60b7e57..6f21be570 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 -// serverHost : "https://napi.yaoulive.com", + serverHost : "https://napi.yaoulive.com", // 測試 - serverHost : "https://ceshi.yaoulive.com", +// serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index 8a46d8030..a7e4a792c 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -1501,6 +1501,11 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl mLivePushViewHolder.changeToBig(); } break; + case AI_AUTOMATIC_SPEECH: + if (mLiveRoomViewHolder != null) { + mLiveRoomViewHolder.aiAutomaticSpeech((event.getAiAutomaticSpeechModel())); + } + break; } } diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index 370ce2659..4afb31a72 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -391,6 +391,12 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { if (mIsAnchor) { ((LiveRyAnchorActivity) mContext).setPkBtnVisible(true); } + //如果PK结束Im没有发送关闭PK的消息,倒计时结束自动关闭 + if (mLiveLinkMicPkViewHolder != null) { + mLiveLinkMicPkViewHolder.removeFromParent(); + mLiveLinkMicPkViewHolder.release(); + } + mLiveLinkMicPkViewHolder = null; } } } From c8ba78f39b98a448b8d6b890d2a887ab68f8203d Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 27 Dec 2022 10:17:47 +0800 Subject: [PATCH 002/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=AE=A4=E8=BF=98=E6=98=AF=E4=BC=9A=E5=8D=A1?= =?UTF-8?q?=E4=B8=8D=E4=BC=9A=E8=87=AA=E5=8A=A8=E6=BB=9A=E5=8A=A8=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/adapter/LiveChatAdapter.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java index 27341f9d0..73127c6e0 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java @@ -47,7 +47,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Set; /** * Created by cxf on 2018/10/10. @@ -68,6 +67,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { private int mRecyclerViewScrolledDy; private int mPosition; + private boolean isBottom = false; public LiveChatAdapter(Context context) { mContext = context; @@ -128,8 +128,23 @@ public class LiveChatAdapter extends RecyclerView.Adapter { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); - if (isSlideToBottom(recyclerView) || dy == 0) return; + if (isBottom && dy >= 0) return; + // Log.i(TAG, "onScrolled: " + dy); mRecyclerViewScrolledDy = dy; + isBottom = false; + } + + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState == 0 && isSlideToBottom(recyclerView)) { + // Log.i(TAG, "onScrollStateChanged: 到底部了"); + mRecyclerViewScrolledDy = 0; + isBottom = true; + } else if (newState == 0) { + // Log.i(TAG, "onScrollStateChanged: 不是底部"); + isBottom = false; + } } }); } @@ -383,7 +398,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { if (bean == null) { return; } - // Log.i(TAG, "insertItem: " + bean.getContent()); + // Log.i(TAG, "insertItem: " + bean.getContent()); int size = mList.size(); //设置最大展示99条消息 if (size == 100) { @@ -397,7 +412,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { notifyItemInserted(getItemCount()); } size = mList.size(); - if (isSlideToBottom(mRecyclerView) || mRecyclerViewScrolledDy == 0) { + if (isBottom || mRecyclerViewScrolledDy == 0) { scrollToBottom(); } else { Bus.get().post(new LiveAudienceEvent() @@ -451,10 +466,10 @@ public class LiveChatAdapter extends RecyclerView.Adapter { } public void scrollToBottom() { - mRecyclerViewScrolledDy = 0; if (mList.size() > 0) { mRecyclerView.smoothScrollToPosition(getItemCount() - 1); } + mRecyclerViewScrolledDy = 0; } public void scrollToAt() { From 339d460c0faabdf0475df9d4523c63d0f91e6246 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 27 Dec 2022 13:52:01 +0800 Subject: [PATCH 003/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=AE=A4=E8=BF=98=E6=98=AF=E4=BC=9A=E5=8D=A1?= =?UTF-8?q?=E4=B8=8D=E4=BC=9A=E8=87=AA=E5=8A=A8=E6=BB=9A=E5=8A=A8=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/adapter/LiveChatAdapter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java index 73127c6e0..7cff740ac 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java @@ -129,7 +129,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (isBottom && dy >= 0) return; - // Log.i(TAG, "onScrolled: " + dy); + // Log.i(TAG, "onScrolled: " + dy); mRecyclerViewScrolledDy = dy; isBottom = false; } @@ -138,11 +138,11 @@ public class LiveChatAdapter extends RecyclerView.Adapter { public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == 0 && isSlideToBottom(recyclerView)) { - // Log.i(TAG, "onScrollStateChanged: 到底部了"); + // Log.i(TAG, "onScrollStateChanged: 到底部了"); mRecyclerViewScrolledDy = 0; isBottom = true; } else if (newState == 0) { - // Log.i(TAG, "onScrollStateChanged: 不是底部"); + // Log.i(TAG, "onScrollStateChanged: 不是底部"); isBottom = false; } } @@ -398,7 +398,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { if (bean == null) { return; } - // Log.i(TAG, "insertItem: " + bean.getContent()); + // Log.i(TAG, "insertItem: " + bean.getContent()+" size = "+(mList.size()+1)); int size = mList.size(); //设置最大展示99条消息 if (size == 100) { From a7cef3c6f87076977d1db2a0c482c436dde32945 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Tue, 27 Dec 2022 14:41:17 +0800 Subject: [PATCH 004/118] =?UTF-8?q?=E6=9C=BA=E5=99=A8=E4=BA=BA=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=89=93=E6=8B=9B=E5=91=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/activity/LiveRyAnchorActivity.java | 171 ++++++++++++++++++ .../yunbao/live/event/LiveAudienceEvent.java | 3 +- 2 files changed, 173 insertions(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index a7e4a792c..6e02d0be9 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -17,6 +17,7 @@ import android.content.Intent; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.os.Handler; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; @@ -31,17 +32,22 @@ import androidx.fragment.app.DialogFragment; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.blankj.utilcode.util.GsonUtils; import com.bumptech.glide.Glide; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.transition.Transition; import com.lxj.xpopup.XPopup; +import com.lxj.xpopup.core.BasePopupView; +import com.lxj.xpopup.interfaces.XPopupCallback; import com.opensource.svgaplayer.SVGAImageView; import com.tencent.trtc.TRTCCloudDef; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.CommonAppContext; import com.yunbao.common.Constants; +import com.yunbao.common.bean.AiAutomaticSpeechModel; import com.yunbao.common.bean.IMLoginModel; import com.yunbao.common.bean.LinkMicUserBean; +import com.yunbao.common.bean.LiveAiRobotBean; import com.yunbao.common.bean.LiveBean; import com.yunbao.common.bean.LiveUserGiftBean; import com.yunbao.common.bean.MicUserBean; @@ -52,6 +58,7 @@ import com.yunbao.common.http.CommonHttpConsts; import com.yunbao.common.http.CommonHttpUtil; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; +import com.yunbao.common.http.live.LiveNetManager; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.IMRTCManager; import com.yunbao.common.manager.RandomPkManager; @@ -99,11 +106,13 @@ import com.yunbao.live.views.LivePushRyViewHolder; import com.yunbao.live.views.LiveRoomViewHolder; import com.yunbao.live.views.LiveRyAnchorViewHolder; +import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.io.File; import java.util.List; +import java.util.Random; import cn.rongcloud.rtc.api.RCRTCEngine; import cn.rongcloud.rtc.api.callback.IRCRTCResultCallback; @@ -284,6 +293,52 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl switch (functionID) { case Constants.LIVE_ROBOT: new XPopup.Builder(mContext) + .setPopupCallback(new XPopupCallback() { + @Override + public void onCreated(BasePopupView popupView) { + + } + + @Override + public void beforeShow(BasePopupView popupView) { + + } + + @Override + public void onShow(BasePopupView popupView) { + + } + + @Override + public void onDismiss(BasePopupView popupView) { + EventBus.getDefault().post(new LiveAudienceEvent().setType(LiveAudienceEvent.LiveAudienceType.UPDATA_ROBOT)); + } + + @Override + public void beforeDismiss(BasePopupView popupView) { + + } + + @Override + public boolean onBackPressed(BasePopupView popupView) { + return false; + } + + @Override + public void onKeyBoardStateChanged(BasePopupView popupView, int height) { + + } + + @Override + public void onDrag(BasePopupView popupView, int value, float percent, boolean upOrLeft) { + + } + + @Override + public void onClickOutside(BasePopupView popupView) { + + } + }) .asCustom(new LiveRobotSettingCustomPopup(mContext)) .show(); break; @@ -674,6 +729,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl * @param data createRoom返回的数据 */ public void startLiveSuccess(String data, int liveType, int liveTypeVal) { + Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((" + data); mLiveType = liveType; mLiveTypeVal = liveTypeVal; //处理createRoom返回的数据 @@ -774,6 +830,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl if (CommonAppConfig.GAME_ENABLE) { mGameList = JSON.parseArray(obj.getString("game_switch"), Integer.class); } + getAiRobotStatus(); } /** @@ -1506,6 +1563,9 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl mLiveRoomViewHolder.aiAutomaticSpeech((event.getAiAutomaticSpeechModel())); } break; + case UPDATA_ROBOT: + getAiRobotStatus(); + break; } } @@ -1532,4 +1592,115 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl } }); } + + /** + * 获取机器人配置;取得求关注时间间隔 + */ + private long robotTime = 0; + + private void getAiRobotStatus() { + Log.e("随机打招呼", "((((((((((((((((((((((((((((((((((((((((((((((("); + LiveNetManager.get(mContext) + .getAiRobotStatus(new com.yunbao.common.http.base.HttpCallback() { + @Override + public void onSuccess(LiveAiRobotBean data) { + Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((" + data.toString()); + if (data.getStatus() == 1) { + if (robotRunnable != null) { + robotHandler.removeCallbacks(robotRunnable); + robotRunnable = null; + } + robotRunnable = new Runnable() { + @Override + public void run() { + Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((data.getName())" + data.getName()); + String robotName = data.getName(); + //发送消息 + LiveNetManager.get(mContext) + .getAiRobotBody(LiveAiRobotBean.Message.TYPE_FOLLOW, + new com.yunbao.common.http.base.HttpCallback>() { + @Override + public void onSuccess(List messageList) { + Random random = new Random(); + int randNumber = random.nextInt(messageList.size() - 1) - 1; + Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((data.randNumber())" + randNumber); + Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((data)" + messageList.toString()); + sendRobotMessage(robotName, messageList.get(randNumber).getContent()); + } + + @Override + public void onError(String error) { + Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((data.error())" + error); + } + }); + + } + }; + robotTime = data.getTime() * 60 * 1000; + Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((robotTime)" + robotTime); + robotHandler.postDelayed(robotRunnable, robotTime); + } + } + + @Override + public void onError(String error) { + ToastUtil.show(error); + } + }); + } + + //机器人求关注轮询器 + private Handler robotHandler = new Handler(); + private Runnable robotRunnable = null; + + /** + * '{"msg": + * [{"_method_":"aiAutomaticSpeech", + * "ct":{"name_color":"#f19ec2","ai_name":"'+_this.robotInfo.ai_name+'", + * "content":"'+content+'","user_name":"", + * "icon":"https://downs.yaoulive.com/xzs_tab.png", + * "system_bubble":"https://downs.yaoulive.com/xzs_qipao.9.png"}, + * "msgtype":"10"}],"retcode":"000000","retmsg":"OK"}' + */ + private void sendRobotMessage(String name, String content) { + Log.e("随机打招呼", name + "==========00000000000000++++" + content); + AiAutomaticSpeechModel aiAutomaticSpeechModel = new AiAutomaticSpeechModel(); + aiAutomaticSpeechModel.setAiName(name) + .setIcon("https://downs.yaoulive.com/xzs_tab.png") + .setNameColor("#f19ec2") + .setSystemBubble("https://downs.yaoulive.com/xzs_qipao.9.png") + .setUserName("") + .setContent(content); + SocketSendBean msg = + new SocketSendBean() + .param("_method_", "aiAutomaticSpeech") + .param("msgtype", "10") + .param("ct", GsonUtils.toJson(aiAutomaticSpeechModel, AiAutomaticSpeechModel.class)); + msg.create(); + String targetId = "g" + mLiveUid; + Conversation.ConversationType conversationType = Conversation.ConversationType.CHATROOM; + TextMessage messageContent = TextMessage.obtain(msg.mResult.toString()); + Message message = Message.obtain(targetId, conversationType, messageContent); + + RongIMClient.getInstance().sendMessage(message, null, null, new IRongCallback.ISendMessageCallback() { + @Override + public void onAttached(Message message) { + + } + + @Override + public void onSuccess(Message message) { + if (SocketRyClient.mSocketHandler != null) { + SocketRyClient.mSocketHandler.processBroadcast(msg.mResult.toString() + ""); + } + } + + @Override + public void onError(Message message, RongIMClient.ErrorCode errorCode) { + Log.e("tx", "aaa" + errorCode.toString()); + ToastUtil.show(errorCode.code + ":" + errorCode.msg); + } + }); + robotHandler.postDelayed(robotRunnable, robotTime); + } } diff --git a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java index c690ed6f2..8e5daccd3 100644 --- a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java +++ b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java @@ -255,7 +255,8 @@ public class LiveAudienceEvent extends BaseModel { DISCONNEXT_PK_TIME(50, "单人Pk结束"), UP_PK_TWO(51, "PK头像信息"), CUSTOM_FULL_SERVICE_NOTIFY(51, "全服通知"), - CHANGE_VIEW(52, "更改连胜位置"); + CHANGE_VIEW(52, "更改连胜位置"), + UPDATA_ROBOT(53, "更新机器人消息"); private int type; private String name; From 137dbc72d8e4c23a0f3fbdb326fe5ecc6fb316d7 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Wed, 28 Dec 2022 17:51:35 +0800 Subject: [PATCH 005/118] update --- config.gradle | 4 +- live/build.gradle | 2 +- .../live/views/LivePlayKsyViewHolder.java | 2 +- .../live/views/LivePlayRyViewHolder.java | 210 ++++++++++++++---- .../live/views/LivePlayTxViewHolder.java | 2 +- .../views/LivePlayTxViewHolder_backup.java | 2 +- .../live/views/LiveRoomPlayViewHolder.java | 9 +- .../yunbao/live/views/LiveRoomViewHolder.java | 7 +- .../live/views/PortraitLiveManager.java | 9 +- .../main/res/layout/view_live_play_ksy.xml | 2 +- 10 files changed, 194 insertions(+), 55 deletions(-) diff --git a/config.gradle b/config.gradle index 6f21be570..ac60b7e57 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", // 測試 -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/build.gradle b/live/build.gradle index f8dddcdbd..0329c0beb 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:2.0.0' implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) implementation (name:'../libs/beautysdk-202202241203',ext:'aar') implementation (name:'../libs/svgaplayer-release-v1.2.1',ext:'aar') //socket.io implementation('io.socket:socket.io-client:1.0.0') { exclude group: 'org.json', module: 'json' } //common api project(path: ':common') api project(path:':FaceUnity')//新娱美颜 annotationProcessor rootProject.ext.dependencies["arouter-compiler"] //工具 api rootProject.ext.dependencies["blank-utilcode"] implementation 'com.eightbitlab:blurview:1.6.6' 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']) implementation (name:'../libs/beautysdk-202202241203',ext:'aar') implementation (name:'../libs/svgaplayer-release-v1.2.1',ext:'aar') //socket.io implementation('io.socket:socket.io-client:1.0.0') { exclude group: 'org.json', module: 'json' } //common api project(path: ':common') api project(path:':FaceUnity')//新娱美颜 annotationProcessor rootProject.ext.dependencies["arouter-compiler"] //工具 api rootProject.ext.dependencies["blank-utilcode"] implementation 'com.eightbitlab:blurview:1.6.6' implementation 'com.google.code.gson:gson:2.8.6' implementation "com.getkeepsafe.relinker:relinker:1.4.4" //ExoPlayer,腾讯的播放器不支持无缝切换 implementation 'com.google.android.exoplayer:exoplayer:2.18.2' implementation 'com.google.android.exoplayer:exoplayer-core:2.18.2@aar' } \ No newline at end of file diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayKsyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayKsyViewHolder.java index 374978a99..b50a38d80 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayKsyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayKsyViewHolder.java @@ -128,7 +128,7 @@ public class LivePlayKsyViewHolder extends LiveRoomPlayViewHolder { * @param url 流地址 */ @Override - public void play(String url) { + public void play(String url,int playModel) { mPlayer = new V2TXLivePlayerImpl(mContext); if (TextUtils.isEmpty(url) || mVideoView == null) { diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 8d979b241..00994d59d 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -6,15 +6,14 @@ import static cn.rongcloud.rtc.core.RendererCommon.ScalingType.SCALE_ASPECT_FILL import android.Manifest; import android.app.Dialog; import android.content.Context; -import android.graphics.Bitmap; import android.graphics.Color; import android.media.AudioManager; -import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; import android.util.Log; import android.view.Gravity; +import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; @@ -23,19 +22,18 @@ import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; -import com.alibaba.fastjson.JSON; +import androidx.annotation.Nullable; + +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.Tracks; +import com.google.android.exoplayer2.video.VideoSize; import com.lzf.easyfloat.EasyFloat; -import com.lzy.okserver.OkDownload; -import com.lzy.okserver.download.DownloadTask; -import com.tencent.live2.V2TXLiveDef; -import com.tencent.live2.V2TXLivePlayer; -import com.tencent.live2.V2TXLivePlayerObserver; -import com.tencent.live2.impl.V2TXLivePlayerImpl; -import com.tencent.rtmp.ui.TXCloudVideoView; -import com.yunbao.common.bean.CrashSaveBean; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; -import com.yunbao.common.utils.DeviceUtils; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.L; @@ -56,7 +54,6 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; -import java.util.Map; import cn.rongcloud.rtc.api.RCRTCEngine; import cn.rongcloud.rtc.api.RCRTCRemoteUser; @@ -89,7 +86,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { private ViewGroup mLeftContainer; private ViewGroup mRightContainer; private RelativeLayout mPkContainer; - public static TXCloudVideoView mVideoView; + public static SurfaceView mVideoView; private View mLoading, mLoading2; private ImageView mCover; @@ -101,15 +98,16 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { private boolean mPausedPlay;//是否被动暂停了播放 public int landscape; //1h 2s public static Context contexts; - public V2TXLivePlayer mPlayer; public static FrameLayout ry_view; private static final int VIDEO_VERTICAL = 1; private static final int VIDEO_HORIZONTAL = 2; - int videoLandscape; // 视频方向,1=竖屏,2=横屏 + int videoLandscape = -1; // 视频方向,1=竖屏,2=横屏 static int vHeight;//视频高 private TextView debugView; + private ExoPlayer mPlayer, mPlayer2; + private boolean isPlayer = true; //0未申请1申请中2连麦中 @@ -141,7 +139,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { mLeftContainer = (ViewGroup) findViewById(R.id.left_container); mRightContainer = (ViewGroup) findViewById(R.id.right_container); mPkContainer = (RelativeLayout) findViewById(R.id.pk_container); - mVideoView = (TXCloudVideoView) findViewById(R.id.video_view); + mVideoView = (SurfaceView) findViewById(R.id.video_view); ry_view = (FrameLayout) findViewById(R.id.ry_view); leave = (ImageView) findViewById(R.id.leave); mLoading = findViewById(R.id.loading); @@ -154,9 +152,14 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mPkContainer.getLayoutParams(); params.height = vHeight; mPkContainer.requestLayout(); - mPlayer = new V2TXLivePlayerImpl(mContext); - mPlayer.setRenderView(mVideoView); + mPlayer = new ExoPlayer.Builder(mContext) + .build(); + mPlayer2 = new ExoPlayer.Builder(mContext).build(); + mPlayer.setVideoSurfaceView(mVideoView); + mPlayer2.setVideoSurfaceView(mVideoView); + mPlayer.addListener(new ExoPlayerListener(true)); + mPlayer2.addListener(new ExoPlayerListener(false)); debugView = new TextView(mContext); debugView.setBackgroundColor(Color.WHITE); @@ -247,13 +250,12 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { */ @Override public void resumePlay() { - if (mPlayer.isPlaying() != 1) { + if (!mPlayer.isPlaying()) { new Handler(Looper.getMainLooper()) .postDelayed(() -> { - mPlayer.stopPlay(); - int val = mPlayer.startPlay(purl); + mPlayer.stop(); + mPlayer.play(); // ToastUtil.show("强制播放" + val); - Log.i(TAG, "强制播放: " + val); }, 100); } } @@ -264,7 +266,14 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { * @param url 流地址 */ @Override - public void play(String url) { + public void play(String url, int playModel) { + if (playModel != PLAY_MODEL_DEF) { + if (videoLandscape == VIDEO_VERTICAL) { + url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); + } else if (videoLandscape == VIDEO_HORIZONTAL) { + url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); + } + } Log.e("purl121", url); if (TextUtils.isEmpty(url) || mVideoView == null) { @@ -275,16 +284,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (TextUtils.isEmpty(url) || mVideoView == null) { return; } - mVideoView.clearLastFrame(true); - mPlayer.setObserver(new V2TXLivePlayerObserver() { - String TAG = "播放流"; - @Override - public void onError(V2TXLivePlayer player, int code, String msg, Bundle extraInfo) { - super.onError(player, code, msg, extraInfo); - Log.i(TAG, "onError: player = " + player + ", code = " + code + ", msg = " + msg + ", extraInfo = " + extraInfo); - debugView.setText("播放出错code=" + code + " msg=" + msg); - } + /*mPlayer.setObserver(new V2TXLivePlayerObserver() { + + @Override public void onWarning(V2TXLivePlayer player, int code, String msg, Bundle extraInfo) { @@ -388,21 +391,55 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onReceiveSeiMessage(V2TXLivePlayer player, int payloadType, byte[] data) { super.onReceiveSeiMessage(player, payloadType, data); } - }); - + });*/ + MediaItem item = createMediaItem(url); + if (mPlayer.isPlaying()) { + ToastUtil.show("set 2"); + mPlayer2.setMediaItem(item); + mPlayer2.setVideoSurfaceView(mVideoView); + mPlayer2.prepare(); + mPlayer2.play(); + } else { + ToastUtil.show("set 1"); + mPlayer.setMediaItem(item); + mPlayer.setVideoSurfaceView(mVideoView); + mPlayer.prepare(); + mPlayer.play(); + } + /* if (mPlayer.isPlaying()) { + MediaSource nextSource = new ProgressiveMediaSource.Factory(new DefaultHttpDataSource.Factory()) + .createMediaSource(createMediaItem(url)); + MediaSource oldSource = new ProgressiveMediaSource.Factory(new DefaultHttpDataSource.Factory()) + .createMediaSource(mPlayer.getCurrentMediaItem()); + ClippingMediaSource clippingMediaSource = new ClippingMediaSource(oldSource, 0, 3000, false, true, true); + ConcatenatingMediaSource source = new ConcatenatingMediaSource(clippingMediaSource, nextSource); + mPlayer.addMediaSource(source); + mPlayer.prepare(); + mPlayer.setPlayWhenReady(true); + } else { + MediaItem item = createMediaItem(url); + mPlayer.setMediaItem(item); + mPlayer.prepare(); + mPlayer.play(); + }*/ purl = url; - int V2TXLiveCode = mPlayer.startPlay(url); onPrepared(); } + private MediaItem createMediaItem(String url) { + MediaItem mediaItem = MediaItem.fromUri(url); + return mediaItem; + } + @Override public void release() { mEnd = true; mStarted = false; if (mPlayer != null) { - mPlayer.stopPlay(); + mPlayer.stop(); + mPlayer.release(); } L.e(TAG, "release------->"); } @@ -416,7 +453,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } } if (mPlayer != null) { - mPlayer.stopPlay(); + mPlayer.stop(); } stopPlay2(); } @@ -629,7 +666,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { params.height = RelativeLayout.LayoutParams.MATCH_PARENT; params.topMargin = 0; params.addRule(RelativeLayout.ALIGN_TOP); - mPlayer.setRenderRotation(V2TXLiveDef.V2TXLiveRotation.V2TXLiveRotation270); + // mPlayer.setRenderRotation(V2TXLiveDef.V2TXLiveRotation.V2TXLiveRotation270); mVideoView.requestLayout(); } @@ -639,7 +676,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = vHeight; params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); - mPlayer.setRenderRotation(V2TXLiveDef.V2TXLiveRotation.V2TXLiveRotation0); + // mPlayer.setRenderRotation(V2TXLiveDef.V2TXLiveRotation.V2TXLiveRotation0); params.addRule(RelativeLayout.ALIGN_TOP); mVideoView.requestLayout(); } @@ -703,10 +740,13 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Log.e("ry", "退出多人房间成功"); new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { - mPlayer.startPlay(purl); + mPlayer.play(); Log.e("ry", mPlayer.isPlaying() + "purl" + purl); - if (mPlayer.isPlaying() != 1) { - mPlayer.startPlay(purl); + if (!mPlayer.isPlaying()) { + MediaItem item = createMediaItem(purl); + mPlayer.setMediaItem(item); + mPlayer.prepare(); + mPlayer.play(); } ry_view.removeAllViews(); ry_view.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; @@ -783,7 +823,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { for (RCRTCInputStream stream : data.getLiveStreams()) { if (stream.getMediaType() == RCRTCMediaType.VIDEO) { //暂停播放 - mPlayer.stopPlay(); + mPlayer.stop(); //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 @@ -1020,4 +1060,86 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } }); } + + protected void startPlay() { + if (mPlayer.isPlaying()) { + mPlayer.stop(); + mPlayer2.play(); + } else { + mPlayer2.stop(); + mPlayer.play(); + } + } + + private class ExoPlayerListener implements Player.Listener { + String TAG = "播放流"; + boolean isPlayer1; + + public ExoPlayerListener(boolean isPlayer1) { + this.isPlayer1 = isPlayer1; + } + + @Override + public void onPlaybackStateChanged(int playbackState) { + Player.Listener.super.onPlaybackStateChanged(playbackState); + if (playbackState == Player.STATE_READY) { + if (isPlayer1) { + mPlayer2.stop(); + Log.i(TAG, "onPlaybackStateChanged1: " + mPlayer.getCurrentMediaItem().localConfiguration.uri); + mPlayer.setVideoSurfaceView(mVideoView); + mPlayer.play(); + } else { + mPlayer.stop(); + Log.i(TAG, "onPlaybackStateChanged2: " + mPlayer2.getCurrentMediaItem().localConfiguration.uri); + mPlayer2.setVideoSurfaceView(mVideoView); + mPlayer2.play(); + } + + }else if (playbackState==Player.STATE_IDLE){ + if(!isPlayer1){ + mPlayer.stop(); + mPlayer2.prepare(); + }else{ + /* mPlayer2.stop(); + mPlayer.prepare();*/ + } + } + Log.i(TAG, "onPlaybackStateChanged: " + playbackState + " play = " + isPlayer1 + " p1 = " + mPlayer.isPlaying() + " p2 = " + mPlayer2.isPlaying()); + isPlayer = !isPlayer; + } + + @Override + public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) { + Player.Listener.super.onMediaItemTransition(mediaItem, reason); + Log.i(TAG, "onMediaItemTransition: " + reason); + } + + @Override + public void onPlayerError(PlaybackException error) { + Player.Listener.super.onPlayerError(error); + debugView.setText("播放出错code=" + error.errorCode + " msg=" + error.getErrorCodeName()); + } + + @Override + public void onVideoSizeChanged(VideoSize videoSize) { + Player.Listener.super.onVideoSizeChanged(videoSize); + if (videoSize.height > videoSize.width) { + videoLandscape = VIDEO_VERTICAL; + } else { + videoLandscape = VIDEO_HORIZONTAL; + } + } + + @Override + public void onTimelineChanged(Timeline timeline, int reason) { + Player.Listener.super.onTimelineChanged(timeline, reason); + Log.i(TAG, "onTimelineChanged: " + reason); + } + + @Override + public void onTracksChanged(Tracks tracks) { + Player.Listener.super.onTracksChanged(tracks); + Log.i(TAG, "onTracksChanged: " + tracks.getGroups().size()); + } + } } diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder.java index 9aef30b33..be84ebfa8 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder.java @@ -257,7 +257,7 @@ public class LivePlayTxViewHolder extends LiveRoomPlayViewHolder implements ITXL * @param url 流地址 */ @Override - public void play(String url) { + public void play(String url,int playModel) { url = "webrtc://5664.liveplay.myqcloud.com/live/5664_harchar1"; mPlayer = new V2TXLivePlayerImpl(mContext); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder_backup.java b/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder_backup.java index 2aaa2705e..9548eda7b 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder_backup.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder_backup.java @@ -251,7 +251,7 @@ public class LivePlayTxViewHolder_backup extends LiveRoomPlayViewHolder implemen * @param url 流地址 */ @Override - public void play(String url) { + public void play(String url,int playModel) { if (TextUtils.isEmpty(url)) { return; } diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index 32ad18a89..5ea00b74f 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -13,14 +13,21 @@ import com.yunbao.live.interfaces.ILiveLinkMicViewHolder; public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements ILiveLinkMicViewHolder { protected LiveBean mLiveBean; + public static final int PLAY_MODEL_DEF=-1; + public static final int PLAY_MODEL_480=0; + public static final int PLAY_MODEL_720=1; + public static final int PLAY_MODEL_1080=2; + public static final String[] videoRatioHorizontal = new String[]{"_640_480", "_960_720", "_1920_1080","_180_180"}; + public static final String[] videoRatioVertical = new String[]{"_480_640", "_720_960", "_1080_1920","_180_180"}; + public static final String[] videoFps = new String[]{"_24", "_30"}; OnMicCallback onMicCallback;//连麦回调 public LiveRoomPlayViewHolder(Context context, ViewGroup parentView) { super(context, parentView); } - public abstract void play(String url); + public abstract void play(String url,int playModel); public abstract void stopPlay(); diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 6fa9eaa4a..13075c098 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -837,7 +837,12 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mLiveUserAdapter.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(UserBean bean, int position) { - showUserDialog(bean.getId()); + if (position < 4) { + ToastUtil.show("切换:" + LiveRoomPlayViewHolder.videoRatioVertical[position]); + PortraitLiveManager.portraitLiveManager.test(position); + } else { + showUserDialog(bean.getId()); + } } }); mUserRecyclerView.setAdapter(mLiveUserAdapter); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 5fd7b77ae..b36d84d29 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -186,6 +186,8 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe private int landscape; private String leaveStream = "", leaveGroupId = ""; + public static PortraitLiveManager portraitLiveManager; + public PortraitLiveManager setQuitF(boolean quitF) { isQuitF = quitF; @@ -196,6 +198,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe this.mContext = context; this.mIntent = intent; liveImDeletUtil = new LiveImDeletUtil(); + portraitLiveManager=this; ininView(); } @@ -296,7 +299,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mask.setVisibility(View.VISIBLE); mLivePlayViewHolder.setLiveBean(mLiveBean); mLivePlayViewHolder.setCover(mLiveBean.getAvatar()); - mLivePlayViewHolder.play(mLiveBean.getPull()); + mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_DEF); mLivePlayViewHolder.setOnMicCallback(new LiveRoomPlayViewHolder.OnMicCallback() { @Override public void onMikUpdate() { @@ -326,7 +329,9 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe }); } - + public void test(int model) { + mLivePlayViewHolder.play(mLiveBean.getPull(), model); + } private Runnable sendFIm = new Runnable() { @Override public void run() { diff --git a/live/src/main/res/layout/view_live_play_ksy.xml b/live/src/main/res/layout/view_live_play_ksy.xml index b136c4bc5..6dc70080c 100644 --- a/live/src/main/res/layout/view_live_play_ksy.xml +++ b/live/src/main/res/layout/view_live_play_ksy.xml @@ -7,7 +7,7 @@ android:layout_height="match_parent"> - From 90f58054fa8944cd906fd6cb6df185f14928b9df Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Wed, 28 Dec 2022 18:21:00 +0800 Subject: [PATCH 006/118] =?UTF-8?q?=E6=9C=BA=E5=99=A8=E4=BA=BA=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=8F=91=E6=B6=88=E6=81=AF=E8=AE=BE=E7=BD=AE=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E4=BF=AE=E6=94=B9=EF=BC=8C=E6=9C=BA=E5=99=A8=E4=BA=BA?= =?UTF-8?q?=E6=B1=82=E5=85=B3=E6=B3=A8=E6=96=B0=E5=A2=9E=E5=8F=91=E9=80=81?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E7=B1=BB=E5=9E=8B=EF=BC=8C=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E5=BC=80=E6=92=AD=E6=B8=85=E6=99=B0=E5=BA=A6=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/common/Constants.java | 1 + .../common/bean/LiveStetUpStatusModel.java | 49 ++++++ .../com/yunbao/common/http/PDLiveApi.java | 10 +- .../yunbao/common/manager/IMLoginManager.java | 19 ++- .../yunbao/common/views/InputCustomPopup.java | 10 +- .../common/views/LiveClarityCustomPopup.java | 116 +++++++++++++++ .../views/LiveRobotMessageCustomPopup.java | 2 +- .../views/LiveRobotSayHelloCustomPopup.java | 2 +- .../common/views/RobotMessageViewHolder.java | 2 +- .../common/views/RobotSayHelloViewHoler.java | 2 +- .../main/res/drawable/bg_btn_definition.xml | 15 ++ .../main/res/layout/dialog_live_clarity.xml | 139 ++++++++++++++++++ .../src/main/res/mipmap-xxhdpi/icon_fhd.png | Bin 0 -> 1275 bytes common/src/main/res/mipmap-xxhdpi/icon_hd.png | Bin 0 -> 1285 bytes common/src/main/res/mipmap-xxhdpi/icon_sd.png | Bin 0 -> 1720 bytes .../main/res/mipmap-xxhdpi/icon_selected.png | Bin 0 -> 1473 bytes common/src/main/res/values/strings.xml | 4 + config.gradle | 4 +- .../live/activity/LiveRyAnchorActivity.java | 11 +- .../yunbao/live/socket/SocketRyClient.java | 1 + .../live/views/LiveNewReadyRyViewHolder.java | 90 +++++++++++- .../main/res/layout/view_new_live_ready.xml | 43 +++++- 22 files changed, 504 insertions(+), 16 deletions(-) create mode 100644 common/src/main/java/com/yunbao/common/bean/LiveStetUpStatusModel.java create mode 100644 common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java create mode 100644 common/src/main/res/drawable/bg_btn_definition.xml create mode 100644 common/src/main/res/layout/dialog_live_clarity.xml create mode 100644 common/src/main/res/mipmap-xxhdpi/icon_fhd.png create mode 100644 common/src/main/res/mipmap-xxhdpi/icon_hd.png create mode 100644 common/src/main/res/mipmap-xxhdpi/icon_sd.png create mode 100644 common/src/main/res/mipmap-xxhdpi/icon_selected.png diff --git a/common/src/main/java/com/yunbao/common/Constants.java b/common/src/main/java/com/yunbao/common/Constants.java index fabbf6967..3063290c0 100644 --- a/common/src/main/java/com/yunbao/common/Constants.java +++ b/common/src/main/java/com/yunbao/common/Constants.java @@ -172,6 +172,7 @@ public class Constants { public static final String RECOMMEND_CARD_NOTIFY = "recommendCardNotify";//推荐卡通知消息 public static final String STAR_CHALLENGE_UPDATE = "starChallengeUpdate";//星级助力 public static final String AI_AUTOMATIC_SPEECH = "aiAutomaticSpeech";//机器人助手 + public static final String AI_AUTOMATIC_SPEECH_LIVE = "aiAutomaticSpeechNew";//机器人助手 public static final String STAR_CHALLENGE_UPGRADE_NOTIFY = "starChallengeUpgradeNotify";//星级挑战成功 public static final String SUPER_VISION = "supervision";//超级发言警告 public static final String PK_RANK_UPDATE = "RankingRankUpdate";//PK排位赛更新数据 diff --git a/common/src/main/java/com/yunbao/common/bean/LiveStetUpStatusModel.java b/common/src/main/java/com/yunbao/common/bean/LiveStetUpStatusModel.java new file mode 100644 index 000000000..a4a98aa0d --- /dev/null +++ b/common/src/main/java/com/yunbao/common/bean/LiveStetUpStatusModel.java @@ -0,0 +1,49 @@ +package com.yunbao.common.bean; + +import android.text.TextUtils; + +import com.google.gson.annotations.SerializedName; + +public class LiveStetUpStatusModel extends BaseModel { + + @SerializedName("wishList") + private String wishList; + @SerializedName("ai_state") + private String aiState; + + /** + * wishList 1设置 0 未设置 + * + * @return + */ + public boolean getWishListState() { + return TextUtils.equals(wishList, "1"); + } + + /** + * aiState 1打开机器人 0 未设置 + * + * @return + */ + public boolean getAiStateState() { + return TextUtils.equals(aiState, "1"); + } + + public String getWishList() { + return wishList; + } + + public LiveStetUpStatusModel setWishList(String wishList) { + this.wishList = wishList; + return this; + } + + public String getAiState() { + return aiState; + } + + public LiveStetUpStatusModel setAiState(String aiState) { + this.aiState = aiState; + return this; + } +} diff --git a/common/src/main/java/com/yunbao/common/http/PDLiveApi.java b/common/src/main/java/com/yunbao/common/http/PDLiveApi.java index 1edb1f6ca..50fd3d6a0 100644 --- a/common/src/main/java/com/yunbao/common/http/PDLiveApi.java +++ b/common/src/main/java/com/yunbao/common/http/PDLiveApi.java @@ -15,6 +15,7 @@ import com.yunbao.common.bean.LinkMicUserBeanV2; import com.yunbao.common.bean.LiveAiRobotBean; import com.yunbao.common.bean.LiveInfoModel; import com.yunbao.common.bean.LiveRoomActivityBanner; +import com.yunbao.common.bean.LiveStetUpStatusModel; import com.yunbao.common.bean.MsgSwitchDetailModel; import com.yunbao.common.bean.NewPeopleInfo; import com.yunbao.common.bean.NobleRankHideUserListModel; @@ -522,11 +523,18 @@ public interface PDLiveApi { /** * 机器人修改话术 */ - @GET("/api/public/?service=Live.updateAiAutomaticSpeech ") + @GET("/api/public/?service=Live.updateAiAutomaticSpeech") Observable>> updateAiAutomaticSpeech( @Query("type") String type, @Query("id") String id, @Query("content") String content ); + /** + * 开播获取机器人状态和心愿单状态 + */ + @GET("/api/public/?service=Live.getLiveStetUpStatus") + Observable> getLiveStetUpStatus( + @Query("liveuid") String liveUid + ); } 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 edd422440..cb0e8a0c6 100644 --- a/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java +++ b/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java @@ -7,7 +7,6 @@ import android.text.TextUtils; import androidx.annotation.NonNull; -import com.cosmos.baseutil.app.AppContext; import com.google.gson.Gson; import com.lzf.easyfloat.EasyFloat; import com.yunbao.common.CommonAppContext; @@ -39,7 +38,25 @@ public class IMLoginManager extends BaseCacheManager { private final String IS_FLOAT = "is_float"; private final String IS_HINT = "is_hint"; private final String IS_HINT2 = "is_hint2"; + private final String SELECT_CLARITY = "selectClarity"; + /** + * 设置清晰度 + * + * @param selectClarity + */ + public void setSelectClarity(int selectClarity) { + put(SELECT_CLARITY, selectClarity); + } + + /** + * 获取清晰度 + * + * @return + */ + public int getSelectClarity() { + return getInt(SELECT_CLARITY, 1); + } public boolean isHint() { return 1 == getInt(IS_HINT, 0); diff --git a/common/src/main/java/com/yunbao/common/views/InputCustomPopup.java b/common/src/main/java/com/yunbao/common/views/InputCustomPopup.java index 8ad8f995a..25a8e22da 100644 --- a/common/src/main/java/com/yunbao/common/views/InputCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/InputCustomPopup.java @@ -4,6 +4,7 @@ import android.content.Context; import android.text.TextUtils; import android.view.View; import android.widget.EditText; +import android.widget.TextView; import androidx.annotation.NonNull; @@ -17,14 +18,17 @@ import com.yunbao.common.utils.ToastUtil; */ public class InputCustomPopup extends CenterPopupView { private String message = ""; + private int title = R.string.dialog_tip; - public InputCustomPopup(@NonNull Context context, String message) { + public InputCustomPopup(@NonNull Context context, String message, int title) { super(context); this.message = message; + this.title = title; } - public InputCustomPopup(@NonNull Context context) { + public InputCustomPopup(@NonNull Context context,int title) { super(context); + this.title = title; } // 返回自定义弹窗的布局 @@ -38,7 +42,9 @@ public class InputCustomPopup extends CenterPopupView { protected void onCreate() { super.onCreate(); EditText content = findViewById(R.id.content); + TextView titleText = findViewById(R.id.title); content.setText(message); + titleText.setText(title); findViewById(R.id.btn_cancel).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java new file mode 100644 index 000000000..13ec97ca9 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -0,0 +1,116 @@ +package com.yunbao.common.views; + +import android.content.Context; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import androidx.annotation.NonNull; + +import com.lxj.xpopup.core.BottomPopupView; +import com.yunbao.common.R; +import com.yunbao.common.views.weight.ViewClicksAntiShake; + +public class LiveClarityCustomPopup extends BottomPopupView implements View.OnClickListener { + private int selectClarity = 1; + private RelativeLayout lineSd, lineHd, lineFhd; + private ImageView iconSd, iconHd, iconFhd; + + public int getSelectClarity() { + return selectClarity; + } + + public LiveClarityCustomPopup(@NonNull Context context, int selectClarity) { + super(context); + this.selectClarity = selectClarity; + } + + public LiveClarityCustomPopup(@NonNull Context context) { + super(context); + } + + @Override + public void onClick(View v) { + + } + + // 返回自定义弹窗的布局 + @Override + protected int getImplLayoutId() { + return R.layout.dialog_live_clarity; + } + + // 执行初始化操作,比如:findView,设置点击,或者任何你弹窗内的业务逻辑 + @Override + protected void onCreate() { + super.onCreate(); + initView(); + initDate(); + } + + private void initView() { + lineSd = findViewById(R.id.line_sd); + lineHd = findViewById(R.id.line_hd); + lineFhd = findViewById(R.id.line_fhd); + iconSd = findViewById(R.id.icon_sd); + iconHd = findViewById(R.id.icon_hd); + iconFhd = findViewById(R.id.icon_fhd); + selectClarity(selectClarity); + //流畅 + ViewClicksAntiShake.clicksAntiShake(lineSd, () -> { + selectClarity = 0; + selectClarity(selectClarity); + dismiss(); + }); + //高清 + ViewClicksAntiShake.clicksAntiShake(lineHd, () -> { + selectClarity = 1; + selectClarity(selectClarity); + dismiss(); + + }); + //超高清 + ViewClicksAntiShake.clicksAntiShake(lineFhd, () -> { + selectClarity = 2; + selectClarity(selectClarity); + dismiss(); + }); + } + + /** + * 状态选择 + * + * @param selectClarity + */ + private void selectClarity(int selectClarity) { + switch (selectClarity) { + case 0: + lineSd.setSelected(true); + lineHd.setSelected(false); + lineFhd.setSelected(false); + iconSd.setVisibility(VISIBLE); + iconHd.setVisibility(GONE); + iconFhd.setVisibility(GONE); + break; + case 1: + lineSd.setSelected(false); + lineHd.setSelected(true); + lineFhd.setSelected(false); + iconSd.setVisibility(GONE); + iconHd.setVisibility(VISIBLE); + iconFhd.setVisibility(GONE); + break; + case 2: + lineSd.setSelected(false); + lineHd.setSelected(false); + lineFhd.setSelected(true); + iconSd.setVisibility(GONE); + iconHd.setVisibility(GONE); + iconFhd.setVisibility(VISIBLE); + break; + } + } + + private void initDate() { + } +} diff --git a/common/src/main/java/com/yunbao/common/views/LiveRobotMessageCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveRobotMessageCustomPopup.java index 953e9c7fe..f4652a3d6 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveRobotMessageCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveRobotMessageCustomPopup.java @@ -136,7 +136,7 @@ public class LiveRobotMessageCustomPopup extends BottomPopupView { @Override public void onClick(View v) { new XPopup.Builder(getContext()) - .asCustom(new InputCustomPopup(getContext()).setListener(new InputCustomPopup.InputCustomListener() { + .asCustom(new InputCustomPopup(getContext(),R.string.automatic_message_sending).setListener(new InputCustomPopup.InputCustomListener() { @Override public void onConfirm(String text) { //添加消息语 diff --git a/common/src/main/java/com/yunbao/common/views/LiveRobotSayHelloCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveRobotSayHelloCustomPopup.java index 93e61f37c..a76fcadef 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveRobotSayHelloCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveRobotSayHelloCustomPopup.java @@ -82,7 +82,7 @@ public class LiveRobotSayHelloCustomPopup extends BottomPopupView { @Override public void onClick(View v) { new XPopup.Builder(getContext()) - .asCustom(new InputCustomPopup(getContext()).setListener(new InputCustomPopup.InputCustomListener() { + .asCustom(new InputCustomPopup(getContext(), R.string.automatic_greeting_setting).setListener(new InputCustomPopup.InputCustomListener() { @Override public void onConfirm(String text) { //添加消息语 diff --git a/common/src/main/java/com/yunbao/common/views/RobotMessageViewHolder.java b/common/src/main/java/com/yunbao/common/views/RobotMessageViewHolder.java index f182a0c12..c14de79f2 100644 --- a/common/src/main/java/com/yunbao/common/views/RobotMessageViewHolder.java +++ b/common/src/main/java/com/yunbao/common/views/RobotMessageViewHolder.java @@ -53,7 +53,7 @@ public class RobotMessageViewHolder extends RecyclerView.ViewHolder { @Override public void onClick(View v) { new XPopup.Builder(itemView.getContext()) - .asCustom(new InputCustomPopup(itemView.getContext(), message.getContent()).setListener(new InputCustomPopup.InputCustomListener() { + .asCustom(new InputCustomPopup(itemView.getContext(), message.getContent(), R.string.automatic_message_sending).setListener(new InputCustomPopup.InputCustomListener() { @Override public void onConfirm(String text) { LiveNetManager.get(itemView.getContext()) diff --git a/common/src/main/java/com/yunbao/common/views/RobotSayHelloViewHoler.java b/common/src/main/java/com/yunbao/common/views/RobotSayHelloViewHoler.java index 359f7ba1a..75ee2e293 100644 --- a/common/src/main/java/com/yunbao/common/views/RobotSayHelloViewHoler.java +++ b/common/src/main/java/com/yunbao/common/views/RobotSayHelloViewHoler.java @@ -53,7 +53,7 @@ public class RobotSayHelloViewHoler extends RecyclerView.ViewHolder { @Override public void onClick(View v) { new XPopup.Builder(itemView.getContext()) - .asCustom(new InputCustomPopup(itemView.getContext(), message.getContent()).setListener(new InputCustomPopup.InputCustomListener() { + .asCustom(new InputCustomPopup(itemView.getContext(), message.getContent(), R.string.automatic_greeting_setting).setListener(new InputCustomPopup.InputCustomListener() { @Override public void onConfirm(String text) { LiveNetManager.get(itemView.getContext()) diff --git a/common/src/main/res/drawable/bg_btn_definition.xml b/common/src/main/res/drawable/bg_btn_definition.xml new file mode 100644 index 000000000..f4a1222ee --- /dev/null +++ b/common/src/main/res/drawable/bg_btn_definition.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/layout/dialog_live_clarity.xml b/common/src/main/res/layout/dialog_live_clarity.xml new file mode 100644 index 000000000..35fd83425 --- /dev/null +++ b/common/src/main/res/layout/dialog_live_clarity.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/mipmap-xxhdpi/icon_fhd.png b/common/src/main/res/mipmap-xxhdpi/icon_fhd.png new file mode 100644 index 0000000000000000000000000000000000000000..278b37842e1da0a98df9e5ae76eab15d6f44a8d2 GIT binary patch literal 1275 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 A?f?J) literal 0 HcmV?d00001 diff --git a/common/src/main/res/mipmap-xxhdpi/icon_selected.png b/common/src/main/res/mipmap-xxhdpi/icon_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..5aeea828a91492a08bddd2b1cdbaed6997f9f0bd GIT binary patch literal 1473 zcmV;y1wQ(TP)Px)dr3q=RA@upn_FxYWfXwFv)dL*OB-$?DoPicUO3=y4G~c{ zx?KV4@72Y0Tx|g6yHT2jH9ILSTqIKu{o`cI5l};wlc0MSs`ol6%j*9{euIK}5^On< z$ZkSF6HdGLf!>x?=Up3_t#Qch+(39^CrgIc#S2$kK=VKe1wJ1_ z-#Mo}-AS02wot$}^0$dq=gCabP+&Q#^`4x_l#s6wDmOxDoxO!Cd*JY5 zXX_#>L_?D|qLHP}tFyGiUksI-p=5@=!M}e1WB0V%*&*?55^W6Z0iET%ItwfOB~ZNu zito2KW`yJ)%Rt?B6J@VxsH_cTk|*~i4>asaG)5?IG*oYeqAGiRm%fCf%Yh{N!ompy z@KVwV-Z`j{n>QCsQboEkF+;I`KugYnlC1bqhJX%-XqOx7+JE^8uWG*W1qZN?9T5;gB)% z)U?l_XsS2J5f#>fl0Vj7{!~4j{V+8+GenI;#%r3$E46l@C{71I-cA-xgQ_i%Kgu59 z#2Pr)cVA5r(o7R6B>H3_iywfhk0Gxl)^SzqFuAZTMW}w_!p77~HMfu@Gp!26Ut|Lp zvC_a_JJJVdouVs5_XlPW*8M4Ic7nY0HH>-`{KIYF!d3!r|0*RHY=zBY+v=pHeqC~c zwDTa+4M(4Mz7=>u@4YS=vT3{UCIe|yKt|DgyO6ng;WYu%*|Km0+4CQ?JOiB} z7mj*d64kOuche~mWVj1jmO$45kDj{_8`yL*cd;?eZ9_ZAa0eWE8vZ@#!pl^a3}_o# zfEj4~`bWauFGFb%uC~I-b#SdM70;bz<28OQ$Q*9nn}E6g^2JISIsE#pH^4QQUw~Sn zn&YpqO~_mxLbw&GIXp%Z1(~aZKz)$8Jj&Gvnajg?{p+Kg9jAowh4I&SNRH0gt_-6%j1oSYfKM|bX>}4)H b(H-i4>yU9mdps*^00000NkvXXu0mjf+Q!A` literal 0 HcmV?d00001 diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index b0b723181..7371b9465 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -996,4 +996,8 @@ 當有用戶進入直播間時,機器人會@該用戶並自動 隨機以下一句話。最少設置1條,最多20條。 機器人設置 + 高清 + 流暢 + 超高清 + 確定清晰度開播後,需要重新開播才能更改 diff --git a/config.gradle b/config.gradle index 6f21be570..ac60b7e57 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", // 測試 -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index 6e02d0be9..8a1dc02df 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -918,6 +918,10 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl LiveHttpUtil.stopLive(mStream, new HttpCallback() { @Override public void onSuccess(int code, String msg, String[] info) { + if (robotRunnable != null) { + robotHandler.removeCallbacks(robotRunnable); + robotRunnable = null; + } if (code == 0) { JSONObject obj = JSON.parseObject(info[0]); JSONObject datas = obj.getJSONObject("data"); @@ -1622,7 +1626,10 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl @Override public void onSuccess(List messageList) { Random random = new Random(); - int randNumber = random.nextInt(messageList.size() - 1) - 1; + int randNumber = random.nextInt(messageList.size()) - 1; + if (randNumber < 0) { + randNumber = 0; + } Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((data.randNumber())" + randNumber); Log.e("随机打招呼", "(((((((((((((((((((((((((((((((((((((((((((((((data)" + messageList.toString()); sendRobotMessage(robotName, messageList.get(randNumber).getContent()); @@ -1673,7 +1680,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl .setContent(content); SocketSendBean msg = new SocketSendBean() - .param("_method_", "aiAutomaticSpeech") + .param("_method_", "aiAutomaticSpeechNew") .param("msgtype", "10") .param("ct", GsonUtils.toJson(aiAutomaticSpeechModel, AiAutomaticSpeechModel.class)); msg.create(); diff --git a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java index ce6ea69f5..b2685d167 100644 --- a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java +++ b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java @@ -529,6 +529,7 @@ public class SocketRyClient { } break; case Constants.AI_AUTOMATIC_SPEECH: + case Constants.AI_AUTOMATIC_SPEECH_LIVE: //{"name_color":"#f19ec2","ai_name":"助手小小P","content":"@1 ","user_name":"1","icon":"https://downs.yaoulive.com/xzs_tab.png","system_bubble":"https://downs.yaoulive.com/xzs_qipao.9.png"} AiAutomaticSpeechModel aiAutomaticSpeechModel = GsonUtils.fromJson(map.getString("ct"), AiAutomaticSpeechModel.class); Bus.get().post(new LiveAudienceEvent() diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index 57be40428..019a85805 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -11,12 +11,15 @@ import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import android.widget.ImageView; import android.widget.TextView; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.ContextCompat; import com.lxj.xpopup.XPopup; +import com.lxj.xpopup.core.BasePopupView; +import com.lxj.xpopup.interfaces.XPopupCallback; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.Constants; import com.yunbao.common.bean.LiveClassBean; @@ -25,6 +28,7 @@ import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.ImageResultCallback; +import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.L; import com.yunbao.common.utils.ProcessImageUtil; @@ -32,7 +36,9 @@ import com.yunbao.common.utils.StringUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.WordUtil; import com.yunbao.common.views.AbsViewHolder; +import com.yunbao.common.views.LiveClarityCustomPopup; import com.yunbao.common.views.LiveRobotSettingCustomPopup; +import com.yunbao.common.views.weight.ViewClicksAntiShake; import com.yunbao.faceunity.FaceManager; import com.yunbao.live.R; import com.yunbao.live.activity.LiveActivity; @@ -59,7 +65,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl private ProcessImageUtil mImageUtil; private File mAvatarFile; private TextView mLiveClass; - private TextView mLiveTypeTextView;//房间类型TextView + private TextView mLiveTypeTextView, liveClarity;//房间类型TextView private TextView mLiveWishListTextView;//心愿单TextView private int mLiveClassID;//直播频道id private int mLiveType;//房间类型 @@ -70,6 +76,8 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl private LiveClassBean classBean; private FaceManager manager; private TextView faceTextView;//提示人脸未检测到的TextView + private ImageView imgClarity; + private int selectClarity = 1; public LiveNewReadyRyViewHolder(Context context, ViewGroup parentView, int liveSdk) { super(context, parentView, liveSdk); @@ -90,6 +98,8 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl @Override public void init() { mRootView = (ConstraintLayout) findViewById(R.id.traceroute_rootview); + imgClarity = (ImageView) findViewById(R.id.img_clarity); + liveClarity = (TextView) findViewById(R.id.live_clarity); mRootView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -163,6 +173,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl findViewById(R.id.btn_start_live).setOnClickListener(this); findViewById(R.id.btn_wishlist).setOnClickListener(this); findViewById(R.id.btn_horizontally).setOnClickListener(this); + if (manager != null) { manager.setFaceStatusChanged(new FaceManager.FaceStatusChanged() { final Handler handler = new Handler(Looper.getMainLooper()); @@ -180,6 +191,83 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl }); //新美颜 setFaceUnity(true); + + } + //设置清晰度 + selectClarity = IMLoginManager.get(mContext).getSelectClarity(); + setSelectClarity(selectClarity); + ViewClicksAntiShake + .clicksAntiShake( + findViewById(R.id.btn_live_clarity), () -> { + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, selectClarity); + new XPopup.Builder(mContext) + .setPopupCallback(new XPopupCallback() { + @Override + public void onCreated(BasePopupView popupView) { + + } + + @Override + public void beforeShow(BasePopupView popupView) { + + } + + @Override + public void onShow(BasePopupView popupView) { + + } + + @Override + public void onDismiss(BasePopupView popupView) { + setSelectClarity(liveClarityCustomPopup.getSelectClarity()); + } + + @Override + public void beforeDismiss(BasePopupView popupView) { + + } + + @Override + public boolean onBackPressed(BasePopupView popupView) { + return false; + } + + @Override + public void onKeyBoardStateChanged(BasePopupView popupView, int height) { + + } + + @Override + public void onDrag(BasePopupView popupView, int value, float percent, boolean upOrLeft) { + + } + + @Override + public void onClickOutside(BasePopupView popupView) { + + } + }) + .asCustom(liveClarityCustomPopup) + .show(); + }); + } + + private void setSelectClarity(int selectClarity) { + this.selectClarity = selectClarity; + IMLoginManager.get(mContext).setSelectClarity(selectClarity); + switch (selectClarity) { + case 0: + imgClarity.setImageResource(R.mipmap.icon_sd); + liveClarity.setText(R.string.standard_clear); + break; + case 1: + imgClarity.setImageResource(R.mipmap.icon_hd); + liveClarity.setText(R.string.high_definition); + break; + case 2: + imgClarity.setImageResource(R.mipmap.icon_fhd); + liveClarity.setText(R.string.ultra_hd); + break; } } diff --git a/live/src/main/res/layout/view_new_live_ready.xml b/live/src/main/res/layout/view_new_live_ready.xml index 98af6cebf..eadb2a80c 100644 --- a/live/src/main/res/layout/view_new_live_ready.xml +++ b/live/src/main/res/layout/view_new_live_ready.xml @@ -54,6 +54,43 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> + + + + + + + + + Date: Thu, 29 Dec 2022 11:01:23 +0800 Subject: [PATCH 007/118] =?UTF-8?q?update=20=E6=B8=85=E6=99=B0=E5=BA=A6?= =?UTF-8?q?=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/common/utils/DialogUitl.java | 8 +- .../live/utils/LiveExoPlayerManager.java | 170 ++++++++++++++++++ .../live/views/LivePlayRyViewHolder.java | 119 +++++------- .../live/views/LiveRoomPlayViewHolder.java | 17 +- 4 files changed, 227 insertions(+), 87 deletions(-) create mode 100644 live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java diff --git a/common/src/main/java/com/yunbao/common/utils/DialogUitl.java b/common/src/main/java/com/yunbao/common/utils/DialogUitl.java index 9ddea94c3..b53f0258b 100644 --- a/common/src/main/java/com/yunbao/common/utils/DialogUitl.java +++ b/common/src/main/java/com/yunbao/common/utils/DialogUitl.java @@ -494,8 +494,12 @@ public class DialogUitl { } } }; - btnConfirm.setOnClickListener(listener); - btnCancel.setOnClickListener(listener); + if(btnConfirm!=null) { + btnConfirm.setOnClickListener(listener); + } + if(btnCancel!=null) { + btnCancel.setOnClickListener(listener); + } dialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialogInterface) { diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java new file mode 100644 index 000000000..2ccc0d15e --- /dev/null +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -0,0 +1,170 @@ +package com.yunbao.live.utils; + +import android.content.Context; +import android.util.Log; +import android.view.SurfaceView; + +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.video.VideoSize; + +public class LiveExoPlayerManager { + private final int MODEL_PLAY1 = 0; + private final int MODEL_PLAY2 = 1; + private Context mContext; + private ExoPlayer player1, player2; + private SurfaceView mainView; + private int status = MODEL_PLAY1; + private Player.Listener listener; + private boolean isSwitchUrl = false; + private String TAG = "播放"; + + public LiveExoPlayerManager(Context mContext) { + this.mContext = mContext; + player1 = new ExoPlayer.Builder(mContext).build(); + player2 = new ExoPlayer.Builder(mContext).build(); + player1.addListener(new Player.Listener() { + @Override + public void onPlaybackStateChanged(int playbackState) { + Player.Listener.super.onPlaybackStateChanged(playbackState); + Log.i(TAG, "onPlaybackStateChanged 1: " + playbackState); + if (playbackState == Player.STATE_READY) { + player2.stop(); + player2.setVideoSurface(null); + player1.play(); + Log.i(TAG, "切换播放器1"); + } else if (playbackState == Player.STATE_BUFFERING && status == MODEL_PLAY1 && !isSwitchUrl) { + if (listener != null) { + listener.onPlaybackStateChanged(playbackState); + } + } + } + + @Override + public void onIsPlayingChanged(boolean isPlaying) { + Player.Listener.super.onIsPlayingChanged(isPlaying); + if (isPlaying) { + Log.i(TAG, "onIsPlayingChanged1: 播放了"); + player1.setVideoSurfaceView(mainView); + status = MODEL_PLAY1; + isSwitchUrl = false; + if (listener != null) { + listener.onIsPlayingChanged(true); + } + } + } + + @Override + public void onVideoSizeChanged(VideoSize videoSize) { + Player.Listener.super.onVideoSizeChanged(videoSize); + if (listener != null) { + listener.onVideoSizeChanged(videoSize); + } + } + + @Override + public void onIsLoadingChanged(boolean isLoading) { + Player.Listener.super.onIsLoadingChanged(isLoading); + Log.i(TAG, "onIsLoadingChanged: 1 " + isLoading); + } + }); + + player2.addListener(new Player.Listener() { + @Override + public void onPlaybackStateChanged(int playbackState) { + Player.Listener.super.onPlaybackStateChanged(playbackState); + Log.i(TAG, "onPlaybackStateChanged 2: " + playbackState); + if (playbackState == Player.STATE_READY) { + player1.stop(); + player1.setVideoSurface(null); + player2.play(); + Log.i(TAG, "切换播放器2 " + player2.isPlaying()); + } else if (playbackState == Player.STATE_BUFFERING && status == MODEL_PLAY2 && !isSwitchUrl) { + if (listener != null) { + listener.onPlaybackStateChanged(playbackState); + } + } + } + + @Override + public void onIsPlayingChanged(boolean isPlaying) { + Player.Listener.super.onIsPlayingChanged(isPlaying); + if (isPlaying) { + Log.i(TAG, "onIsPlayingChanged2: 播放了"); + player2.setVideoSurfaceView(mainView); + status = MODEL_PLAY2; + isSwitchUrl = false; + if (listener != null) { + listener.onIsPlayingChanged(true); + } + } + } + + @Override + public void onVideoSizeChanged(VideoSize videoSize) { + Player.Listener.super.onVideoSizeChanged(videoSize); + if (listener != null) { + listener.onVideoSizeChanged(videoSize); + } + } + + @Override + public void onIsLoadingChanged(boolean isLoading) { + Player.Listener.super.onIsLoadingChanged(isLoading); + Log.i(TAG, "onIsLoadingChanged: 2 " + isLoading); + } + }); + } + + public void setListener(Player.Listener listener) { + this.listener = listener; + } + + public void setMainView(SurfaceView mainView) { + this.mainView = mainView; + } + + public void startUrl(String url) { + isSwitchUrl = true; + getNowPlayer().setVideoSurfaceView(mainView); + getNowPlayer().setMediaItem(createMediaItem(url)); + getNowPlayer().prepare(); + getNowPlayer().play(); + } + + public void switchUrl(String url) { + isSwitchUrl = true; + getNextPlayer().setMediaItem(createMediaItem(url)); + getNextPlayer().prepare(); + } + + private MediaItem createMediaItem(String url) { + return MediaItem.fromUri(url); + } + + public ExoPlayer getNowPlayer() { + return status == MODEL_PLAY1 ? player1 : player2; + } + + private ExoPlayer getNextPlayer() { + return status == MODEL_PLAY1 ? player2 : player1; + } + + public boolean isPlaying() { + return getNowPlayer().isPlaying(); + } + + public void stop() { + getNowPlayer().stop(); + } + + public void play() { + getNowPlayer().play(); + } + + public void release() { + player1.release(); + player2.release(); + } +} diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 00994d59d..4e2e01176 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -24,7 +24,6 @@ import android.widget.TextView; import androidx.annotation.Nullable; -import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; @@ -44,6 +43,7 @@ import com.yunbao.common.utils.WordUtil; import com.yunbao.live.R; import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveAudienceActivity; +import com.yunbao.live.utils.LiveExoPlayerManager; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -106,13 +106,11 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { static int vHeight;//视频高 private TextView debugView; - private ExoPlayer mPlayer, mPlayer2; - private boolean isPlayer = true; - + private LiveExoPlayerManager mPlayer; //0未申请1申请中2连麦中 RCRTCRoom rcrtcRoom; - String purl; + String purl, srcUrl; public int getLandscape() { return landscape; @@ -153,13 +151,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { params.height = vHeight; mPkContainer.requestLayout(); - mPlayer = new ExoPlayer.Builder(mContext) - .build(); - mPlayer2 = new ExoPlayer.Builder(mContext).build(); - mPlayer.setVideoSurfaceView(mVideoView); - mPlayer2.setVideoSurfaceView(mVideoView); - mPlayer.addListener(new ExoPlayerListener(true)); - mPlayer2.addListener(new ExoPlayerListener(false)); + mPlayer = new LiveExoPlayerManager(mContext); + mPlayer.setMainView(mVideoView); + mPlayer.setListener(new ExoPlayerListener()); debugView = new TextView(mContext); debugView.setBackgroundColor(Color.WHITE); @@ -267,6 +261,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { */ @Override public void play(String url, int playModel) { + srcUrl = url; + PLAY_MODEL = playModel; if (playModel != PLAY_MODEL_DEF) { if (videoLandscape == VIDEO_VERTICAL) { url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); @@ -395,16 +391,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { MediaItem item = createMediaItem(url); if (mPlayer.isPlaying()) { ToastUtil.show("set 2"); - mPlayer2.setMediaItem(item); - mPlayer2.setVideoSurfaceView(mVideoView); - mPlayer2.prepare(); - mPlayer2.play(); + mPlayer.switchUrl(url); } else { ToastUtil.show("set 1"); - mPlayer.setMediaItem(item); - mPlayer.setVideoSurfaceView(mVideoView); - mPlayer.prepare(); - mPlayer.play(); + mPlayer.startUrl(url); } /* if (mPlayer.isPlaying()) { MediaSource nextSource = new ProgressiveMediaSource.Factory(new DefaultHttpDataSource.Factory()) @@ -743,10 +733,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { mPlayer.play(); Log.e("ry", mPlayer.isPlaying() + "purl" + purl); if (!mPlayer.isPlaying()) { - MediaItem item = createMediaItem(purl); - mPlayer.setMediaItem(item); - mPlayer.prepare(); - mPlayer.play(); + mPlayer.switchUrl(purl); } ry_view.removeAllViews(); ry_view.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; @@ -1061,58 +1048,31 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { }); } - protected void startPlay() { - if (mPlayer.isPlaying()) { - mPlayer.stop(); - mPlayer2.play(); - } else { - mPlayer2.stop(); - mPlayer.play(); + private void showLoadingDialog() { + if (PLAY_MODEL == PLAY_MODEL_480) return; + + new DialogUitl.Builder(mContext) + .setTitle("網絡提示") + .setContent("系統監測到您的網絡不穩定,對此將清晰度變成了流暢,您可以在側邊菜單中的「清晰度」選擇調回。") + .setView(R.layout.dialog_simple_tip) + .setClickCallback(new DialogUitl.SimpleCallback() { + @Override + public void onConfirmClick(Dialog dialog, String content) { + dialog.dismiss(); + } + }).build().show(); + PLAY_MODEL = PLAY_MODEL_480; + String url = srcUrl; + if (videoLandscape == VIDEO_VERTICAL) { + url = url.replace(".flv", videoRatioVertical[PLAY_MODEL_480] + videoFps[0] + ".flv"); + } else if (videoLandscape == VIDEO_HORIZONTAL) { + url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL_480] + videoFps[0] + ".flv"); } + mPlayer.switchUrl(url); } private class ExoPlayerListener implements Player.Listener { String TAG = "播放流"; - boolean isPlayer1; - - public ExoPlayerListener(boolean isPlayer1) { - this.isPlayer1 = isPlayer1; - } - - @Override - public void onPlaybackStateChanged(int playbackState) { - Player.Listener.super.onPlaybackStateChanged(playbackState); - if (playbackState == Player.STATE_READY) { - if (isPlayer1) { - mPlayer2.stop(); - Log.i(TAG, "onPlaybackStateChanged1: " + mPlayer.getCurrentMediaItem().localConfiguration.uri); - mPlayer.setVideoSurfaceView(mVideoView); - mPlayer.play(); - } else { - mPlayer.stop(); - Log.i(TAG, "onPlaybackStateChanged2: " + mPlayer2.getCurrentMediaItem().localConfiguration.uri); - mPlayer2.setVideoSurfaceView(mVideoView); - mPlayer2.play(); - } - - }else if (playbackState==Player.STATE_IDLE){ - if(!isPlayer1){ - mPlayer.stop(); - mPlayer2.prepare(); - }else{ - /* mPlayer2.stop(); - mPlayer.prepare();*/ - } - } - Log.i(TAG, "onPlaybackStateChanged: " + playbackState + " play = " + isPlayer1 + " p1 = " + mPlayer.isPlaying() + " p2 = " + mPlayer2.isPlaying()); - isPlayer = !isPlayer; - } - - @Override - public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) { - Player.Listener.super.onMediaItemTransition(mediaItem, reason); - Log.i(TAG, "onMediaItemTransition: " + reason); - } @Override public void onPlayerError(PlaybackException error) { @@ -1123,6 +1083,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); + Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { @@ -1131,15 +1092,19 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } @Override - public void onTimelineChanged(Timeline timeline, int reason) { - Player.Listener.super.onTimelineChanged(timeline, reason); - Log.i(TAG, "onTimelineChanged: " + reason); + public void onPlaybackStateChanged(int playbackState) { + Player.Listener.super.onPlaybackStateChanged(playbackState); + if (playbackState == Player.STATE_BUFFERING) { + showLoadingDialog(); + } } @Override - public void onTracksChanged(Tracks tracks) { - Player.Listener.super.onTracksChanged(tracks); - Log.i(TAG, "onTracksChanged: " + tracks.getGroups().size()); + public void onIsPlayingChanged(boolean isPlaying) { + Player.Listener.super.onIsPlayingChanged(isPlaying); + if (isPlaying) { + hideCover(); + } } } } diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index 5ea00b74f..b9ee9a46c 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -13,13 +13,14 @@ import com.yunbao.live.interfaces.ILiveLinkMicViewHolder; public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements ILiveLinkMicViewHolder { protected LiveBean mLiveBean; - public static final int PLAY_MODEL_DEF=-1; - public static final int PLAY_MODEL_480=0; - public static final int PLAY_MODEL_720=1; - public static final int PLAY_MODEL_1080=2; + public static final int PLAY_MODEL_DEF = -1; + public static final int PLAY_MODEL_480 = 0; + public static final int PLAY_MODEL_720 = 1; + public static final int PLAY_MODEL_1080 = 2; + public static int PLAY_MODEL = PLAY_MODEL_DEF; - public static final String[] videoRatioHorizontal = new String[]{"_640_480", "_960_720", "_1920_1080","_180_180"}; - public static final String[] videoRatioVertical = new String[]{"_480_640", "_720_960", "_1080_1920","_180_180"}; + public static final String[] videoRatioHorizontal = new String[]{"_640_480", "_1280_720", "_1920_1080", "_180_180"}; + public static final String[] videoRatioVertical = new String[]{"_480_640", "_1280_960", "_1080_1920", "_180_180"}; public static final String[] videoFps = new String[]{"_24", "_30"}; OnMicCallback onMicCallback;//连麦回调 @@ -27,7 +28,7 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL super(context, parentView); } - public abstract void play(String url,int playModel); + public abstract void play(String url, int playModel); public abstract void stopPlay(); @@ -66,7 +67,7 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL } - public interface OnMicCallback{ + public interface OnMicCallback { void onMikUpdate(); } From 5db84c1e61ce5ff6ee0764a3ec592a9d2870f17c Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 29 Dec 2022 13:13:05 +0800 Subject: [PATCH 008/118] =?UTF-8?q?update=20=E6=B8=85=E6=99=B0=E5=BA=A6?= =?UTF-8?q?=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/views/CustomDrawerPopupView.java | 6 +- .../common/views/LiveClarityCustomPopup.java | 18 +++++ .../live/activity/LiveAudienceActivity.java | 2 +- .../yunbao/live/event/LiveAudienceEvent.java | 3 +- .../live/utils/LiveExoPlayerManager.java | 1 + .../live/views/LivePlayRyViewHolder.java | 71 ++++++++++++++++++- .../live/views/LiveRoomPlayViewHolder.java | 2 +- 7 files changed, 96 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/views/CustomDrawerPopupView.java b/common/src/main/java/com/yunbao/common/views/CustomDrawerPopupView.java index ab2199dbd..c5c23580c 100644 --- a/common/src/main/java/com/yunbao/common/views/CustomDrawerPopupView.java +++ b/common/src/main/java/com/yunbao/common/views/CustomDrawerPopupView.java @@ -127,8 +127,10 @@ public class CustomDrawerPopupView extends DrawerPopupView { ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.system_notice), new ViewClicksAntiShake.ViewClicksCallBack() { @Override public void onViewClicks() { -// dismiss(); - + dismiss(); + if (callBack != null) { + callBack.systemNotice(); + } } diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index 13ec97ca9..edf5ec993 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -12,16 +12,28 @@ import com.yunbao.common.R; import com.yunbao.common.views.weight.ViewClicksAntiShake; public class LiveClarityCustomPopup extends BottomPopupView implements View.OnClickListener { + public static final int BAN_720 = 1; + public static final int BAN_1080 = 2; private int selectClarity = 1; private RelativeLayout lineSd, lineHd, lineFhd; private ImageView iconSd, iconHd, iconFhd; + private int banSelect; public int getSelectClarity() { return selectClarity; } + public LiveClarityCustomPopup(@NonNull Context context, int selectClarity, int banSelect) { + super(context); + this.selectClarity = selectClarity; + this.banSelect = banSelect; + } + public LiveClarityCustomPopup(@NonNull Context context, int selectClarity) { super(context); + if (selectClarity == -1) { + selectClarity = 0; + } this.selectClarity = selectClarity; } @@ -75,6 +87,12 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl selectClarity(selectClarity); dismiss(); }); + if (banSelect == BAN_720) { + lineFhd.setEnabled(false); + lineHd.setEnabled(false); + } else if (banSelect == BAN_1080) { + lineFhd.setEnabled(false); + } } /** diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index 135739ce7..d817ab129 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -864,7 +864,7 @@ public class LiveAudienceActivity extends LiveActivity { public void systemNotice() { Bus.get().post(new LiveAudienceEvent() .setBean(mLiveBean) - .setType(LiveAudienceEvent.LiveAudienceType.NOTICE)); + .setType(LiveAudienceEvent.LiveAudienceType.LIVE_VIDEO)); } @Override diff --git a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java index 8e5daccd3..204abebf2 100644 --- a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java +++ b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java @@ -256,7 +256,8 @@ public class LiveAudienceEvent extends BaseModel { UP_PK_TWO(51, "PK头像信息"), CUSTOM_FULL_SERVICE_NOTIFY(51, "全服通知"), CHANGE_VIEW(52, "更改连胜位置"), - UPDATA_ROBOT(53, "更新机器人消息"); + UPDATA_ROBOT(53, "更新机器人消息"), + LIVE_VIDEO(54, "画质选择"); private int type; private String name; diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 2ccc0d15e..9e0bf571b 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -134,6 +134,7 @@ public class LiveExoPlayerManager { } public void switchUrl(String url) { + Log.i(TAG, "switchUrl: "+url); isSwitchUrl = true; getNextPlayer().setMediaItem(createMediaItem(url)); getNextPlayer().prepare(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 4e2e01176..253d33e02 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -30,9 +30,13 @@ import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Tracks; import com.google.android.exoplayer2.video.VideoSize; +import com.lxj.xpopup.XPopup; +import com.lxj.xpopup.core.BasePopupView; +import com.lxj.xpopup.interfaces.XPopupCallback; import com.lzf.easyfloat.EasyFloat; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; +import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.L; @@ -40,9 +44,11 @@ import com.yunbao.common.utils.MicStatusManager; import com.yunbao.common.utils.ScreenDimenUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.WordUtil; +import com.yunbao.common.views.LiveClarityCustomPopup; import com.yunbao.live.R; import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveAudienceActivity; +import com.yunbao.live.event.LiveAudienceEvent; import com.yunbao.live.utils.LiveExoPlayerManager; import org.greenrobot.eventbus.EventBus; @@ -132,6 +138,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void init() { EventBus.getDefault().register(this); + Bus.getOn(this); mRoot = (ViewGroup) findViewById(R.id.root); mSmallContainer = (ViewGroup) findViewById(R.id.small_container); mLeftContainer = (ViewGroup) findViewById(R.id.left_container); @@ -390,10 +397,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { });*/ MediaItem item = createMediaItem(url); if (mPlayer.isPlaying()) { - ToastUtil.show("set 2"); + ToastUtil.show("set 2 画质="+playModel); mPlayer.switchUrl(url); } else { - ToastUtil.show("set 1"); + ToastUtil.show("set 1 画质="+playModel); mPlayer.startUrl(url); } /* if (mPlayer.isPlaying()) { @@ -431,6 +438,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { mPlayer.stop(); mPlayer.release(); } + Bus.getOff(this); + EventBus.getDefault().unregister(this); L.e(TAG, "release------->"); } @@ -782,6 +791,64 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onOpenDrawer(LiveAudienceEvent event) { + if (event.getType() == LiveAudienceEvent.LiveAudienceType.LIVE_VIDEO) { + int ban = PLAY_MODEL == PLAY_MODEL_720 ? LiveClarityCustomPopup.BAN_1080 : PLAY_MODEL == PLAY_MODEL_480 ? LiveClarityCustomPopup.BAN_720 : 0; + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL); + new XPopup.Builder(mContext) + .setPopupCallback(new XPopupCallback() { + @Override + public void onCreated(BasePopupView popupView) { + + } + + @Override + public void beforeShow(BasePopupView popupView) { + + } + + @Override + public void onShow(BasePopupView popupView) { + + } + + @Override + public void onDismiss(BasePopupView popupView) { + int selectClarity = liveClarityCustomPopup.getSelectClarity(); + play(srcUrl, selectClarity); + } + + @Override + public void beforeDismiss(BasePopupView popupView) { + + } + + @Override + public boolean onBackPressed(BasePopupView popupView) { + return false; + } + + @Override + public void onKeyBoardStateChanged(BasePopupView popupView, int height) { + + } + + @Override + public void onDrag(BasePopupView popupView, int value, float percent, boolean upOrLeft) { + + } + + @Override + public void onClickOutside(BasePopupView popupView) { + + } + }) + .asCustom(liveClarityCustomPopup) + .show(); + } + } + /** * 把观众转换成主播 */ diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index b9ee9a46c..ffb150b0b 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -20,7 +20,7 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL public static int PLAY_MODEL = PLAY_MODEL_DEF; public static final String[] videoRatioHorizontal = new String[]{"_640_480", "_1280_720", "_1920_1080", "_180_180"}; - public static final String[] videoRatioVertical = new String[]{"_480_640", "_1280_960", "_1080_1920", "_180_180"}; + public static final String[] videoRatioVertical = new String[]{"_480_640", "_720_1280", "_1080_1920", "_180_180"}; public static final String[] videoFps = new String[]{"_24", "_30"}; OnMicCallback onMicCallback;//连麦回调 From 43c22fca7c2dec5f9aa0821a2df1c10551e55bad Mon Sep 17 00:00:00 2001 From: 18142669586 <1669783059@qq.com> Date: Thu, 29 Dec 2022 15:17:34 +0800 Subject: [PATCH 009/118] =?UTF-8?q?=E4=B8=BB=E6=92=ADPK=E5=90=8D=E5=AD=97?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E6=96=B0=E5=A2=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/event/AnchorInfoEvent.java | 47 +++++++++++++ .../presenter/LiveRyLinkMicPkPresenter.java | 8 +++ .../live/views/LivePushRyViewHolder.java | 30 ++++++++ .../src/main/res/layout/view_live_push_ry.xml | 70 +++++++++++++++---- live/src/main/res/layout/view_live_room.xml | 1 - 5 files changed, 140 insertions(+), 16 deletions(-) create mode 100644 common/src/main/java/com/yunbao/common/event/AnchorInfoEvent.java diff --git a/common/src/main/java/com/yunbao/common/event/AnchorInfoEvent.java b/common/src/main/java/com/yunbao/common/event/AnchorInfoEvent.java new file mode 100644 index 000000000..e15712cc0 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/event/AnchorInfoEvent.java @@ -0,0 +1,47 @@ +package com.yunbao.common.event; + +public class AnchorInfoEvent { + protected boolean clear; + protected String id; + protected String userNiceName; + protected String avatar; + + public AnchorInfoEvent(boolean clears,String ids, String userNiceNames,String avatars) { + clear = clears; + id = ids; + userNiceName = userNiceNames; + avatar = avatars; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUserNiceName() { + return userNiceName; + } + + public void setUserNiceName(String userNiceName) { + this.userNiceName = userNiceName; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public boolean isClear() { + return clear; + } + + public void setClear(boolean clear) { + this.clear = clear; + } +} diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index 4afb31a72..e5993db45 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -38,6 +38,8 @@ import com.alibaba.fastjson.JSONObject; import com.tencent.trtc.TRTCCloud; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.bean.UserBean; +import com.yunbao.common.event.AnchorInfoEvent; +import com.yunbao.common.event.FollowEvent; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.http.live.LiveNetManager; @@ -608,6 +610,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * 主播与主播PK PK主播发过来的已经接受 */ public void onLinkMicToPk(UserBean u) { + EventBus.getDefault().post(new AnchorInfoEvent(false,u.getId(), u.getUserNiceName(),u.getAvatar())); Log.e("eve", u.getId() + ""); /** * 加入副房间 @@ -770,6 +773,8 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { msg1.put("pkuid", CommonAppConfig.getInstance().getUid()); msg1.put("pkhead", CommonAppConfig.getInstance().getUserBean().getAvatarThumb()); msg1.put("pkname", CommonAppConfig.getInstance().getUserBean().getUserNiceName()); + EventBus.getDefault().post(new AnchorInfoEvent(false,bean.getId(), bean.getUserNiceName(),bean.getAvatar())); + if (bean != null && bean.isRandomPk()) { msg1.put("random_pk", bean.isRandomPk() ? 1 : 0); msg1.put("is_ladders", bean.getRankPkImgUrl()); @@ -1057,6 +1062,9 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * 退出多人PK */ public static void leaveDRRoom() { + //清理PK上面对方的头像 + EventBus.getDefault().post(new AnchorInfoEvent(true,"", "","")); + Log.e("ry", "退出多人OKKK" + inputStreamList.size()); isDRPK = 0; for (int i = 0; i < inputStreamList.size(); i++) { diff --git a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java index b18d24825..a3c663c54 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java @@ -25,6 +25,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.alibaba.fastjson.JSONObject; +import com.makeramen.roundedimageview.RoundedImageView; import com.tencent.liteav.device.TXDeviceManager; import com.tencent.rtmp.ITXLivePushListener; import com.tencent.rtmp.TXLiveConstants; @@ -33,6 +34,9 @@ import com.yunbao.common.CommonAppConfig; import com.yunbao.common.Constants; import com.yunbao.common.bean.HttpCallbackModel; import com.yunbao.common.bean.UserBean; +import com.yunbao.common.event.AnchorInfoEvent; +import com.yunbao.common.event.FollowEvent; +import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.http.live.LiveNetManager; @@ -53,6 +57,8 @@ import com.yunbao.live.presenter.LiveRyLinkMicPkPresenter; import com.yunbao.live.socket.SocketSendBean; import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; import java.util.ArrayList; import java.util.List; @@ -100,10 +106,30 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX public static RCRTCLiveInfo rcrtcLiveInfo; private ViewGroup liveActivityContainer; + private TextView tv_avatarOther_name; + private ImageView avatarOther; + private LinearLayout goto_room_view; + + //修改上面主播的头像 + @Subscribe(threadMode = ThreadMode.MAIN) + public void onUPAnchorInfo(AnchorInfoEvent e) { + if (e != null) { + if(e.isClear()==false) { + tv_avatarOther_name.setText(e.getUserNiceName()); + ImgLoader.displayAvatar(mContext, e.getAvatar(), avatarOther); + goto_room_view.setVisibility(View.VISIBLE); + }else{ + goto_room_view.setVisibility(View.GONE); + + } + } + } + public LivePushRyViewHolder(Context context, ViewGroup parentView) { super(context, parentView); this.contexts = context; + EventBus.getDefault().register(this); } @Override @@ -379,6 +405,10 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX dr_pk_view = (LinearLayout) findViewById(R.id.dr_pk_view); dr_pk_view.setVisibility(View.GONE); btn_close = (TextView) findViewById(R.id.btn_close); + tv_avatarOther_name = (TextView) findViewById(R.id.tv_avatarOther_name); + avatarOther = (ImageView) findViewById(R.id.avatarOther); + goto_room_view = (LinearLayout) findViewById(R.id.goto_room_view); + goto_room_view.setVisibility(View.GONE); mMainHandler = new Handler(Looper.getMainLooper()); btn_close.setOnClickListener(new View.OnClickListener() { @Override diff --git a/live/src/main/res/layout/view_live_push_ry.xml b/live/src/main/res/layout/view_live_push_ry.xml index dd8c03d43..877d2519c 100644 --- a/live/src/main/res/layout/view_live_push_ry.xml +++ b/live/src/main/res/layout/view_live_push_ry.xml @@ -104,6 +104,46 @@ android:layout_height="match_parent" /> + + + + + + + + + + + + + - From 956bef4b9030739f8b3b34fa663be2d4b1dd067f Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 29 Dec 2022 15:59:03 +0800 Subject: [PATCH 010/118] =?UTF-8?q?update=20=E6=B8=85=E6=99=B0=E5=BA=A6?= =?UTF-8?q?=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/bean/EnterRoomNewModel.java | 10 +++ .../com/yunbao/common/utils/DialogUitl.java | 16 ++++ .../common/views/LiveClarityCustomPopup.java | 24 ++++- .../main/res/layout/dialog_live_clarity.xml | 3 + common/src/main/res/layout/dialog_toast.xml | 18 ++++ .../live/adapter/FreePkRecyclerAdapter.java | 2 +- .../live/utils/LiveExoPlayerManager.java | 84 ++++++++++++++--- .../live/views/LivePlayKsyViewHolder.java | 5 ++ .../live/views/LivePlayRyViewHolder.java | 90 ++++++++++++------- .../live/views/LivePlayTxViewHolder.java | 5 ++ .../views/LivePlayTxViewHolder_backup.java | 5 ++ .../live/views/LiveRoomPlayViewHolder.java | 8 ++ .../live/views/PortraitLiveManager.java | 6 +- 13 files changed, 229 insertions(+), 47 deletions(-) create mode 100644 common/src/main/res/layout/dialog_toast.xml diff --git a/common/src/main/java/com/yunbao/common/bean/EnterRoomNewModel.java b/common/src/main/java/com/yunbao/common/bean/EnterRoomNewModel.java index b8245fe3f..66daf307c 100644 --- a/common/src/main/java/com/yunbao/common/bean/EnterRoomNewModel.java +++ b/common/src/main/java/com/yunbao/common/bean/EnterRoomNewModel.java @@ -28,6 +28,8 @@ public class EnterRoomNewModel extends BaseModel { private String isUseHotCard = "";//是否使用热度卡 @SerializedName("liveRoomActivity") private List liveRoomActivityModels = new ArrayList<>();//活动列表 + @SerializedName("clarityType") + private int clarityType; public List getLiveRoomActivityModels() { return liveRoomActivityModels; @@ -109,4 +111,12 @@ public class EnterRoomNewModel extends BaseModel { this.isUseHotCard = isUseHotCard; return this; } + + public int getClarityType() { + return clarityType; + } + + public void setClarityType(int clarityType) { + this.clarityType = clarityType; + } } diff --git a/common/src/main/java/com/yunbao/common/utils/DialogUitl.java b/common/src/main/java/com/yunbao/common/utils/DialogUitl.java index b53f0258b..d75105daf 100644 --- a/common/src/main/java/com/yunbao/common/utils/DialogUitl.java +++ b/common/src/main/java/com/yunbao/common/utils/DialogUitl.java @@ -4,6 +4,8 @@ import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; +import android.os.Handler; +import android.os.Looper; import android.text.InputFilter; import android.text.InputType; import android.text.Spanned; @@ -68,6 +70,20 @@ public class DialogUitl { } return dialog; } + public static void showToast(Context context,String content,long delayMillis){ + Dialog dialog = new Dialog(context, R.style.dialog); + dialog.setContentView(R.layout.dialog_toast); + dialog.setCancelable(false); + dialog.setCanceledOnTouchOutside(false); + if (!TextUtils.isEmpty(content)) { + TextView titleView = (TextView) dialog.findViewById(R.id.text); + if (titleView != null) { + titleView.setText(content); + } + } + dialog.show(); + new Handler(Looper.getMainLooper()).postDelayed(dialog::dismiss,delayMillis); + } public static Dialog loadingDialog(Context context) { diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index edf5ec993..b22df8f9c 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -2,13 +2,17 @@ package com.yunbao.common.views; import android.content.Context; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.RelativeLayout; +import android.widget.TextView; import androidx.annotation.NonNull; import com.lxj.xpopup.core.BottomPopupView; import com.yunbao.common.R; +import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.views.weight.ViewClicksAntiShake; public class LiveClarityCustomPopup extends BottomPopupView implements View.OnClickListener { @@ -17,6 +21,8 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl private int selectClarity = 1; private RelativeLayout lineSd, lineHd, lineFhd; private ImageView iconSd, iconHd, iconFhd; + private ImageView titleSDImg, titleHDImg, titleFHDImg; + private TextView titleSDText, titleHDText, titleFHDText; private int banSelect; public int getSelectClarity() { @@ -25,8 +31,12 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl public LiveClarityCustomPopup(@NonNull Context context, int selectClarity, int banSelect) { super(context); - this.selectClarity = selectClarity; this.banSelect = banSelect; + if (selectClarity == -1) { + selectClarity = 0; + } + this.selectClarity = selectClarity; + ToastUtil.show("ban "+banSelect); } public LiveClarityCustomPopup(@NonNull Context context, int selectClarity) { @@ -67,6 +77,12 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl iconSd = findViewById(R.id.icon_sd); iconHd = findViewById(R.id.icon_hd); iconFhd = findViewById(R.id.icon_fhd); + titleSDImg = findViewById(R.id.sd); + titleHDImg = findViewById(R.id.hd); + titleFHDImg = findViewById(R.id.fhd); + titleSDText = findViewById(R.id.sd_text); + titleHDText = findViewById(R.id.hd_text); + titleFHDText = findViewById(R.id.fhd_text); selectClarity(selectClarity); //流畅 ViewClicksAntiShake.clicksAntiShake(lineSd, () -> { @@ -90,8 +106,14 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl if (banSelect == BAN_720) { lineFhd.setEnabled(false); lineHd.setEnabled(false); + titleHDImg.setImageAlpha(40); + titleFHDImg.setImageAlpha(40); + titleHDText.setAlpha(0.2f); + titleFHDText.setAlpha(0.2f); } else if (banSelect == BAN_1080) { lineFhd.setEnabled(false); + titleFHDText.setAlpha(0.2f); + titleFHDImg.setImageAlpha(20); } } diff --git a/common/src/main/res/layout/dialog_live_clarity.xml b/common/src/main/res/layout/dialog_live_clarity.xml index 35fd83425..04d3d5a58 100644 --- a/common/src/main/res/layout/dialog_live_clarity.xml +++ b/common/src/main/res/layout/dialog_live_clarity.xml @@ -41,6 +41,7 @@ android:src="@mipmap/icon_sd" /> + + + + + \ No newline at end of file diff --git a/live/src/main/java/com/yunbao/live/adapter/FreePkRecyclerAdapter.java b/live/src/main/java/com/yunbao/live/adapter/FreePkRecyclerAdapter.java index 93a0c7762..57b0f377b 100644 --- a/live/src/main/java/com/yunbao/live/adapter/FreePkRecyclerAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/FreePkRecyclerAdapter.java @@ -115,7 +115,7 @@ public class FreePkRecyclerAdapter extends RefreshAdapter { } if (freePkNum == 0 && mDrPkNum == -1) { ToastUtil.show(R.string.free_pk_num_null); - return; + // return; } LiveHttpUtil.getMicList(LiveRyAnchorActivity.mLiveUid, 0, new com.yunbao.common.http.HttpCallback() { diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 9e0bf571b..e0da52982 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -1,12 +1,17 @@ package com.yunbao.live.utils; import android.content.Context; +import android.os.Handler; +import android.os.Looper; import android.util.Log; import android.view.SurfaceView; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.analytics.AnalyticsListener; +import com.google.android.exoplayer2.analytics.PlaybackStats; +import com.google.android.exoplayer2.analytics.PlaybackStatsListener; import com.google.android.exoplayer2.video.VideoSize; public class LiveExoPlayerManager { @@ -19,11 +24,66 @@ public class LiveExoPlayerManager { private Player.Listener listener; private boolean isSwitchUrl = false; private String TAG = "播放"; + private int playBufferIndex = 0; + private Handler handler; public LiveExoPlayerManager(Context mContext) { this.mContext = mContext; player1 = new ExoPlayer.Builder(mContext).build(); player2 = new ExoPlayer.Builder(mContext).build(); + handler = new Handler(Looper.getMainLooper()); + setListener(); + setAnalyticsListener(); + } + + public void setListener(Player.Listener listener) { + this.listener = listener; + } + + public void setMainView(SurfaceView mainView) { + this.mainView = mainView; + } + + private void setAnalyticsListener() { + player1.addAnalyticsListener(new AnalyticsListener() { + @Override + public void onPlaybackStateChanged( + EventTime eventTime, int state) { + Log.d(TAG, "onPlaybackStateChanged(1) called with: eventTime = [" + eventTime + "], state = [" + state + "]"); + } + + @Override + public void onDroppedVideoFrames( + EventTime eventTime, int droppedFrames, long elapsedMs) { + Log.d(TAG, "onDroppedVideoFrames(1) called with: eventTime = [" + eventTime + "], droppedFrames = [" + droppedFrames + "], elapsedMs = [" + elapsedMs + "]"); + } + }); + + player2.addAnalyticsListener(new AnalyticsListener() { + @Override + public void onPlaybackStateChanged( + EventTime eventTime, int state) { + Log.d(TAG, "onPlaybackStateChanged(2) called with: eventTime = [" + eventTime.totalBufferedDurationMs + "], state = [" + state + "]"); + } + + @Override + public void onDroppedVideoFrames( + EventTime eventTime, int droppedFrames, long elapsedMs) { + Log.d(TAG, "onDroppedVideoFrames(2) called with: eventTime = [" + eventTime + "], droppedFrames = [" + droppedFrames + "], elapsedMs = [" + elapsedMs + "]"); + } + }); + + } + + private Runnable buffRunnable = new Runnable() { + @Override + public void run() { + playBufferIndex = 0; + listener.onPlaybackStateChanged(Player.STATE_BUFFERING); + } + }; + + private void setListener() { player1.addListener(new Player.Listener() { @Override public void onPlaybackStateChanged(int playbackState) { @@ -34,9 +94,13 @@ public class LiveExoPlayerManager { player2.setVideoSurface(null); player1.play(); Log.i(TAG, "切换播放器1"); + handler.removeCallbacks(buffRunnable); + playBufferIndex = 0; } else if (playbackState == Player.STATE_BUFFERING && status == MODEL_PLAY1 && !isSwitchUrl) { if (listener != null) { - listener.onPlaybackStateChanged(playbackState); + if (playBufferIndex++ == 0) { + handler.postDelayed(buffRunnable, 1000); + } } } } @@ -80,9 +144,13 @@ public class LiveExoPlayerManager { player1.setVideoSurface(null); player2.play(); Log.i(TAG, "切换播放器2 " + player2.isPlaying()); + handler.removeCallbacks(buffRunnable); + playBufferIndex = 0; } else if (playbackState == Player.STATE_BUFFERING && status == MODEL_PLAY2 && !isSwitchUrl) { if (listener != null) { - listener.onPlaybackStateChanged(playbackState); + if (playBufferIndex++ == 0) { + handler.postDelayed(buffRunnable, 1000); + } } } } @@ -117,16 +185,9 @@ public class LiveExoPlayerManager { }); } - public void setListener(Player.Listener listener) { - this.listener = listener; - } - - public void setMainView(SurfaceView mainView) { - this.mainView = mainView; - } - public void startUrl(String url) { isSwitchUrl = true; + playBufferIndex = 0; getNowPlayer().setVideoSurfaceView(mainView); getNowPlayer().setMediaItem(createMediaItem(url)); getNowPlayer().prepare(); @@ -134,7 +195,8 @@ public class LiveExoPlayerManager { } public void switchUrl(String url) { - Log.i(TAG, "switchUrl: "+url); + Log.i(TAG, "switchUrl: " + url); + playBufferIndex = 0; isSwitchUrl = true; getNextPlayer().setMediaItem(createMediaItem(url)); getNextPlayer().prepare(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayKsyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayKsyViewHolder.java index b50a38d80..4dc373b50 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayKsyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayKsyViewHolder.java @@ -142,6 +142,11 @@ public class LivePlayKsyViewHolder extends LiveRoomPlayViewHolder { } + @Override + public void switchStream(String url, int playModel) { + + } + @Override public void release() { diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 253d33e02..e61d64f3f 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -106,9 +106,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public static Context contexts; public static FrameLayout ry_view; - private static final int VIDEO_VERTICAL = 1; - private static final int VIDEO_HORIZONTAL = 2; - int videoLandscape = -1; // 视频方向,1=竖屏,2=横屏 + private static final int VIDEO_VERTICAL = 2; + private static final int VIDEO_HORIZONTAL = 1; + int videoLandscape = -1; // 视频方向,2=竖屏,1=横屏 static int vHeight;//视频高 private TextView debugView; @@ -197,6 +197,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public synchronized void setLiveBeanLandscape(int landscape) { this.landscape = landscape; + this.videoLandscape = landscape; if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); @@ -395,40 +396,38 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { super.onReceiveSeiMessage(player, payloadType, data); } });*/ - MediaItem item = createMediaItem(url); if (mPlayer.isPlaying()) { - ToastUtil.show("set 2 画质="+playModel); - mPlayer.switchUrl(url); - } else { - ToastUtil.show("set 1 画质="+playModel); - mPlayer.startUrl(url); + mPlayer.stop(); } - /* if (mPlayer.isPlaying()) { - MediaSource nextSource = new ProgressiveMediaSource.Factory(new DefaultHttpDataSource.Factory()) - .createMediaSource(createMediaItem(url)); - MediaSource oldSource = new ProgressiveMediaSource.Factory(new DefaultHttpDataSource.Factory()) - .createMediaSource(mPlayer.getCurrentMediaItem()); - ClippingMediaSource clippingMediaSource = new ClippingMediaSource(oldSource, 0, 3000, false, true, true); - ConcatenatingMediaSource source = new ConcatenatingMediaSource(clippingMediaSource, nextSource); - mPlayer.addMediaSource(source); - mPlayer.prepare(); - mPlayer.setPlayWhenReady(true); - } else { - MediaItem item = createMediaItem(url); - mPlayer.setMediaItem(item); - mPlayer.prepare(); - mPlayer.play(); - }*/ + mPlayer.startUrl(url); purl = url; onPrepared(); - } - private MediaItem createMediaItem(String url) { - MediaItem mediaItem = MediaItem.fromUri(url); - return mediaItem; - } + @Override + public void switchStream(String url, int playModel) { + srcUrl = url; + PLAY_MODEL = playModel; + if (playModel != PLAY_MODEL_DEF) { + if (videoLandscape == VIDEO_VERTICAL) { + url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); + } else if (videoLandscape == VIDEO_HORIZONTAL) { + url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); + } + } + Log.e("purl121", url); + if (TextUtils.isEmpty(url) || mVideoView == null) { + return; + } + + + if (TextUtils.isEmpty(url) || mVideoView == null) { + return; + } + mPlayer.switchUrl(url); + purl = url; + } @Override public void release() { @@ -445,6 +444,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void stopPlay() { + Log.i(TAG, "stopPlay: "); if (mCover != null) { mCover.setAlpha(1f); if (mCover.getVisibility() != View.VISIBLE) { @@ -794,8 +794,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Subscribe(threadMode = ThreadMode.MAIN) public void onOpenDrawer(LiveAudienceEvent event) { if (event.getType() == LiveAudienceEvent.LiveAudienceType.LIVE_VIDEO) { - int ban = PLAY_MODEL == PLAY_MODEL_720 ? LiveClarityCustomPopup.BAN_1080 : PLAY_MODEL == PLAY_MODEL_480 ? LiveClarityCustomPopup.BAN_720 : 0; - LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL); + int ban = roomModel.getClarityType() - 1 == PLAY_MODEL_720 ? LiveClarityCustomPopup.BAN_1080 : roomModel.getClarityType() - 1 == PLAY_MODEL_480 ? LiveClarityCustomPopup.BAN_720 : 0; + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL, ban); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override @@ -816,7 +816,30 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void onDismiss(BasePopupView popupView) { int selectClarity = liveClarityCustomPopup.getSelectClarity(); - play(srcUrl, selectClarity); + if (selectClarity == PLAY_MODEL) return; + if (selectClarity == 2) { + new DialogUitl.Builder(mContext) + .setTitle("超高清提示") + .setContent("在網速不穩定的情況下,選擇超高清將會有可能導致直播間畫面卡頓,是否確認選擇?") + .setConfrimString("堅持選擇") + .setCancelString("返回") + .setClickCallback(new DialogUitl.SimpleCallback() { + @Override + public void onConfirmClick(Dialog dialog, String content) { + switchStream(srcUrl, selectClarity); + dialog.dismiss(); + showToast(); + } + }).build().show(); + } else { + switchStream(srcUrl, selectClarity); + showToast(); + } + } + + private void showToast() { + DialogUitl.showToast(mContext, " 設置成功\n" + + "正在為你轉換中", 3000); } @Override @@ -1151,6 +1174,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); + ToastUtil.show("分辨率: width = " + videoSize.width + " height = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder.java index be84ebfa8..5acc92c24 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder.java @@ -318,6 +318,11 @@ public class LivePlayTxViewHolder extends LiveRoomPlayViewHolder implements ITXL L.e(TAG, "play----url--->" + url); } + @Override + public void switchStream(String url, int playModel) { + + } + @Override public void stopPlay() { mChangeToLeft = false; diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder_backup.java b/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder_backup.java index 9548eda7b..1227a9324 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder_backup.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayTxViewHolder_backup.java @@ -280,6 +280,11 @@ public class LivePlayTxViewHolder_backup extends LiveRoomPlayViewHolder implemen L.e(TAG, "play----url--->" + url); } + @Override + public void switchStream(String url, int playModel) { + + } + @Override public void stopPlay() { mChangeToLeft = false; diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index ffb150b0b..aa28c3378 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -3,6 +3,7 @@ package com.yunbao.live.views; import android.content.Context; import android.view.ViewGroup; +import com.yunbao.common.bean.EnterRoomNewModel; import com.yunbao.common.bean.LiveBean; import com.yunbao.common.views.AbsViewHolder; import com.yunbao.live.interfaces.ILiveLinkMicViewHolder; @@ -23,12 +24,14 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL public static final String[] videoRatioVertical = new String[]{"_480_640", "_720_1280", "_1080_1920", "_180_180"}; public static final String[] videoFps = new String[]{"_24", "_30"}; OnMicCallback onMicCallback;//连麦回调 + public EnterRoomNewModel roomModel; public LiveRoomPlayViewHolder(Context context, ViewGroup parentView) { super(context, parentView); } public abstract void play(String url, int playModel); + public abstract void switchStream(String url, int playModel); public abstract void stopPlay(); @@ -66,6 +69,11 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL this.onMicCallback = onMicCallback; } + public void setLiveEnterRoomNewModel(EnterRoomNewModel data) { + data.setClarityType(2); + this.roomModel = data; + } + public interface OnMicCallback { void onMikUpdate(); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index b36d84d29..f91dcd5db 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -198,7 +198,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe this.mContext = context; this.mIntent = intent; liveImDeletUtil = new LiveImDeletUtil(); - portraitLiveManager=this; + portraitLiveManager = this; ininView(); } @@ -329,9 +329,11 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe }); } + public void test(int model) { mLivePlayViewHolder.play(mLiveBean.getPull(), model); } + private Runnable sendFIm = new Runnable() { @Override public void run() { @@ -357,6 +359,8 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe } landscape = data.getLiveInfo().getLandscape(); mLivePlayViewHolder.setLiveBeanLandscape(landscape); + mLivePlayViewHolder.setLiveEnterRoomNewModel(data); + mLivePlayViewHolder.switchStream(mLiveBean.getPull(), data.getClarityType() - 1); //是否热度卡加成 liveHandler.postDelayed(() -> mLiveRoomViewHolder.getIsHot(data.getIsUseHotCard()), 700); From 660853d5be46bad2160ccacde422f584759a7ad7 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 29 Dec 2022 15:59:32 +0800 Subject: [PATCH 011/118] =?UTF-8?q?update=20=E6=B8=85=E6=99=B0=E5=BA=A6?= =?UTF-8?q?=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/common/views/LiveClarityCustomPopup.java | 1 - 1 file changed, 1 deletion(-) diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index b22df8f9c..57e701de3 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -36,7 +36,6 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl selectClarity = 0; } this.selectClarity = selectClarity; - ToastUtil.show("ban "+banSelect); } public LiveClarityCustomPopup(@NonNull Context context, int selectClarity) { From 2e986db686d812d8e0238aef59bd7066591b201c Mon Sep 17 00:00:00 2001 From: 18142669586 <1669783059@qq.com> Date: Thu, 29 Dec 2022 16:12:41 +0800 Subject: [PATCH 012/118] =?UTF-8?q?=E5=96=AE=E4=BA=BAPK=E5=8D=A10=E5=88=86?= =?UTF-8?q?=20=E5=84=AA=E5=8C=96=E8=A8=88=E7=AE=97=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/presenter/LiveRyLinkMicPkPresenter.java | 8 ++++---- .../com/yunbao/live/views/LiveLinkMicPkViewHolder.java | 8 ++++++-- live/src/main/res/layout/view_live_push_ry.xml | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index e5993db45..0c457eab4 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -394,10 +394,10 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { ((LiveRyAnchorActivity) mContext).setPkBtnVisible(true); } //如果PK结束Im没有发送关闭PK的消息,倒计时结束自动关闭 - if (mLiveLinkMicPkViewHolder != null) { - mLiveLinkMicPkViewHolder.removeFromParent(); - mLiveLinkMicPkViewHolder.release(); - } +// if (mLiveLinkMicPkViewHolder != null) { +// mLiveLinkMicPkViewHolder.removeFromParent(); +// mLiveLinkMicPkViewHolder.release(); +// } mLiveLinkMicPkViewHolder = null; } } diff --git a/live/src/main/java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java index 616b14366..c83022461 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java @@ -190,8 +190,12 @@ public class LiveLinkMicPkViewHolder extends AbsViewHolder { public void setTime(String content) { if (mTime != null) { - - mTime.setText(content); + Log.i("vvvs",content); + if(content.trim().equals("00:01")||content.trim().equals("00:00")){ + mTime.setText("計算中"); + }else { + mTime.setText(content); + } } } diff --git a/live/src/main/res/layout/view_live_push_ry.xml b/live/src/main/res/layout/view_live_push_ry.xml index 877d2519c..733b3d72f 100644 --- a/live/src/main/res/layout/view_live_push_ry.xml +++ b/live/src/main/res/layout/view_live_push_ry.xml @@ -110,7 +110,7 @@ android:layout_width="wrap_content" android:layout_height="27dp" android:layout_alignParentRight="true" - android:layout_marginTop="120dp" + android:layout_marginTop="122dp" android:layout_marginRight="9dp" android:background="@drawable/bg_live_other_ico" android:gravity="center"> @@ -174,7 +174,7 @@ android:paddingBottom="5dp" android:paddingLeft="8dp" android:paddingRight="8dp" - android:layout_marginTop="420dp" + android:layout_marginTop="400dp" android:layout_marginRight="8dp" android:layout_alignParentRight="true" android:text="結束連麥" From 7555510d9424279294df76b012dc698b92046fc9 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 29 Dec 2022 16:16:08 +0800 Subject: [PATCH 013/118] =?UTF-8?q?update=20=E6=B8=85=E6=99=B0=E5=BA=A6?= =?UTF-8?q?=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/utils/LiveExoPlayerManager.java | 45 ++++++- .../live/views/LivePlayRyViewHolder.java | 112 +----------------- 2 files changed, 43 insertions(+), 114 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index e0da52982..ac2d8a8d7 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -14,17 +14,21 @@ import com.google.android.exoplayer2.analytics.PlaybackStats; import com.google.android.exoplayer2.analytics.PlaybackStatsListener; import com.google.android.exoplayer2.video.VideoSize; +/** + * 直播间播放器管理器 + * 通过预加载子播放器来实现无缝切换分辨率功能 + */ public class LiveExoPlayerManager { - private final int MODEL_PLAY1 = 0; - private final int MODEL_PLAY2 = 1; + private final int MODEL_PLAY1 = 0;//当前主播放器 + private final int MODEL_PLAY2 = 1;//当前子播放器 private Context mContext; private ExoPlayer player1, player2; - private SurfaceView mainView; + private SurfaceView mainView;//渲染视图 private int status = MODEL_PLAY1; private Player.Listener listener; - private boolean isSwitchUrl = false; + private boolean isSwitchUrl = false;//是否为主动切换播放器 private String TAG = "播放"; - private int playBufferIndex = 0; + private int playBufferIndex = 0;//卡顿计数器 private Handler handler; public LiveExoPlayerManager(Context mContext) { @@ -75,6 +79,9 @@ public class LiveExoPlayerManager { } + /** + * 延迟1秒还未恢复播放则认为卡顿了,可以切分辨率了 + */ private Runnable buffRunnable = new Runnable() { @Override public void run() { @@ -185,6 +192,11 @@ public class LiveExoPlayerManager { }); } + /** + * 开始播放 + * + * @param url 地址 + */ public void startUrl(String url) { isSwitchUrl = true; playBufferIndex = 0; @@ -194,6 +206,11 @@ public class LiveExoPlayerManager { getNowPlayer().play(); } + /** + * 无缝切换 + * + * @param url 地址 + */ public void switchUrl(String url) { Log.i(TAG, "switchUrl: " + url); playBufferIndex = 0; @@ -206,26 +223,44 @@ public class LiveExoPlayerManager { return MediaItem.fromUri(url); } + /** + * 获取当前播放器 + */ public ExoPlayer getNowPlayer() { return status == MODEL_PLAY1 ? player1 : player2; } + /** + * 获取下一个播放器。 + */ private ExoPlayer getNextPlayer() { return status == MODEL_PLAY1 ? player2 : player1; } + /** + * 是否正在播放 + */ public boolean isPlaying() { return getNowPlayer().isPlaying(); } + /** + * 停止播放 + */ public void stop() { getNowPlayer().stop(); } + /** + * 开始播放 + */ public void play() { getNowPlayer().play(); } + /** + * 释放播放器 + */ public void release() { player1.release(); player2.release(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index e61d64f3f..d3209358a 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -34,6 +34,7 @@ import com.lxj.xpopup.XPopup; import com.lxj.xpopup.core.BasePopupView; import com.lxj.xpopup.interfaces.XPopupCallback; import com.lzf.easyfloat.EasyFloat; +import com.lzy.okserver.OkDownload; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.utils.Bus; @@ -284,118 +285,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { return; } - if (TextUtils.isEmpty(url) || mVideoView == null) { return; } - - /*mPlayer.setObserver(new V2TXLivePlayerObserver() { - - - - @Override - public void onWarning(V2TXLivePlayer player, int code, String msg, Bundle extraInfo) { - super.onWarning(player, code, msg, extraInfo); - Log.i(TAG, "onWarning: " + "player = " + player + ", code = " + code + ", msg = " + msg + ", extraInfo = " + extraInfo); - if (code == 2105) { - // mPlayer.resumeVideo(); - // mPlayer.resumeAudio(); - mPlayer.stopPlay(); - mPlayer.startPlay(purl); - } - debugView.setText("播放警告code=" + code + " msg=" + msg); - } - - @Override - public void onVideoPlayStatusUpdate(V2TXLivePlayer player, V2TXLiveDef.V2TXLivePlayStatus status, V2TXLiveDef.V2TXLiveStatusChangeReason reason, Bundle extraInfo) { - super.onVideoPlayStatusUpdate(player, status, reason, extraInfo); - //Log.i(TAG, "onVideoPlayStatusUpdate: " + "player = " + player + ", status = " + status + ", reason = " + reason + ", extraInfo = " + extraInfo); - } - - @Override - public void onAudioPlayStatusUpdate(V2TXLivePlayer player, V2TXLiveDef.V2TXLivePlayStatus status, V2TXLiveDef.V2TXLiveStatusChangeReason reason, Bundle extraInfo) { - super.onAudioPlayStatusUpdate(player, status, reason, extraInfo); - //Log.i(TAG, "onAudioPlayStatusUpdate: " + "player = " + player + ", status = " + status + ", reason = " + reason + ", extraInfo = " + extraInfo); - } - - @Override - public void onPlayoutVolumeUpdate(V2TXLivePlayer player, int volume) { - super.onPlayoutVolumeUpdate(player, volume); - - } - - @Override - public void onStatisticsUpdate(V2TXLivePlayer player, V2TXLiveDef.V2TXLivePlayerStatistics statistics) { - super.onStatisticsUpdate(player, statistics); - Map taskMap = OkDownload.getInstance().getTaskMap(); - StringBuilder buffer = new StringBuilder(); - buffer.append("|"); - for (String key : taskMap.keySet()) { - DownloadTask task = taskMap.get(key); - buffer.append(task.progress.fileName).append(":"); - int status = task.progress.status; - switch (status) { - case 0: - buffer.append("无状态"); - break; - case 1: - buffer.append("等待"); - break; - case 2: - buffer.append("下载中:").append(task.progress.fraction); - break; - case 3: - buffer.append("暂停"); - break; - case 4: - buffer.append("错误"); - break; - case 5: - buffer.append("完成"); - - break; - } - - buffer.append("|"); - } - hideCover(); - String debugText = "视频码率:" + statistics.videoBitrate + "\n" + - "音频码率:" + statistics.audioBitrate + "\n" + - "FPS:" + statistics.fps + "\n" + - "CPU:" + statistics.appCpu + "\n" + - "剩余内存:" + DeviceUtils.getMemory(mContext) + "\n" + - "分辨率:" + statistics.height + "x" + statistics.width + "\n" + - "播放状态:" + mPlayer.isPlaying() + "\n" + - "运行时间:" + (System.currentTimeMillis() - CrashSaveBean.getInstance().getStartTime()) / 1000 + "\n"; - debugView.setText(debugText); - Log.i(TAG, "onStatisticsUpdate: " + JSON.toJSONString(statistics) + " |当前下载数 : " + OkDownload.getInstance().getTaskMap().size() + buffer); - if (statistics.height > statistics.width) { - videoLandscape = VIDEO_VERTICAL; - } else { - videoLandscape = VIDEO_HORIZONTAL; - } - if (statistics.fps == 0) { - OkDownload.getInstance().pauseAll(); - } else { - OkDownload.getInstance().startAll(); - } - } - - @Override - public void onSnapshotComplete(V2TXLivePlayer player, Bitmap image) { - super.onSnapshotComplete(player, image); - } - - @Override - public void onRenderVideoFrame(V2TXLivePlayer player, V2TXLiveDef.V2TXLiveVideoFrame videoFrame) { - super.onRenderVideoFrame(player, videoFrame); - } - - @Override - public void onReceiveSeiMessage(V2TXLivePlayer player, int payloadType, byte[] data) { - super.onReceiveSeiMessage(player, payloadType, data); - } - });*/ if (mPlayer.isPlaying()) { mPlayer.stop(); } @@ -1187,6 +1079,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Player.Listener.super.onPlaybackStateChanged(playbackState); if (playbackState == Player.STATE_BUFFERING) { showLoadingDialog(); + OkDownload.getInstance().pauseAll(); } } @@ -1195,6 +1088,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Player.Listener.super.onIsPlayingChanged(isPlaying); if (isPlaying) { hideCover(); + OkDownload.getInstance().startAll(); } } } From 0c053a028e9f10e72ee713d6536f8f678ba2255b Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 29 Dec 2022 16:20:39 +0800 Subject: [PATCH 014/118] =?UTF-8?q?update=20=E6=B8=85=E6=99=B0=E5=BA=A6?= =?UTF-8?q?=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/views/LivePlayRyViewHolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index d3209358a..62d157f9e 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -1066,7 +1066,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); - ToastUtil.show("分辨率: width = " + videoSize.width + " height = " + videoSize.height); + // ToastUtil.show("分辨率: width = " + videoSize.width + " height = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { From 87e3dddac52b528e3840ebc1d7fd7e89dd10cfa7 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 29 Dec 2022 16:34:35 +0800 Subject: [PATCH 015/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=8B=E6=92=AD?= =?UTF-8?q?=E5=90=8E=E9=9A=8F=E5=8D=B3PK=E6=B2=A1=E6=9C=89=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=8F=96=E6=B6=88=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/manager/RandomPkManager.java | 56 ++++++++++++++----- .../live/activity/LiveRyAnchorActivity.java | 1 + 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/manager/RandomPkManager.java b/common/src/main/java/com/yunbao/common/manager/RandomPkManager.java index a48203591..cd4a847b5 100644 --- a/common/src/main/java/com/yunbao/common/manager/RandomPkManager.java +++ b/common/src/main/java/com/yunbao/common/manager/RandomPkManager.java @@ -37,6 +37,8 @@ public class RandomPkManager { private String pkUid;//对方房间ID public static String debugUid; private RankPkInfoBean rankPkInfoBean;//排位赛信息 + private int exitTimer;//退出倒计时 + private TimerTask exitTask = null;//退出任务 Handler handler = new Handler(Looper.getMainLooper()); private RandomPkManager() { @@ -118,6 +120,8 @@ public class RandomPkManager { return String.format(Locale.CHINA, "%02d:%02d", min, sec); } + private Runnable pkRunnable = this::next; + /** * 对方拒绝,开始下一轮匹配 */ @@ -125,11 +129,11 @@ public class RandomPkManager { if (status != PK_STATUS_DEFAULT && status != PK_STATUS_REFUSE) { return; } - new Handler(Looper.getMainLooper()).postDelayed(this::next, 5000); + handler.postDelayed(pkRunnable, 5000); } private void next() { - if (task==null) { + if (task == null) { return; } status = PK_STATUS_REQUEST; @@ -243,19 +247,9 @@ public class RandomPkManager { } } - private int exitTimer; - /** - * 退出匹配 - */ - public void exitPk() { - if (status == PK_STATUS_EXIT_ING) { - return; - } - callEndPkStart(); - status = PK_STATUS_EXIT_ING; - exitTimer = 11; - new Timer().schedule(new TimerTask() { + private TimerTask createExitTask() { + return new TimerTask() { Handler handler = new Handler(Looper.getMainLooper()); @@ -269,10 +263,25 @@ public class RandomPkManager { end(); callEndPkSuccess(); cancel(); + exitTask = null; } }); } - }, 0, 1000); + }; + } + + /** + * 退出匹配 + */ + public void exitPk() { + if (status == PK_STATUS_EXIT_ING) { + return; + } + callEndPkStart(); + status = PK_STATUS_EXIT_ING; + exitTimer = 11; + exitTask = createExitTask(); + new Timer().schedule(exitTask, 0, 1000); } /** @@ -387,6 +396,23 @@ public class RandomPkManager { return exitTimer + ""; } + /** + * 清空状态,下播时调用 + */ + public void release() { + status = PK_STATUS_REQUEST; + if (task != null) { + task.cancel(); + } + if (exitTask != null) { + exitTask.cancel(); + } + randomPkTimer.clear(); + rankPkInfoBean = null; + pkUid = null; + handler.removeCallbacks(pkRunnable); + } + public static abstract class OnRandomPkTimer { /** diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index 8a1dc02df..f4f8b8178 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -843,6 +843,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl PKing = false; isDRPK = 0; endLive(); + RandomPkManager.getInstance().release(); } }); } From d81e6b9f049a21592c520bb0df23e9e499760f68 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Thu, 29 Dec 2022 17:04:23 +0800 Subject: [PATCH 016/118] =?UTF-8?q?=E9=96=8B=E6=92=AD=E8=A8=AD=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=96=8B=E6=92=AD=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=86=E8=BE=A8=E7=8E=87=E8=A8=AD=E7=BD=AE?= =?UTF-8?q?=E5=8F=83=E6=95=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common}/bean/LiveRoomTypeBean.java | 4 +- .../common/http/live/LiveNetManager.java | 29 +++ .../common/views/LiveOpenCustomPopup.java | 178 +++++++++++++ .../views/LiveRobotSettingCustomPopup.java | 7 +- .../res/drawable/backgroud_live_open_lfet.xml | 8 + .../drawable/backgroud_live_open_right.xml | 5 + common/src/main/res/layout/view_live_open.xml | 245 ++++++++++++++++++ .../icon_live_type_normal_1.png | Bin .../icon_live_type_normal_2.png | Bin .../mipmap-xxhdpi}/icon_live_type_pay_1.png | Bin .../mipmap-xxhdpi}/icon_live_type_pay_2.png | Bin .../mipmap-xxhdpi}/icon_live_type_pwd_1.png | Bin .../mipmap-xxhdpi}/icon_live_type_pwd_2.png | Bin .../mipmap-xxhdpi}/icon_live_type_time_1.png | Bin .../mipmap-xxhdpi}/icon_live_type_time_2.png | Bin .../main/res/mipmap-xxhdpi/icon_more_open.png | Bin 0 -> 632 bytes common/src/main/res/values/strings.xml | 9 + .../live/activity/LiveTRTCAnchorActivity.java | 4 +- .../live/adapter/LiveRoomTypeAdapter.java | 2 +- .../LiveNewRoomClassDialogFragment.java | 1 - .../dialog/LiveNewRoomTypeDialogFragment.java | 2 +- .../dialog/LiveRoomTypeDialogFragment.java | 2 +- .../com/yunbao/live/http/LiveHttpUtil.java | 15 +- .../live/views/LiveNewReadyRyViewHolder.java | 186 ++++++++++++- .../live/views/LivePushRyViewHolder.java | 4 +- .../live/views/LiveReadyRyViewHolder.java | 4 +- .../live/views/LiveReadyViewHolder.java | 21 +- 27 files changed, 691 insertions(+), 35 deletions(-) rename {live/src/main/java/com/yunbao/live => common/src/main/java/com/yunbao/common}/bean/LiveRoomTypeBean.java (97%) create mode 100644 common/src/main/java/com/yunbao/common/views/LiveOpenCustomPopup.java create mode 100644 common/src/main/res/drawable/backgroud_live_open_lfet.xml create mode 100644 common/src/main/res/drawable/backgroud_live_open_right.xml create mode 100644 common/src/main/res/layout/view_live_open.xml rename {live/src/main/res/mipmap-mdpi => common/src/main/res/mipmap-xxhdpi}/icon_live_type_normal_1.png (100%) rename {live/src/main/res/mipmap-mdpi => common/src/main/res/mipmap-xxhdpi}/icon_live_type_normal_2.png (100%) rename {live/src/main/res/mipmap-mdpi => common/src/main/res/mipmap-xxhdpi}/icon_live_type_pay_1.png (100%) rename {live/src/main/res/mipmap-mdpi => common/src/main/res/mipmap-xxhdpi}/icon_live_type_pay_2.png (100%) rename {live/src/main/res/mipmap-mdpi => common/src/main/res/mipmap-xxhdpi}/icon_live_type_pwd_1.png (100%) rename {live/src/main/res/mipmap-mdpi => common/src/main/res/mipmap-xxhdpi}/icon_live_type_pwd_2.png (100%) rename {live/src/main/res/mipmap-mdpi => common/src/main/res/mipmap-xxhdpi}/icon_live_type_time_1.png (100%) rename {live/src/main/res/mipmap-mdpi => common/src/main/res/mipmap-xxhdpi}/icon_live_type_time_2.png (100%) create mode 100644 common/src/main/res/mipmap-xxhdpi/icon_more_open.png diff --git a/live/src/main/java/com/yunbao/live/bean/LiveRoomTypeBean.java b/common/src/main/java/com/yunbao/common/bean/LiveRoomTypeBean.java similarity index 97% rename from live/src/main/java/com/yunbao/live/bean/LiveRoomTypeBean.java rename to common/src/main/java/com/yunbao/common/bean/LiveRoomTypeBean.java index ab4370e58..8151367e3 100644 --- a/live/src/main/java/com/yunbao/live/bean/LiveRoomTypeBean.java +++ b/common/src/main/java/com/yunbao/common/bean/LiveRoomTypeBean.java @@ -1,7 +1,7 @@ -package com.yunbao.live.bean; +package com.yunbao.common.bean; import com.yunbao.common.Constants; -import com.yunbao.live.R; +import com.yunbao.common.R; import java.util.ArrayList; import java.util.List; diff --git a/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java b/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java index d83668492..fee7cbbc5 100644 --- a/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java +++ b/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java @@ -17,6 +17,7 @@ import com.yunbao.common.bean.LinkMicUserBeanV2; import com.yunbao.common.bean.LiveAiRobotBean; import com.yunbao.common.bean.LiveInfoModel; import com.yunbao.common.bean.LiveRoomActivityBanner; +import com.yunbao.common.bean.LiveStetUpStatusModel; import com.yunbao.common.bean.NobleRankHideUserListModel; import com.yunbao.common.bean.NobleTrumpetModel; import com.yunbao.common.bean.PkRankBean; @@ -1034,6 +1035,34 @@ public class LiveNetManager { }).isDisposed(); } + /** + * 开播设置数据获取 + * + * @param liveUid + * @param callback + */ + public void getLiveStetUpStatus(String liveUid, HttpCallback callback) { + API.get().pdLiveApi(mContext) + .getLiveStetUpStatus(liveUid) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer>() { + @Override + public void accept(ResponseModel liveStetUpStatusModelResponseModel) throws Exception { + if (callback != null) { + callback.onSuccess(liveStetUpStatusModelResponseModel.getData().getInfo()); + } + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + if (callback != null) { + callback.onError(throwable.getMessage()); + } + } + }).isDisposed(); + } + /** * 直播间取消网络请求 */ diff --git a/common/src/main/java/com/yunbao/common/views/LiveOpenCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveOpenCustomPopup.java new file mode 100644 index 000000000..784fd7004 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/views/LiveOpenCustomPopup.java @@ -0,0 +1,178 @@ +package com.yunbao.common.views; + +import android.content.Context; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.lxj.xpopup.core.CenterPopupView; +import com.yunbao.common.R; +import com.yunbao.common.bean.LiveClassBean; +import com.yunbao.common.bean.LiveRoomTypeBean; +import com.yunbao.common.bean.LiveStetUpStatusModel; +import com.yunbao.common.http.base.HttpCallback; +import com.yunbao.common.http.live.LiveNetManager; +import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.utils.ToastUtil; +import com.yunbao.common.views.weight.ViewClicksAntiShake; + +public class LiveOpenCustomPopup extends CenterPopupView { + //清晰度 + private int selectClarity; + //直播类型 + private LiveClassBean classBean; + //房间类型 + private LiveRoomTypeBean liveRoomTypeBean; + + private TextView textClarity, textLiveRoomType, textLiveClass, textLiveWishlist, textRobot; + + public LiveOpenCustomPopup setClassBean(LiveClassBean classBean) { + this.classBean = classBean; + textLiveClass.setText(classBean.getName()); + return this; + } + + public LiveOpenCustomPopup setLiveRoomTypeBean(LiveRoomTypeBean liveRoomTypeBean) { + this.liveRoomTypeBean = liveRoomTypeBean; + textLiveRoomType.setText(liveRoomTypeBean.getName()); + return this; + } + + public LiveOpenCustomPopup(@NonNull Context context, int selectClarity, LiveClassBean classBean, LiveRoomTypeBean liveRoomTypeBean) { + super(context); + this.selectClarity = selectClarity; + this.classBean = classBean; + this.liveRoomTypeBean = liveRoomTypeBean; + } + + // 返回自定义弹窗的布局 + @Override + protected int getImplLayoutId() { + return R.layout.view_live_open; + } + + // 执行初始化操作,比如:findView,设置点击,或者任何你弹窗内的业务逻辑 + @Override + protected void onCreate() { + super.onCreate(); + initView(); + initDate(); + } + + private void initView() { + textClarity = findViewById(R.id.text_clarity); + textLiveRoomType = findViewById(R.id.text_live_room_type); + textLiveClass = findViewById(R.id.text_live_class); + textLiveWishlist = findViewById(R.id.text_live_wishlist); + textRobot = findViewById(R.id.text_robot); + if (classBean != null) { + textLiveClass.setText(classBean.getName()); + } + if (liveRoomTypeBean != null) { + textLiveRoomType.setText(liveRoomTypeBean.getName()); + } + setSelectClarity(selectClarity); + //關閉彈窗 + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.live_open_cancel), () -> dismiss()); + //開播 + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.live_open_ok), () -> { + if (callBack != null) { + callBack.startLive(liveRoomTypeBean, classBean); + } + dismiss(); + }); + //設置直播類型 + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.line_live_class), () -> { + if (callBack != null) { + callBack.openLiveClass(classBean); + } + }); + //設置清晰度 + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.line_clarity), () -> { + if (callBack != null) { + callBack.selectClarity(selectClarity); + } + }); + //設置房間類型 + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.line_live_room_type), () -> { + if (callBack != null) { + callBack.openLiveRoomType(liveRoomTypeBean); + } + }); + //打開心願單 + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.line_live_wishlist), () -> { + if (callBack != null) { + callBack.openWishlist(); + } + }); + //設置機器人 + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.line_robot), new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + if (callBack != null) { + callBack.openRobot(); + } + } + }); + } + + public void setSelectClarity(int selectClarity) { + switch (selectClarity) { + case 0: + textClarity.setText(R.string.standard_clear); + break; + case 1: + textClarity.setText(R.string.high_definition); + break; + case 2: + textClarity.setText(R.string.ultra_hd); + break; + } + } + + public void initDate() { + LiveNetManager.get(getContext()) + .getLiveStetUpStatus(String.valueOf(IMLoginManager.get(getContext()).getUserInfo().getId()), + new HttpCallback() { + @Override + public void onSuccess(LiveStetUpStatusModel data) { + textLiveWishlist.setText(data.getWishListState() ? R.string.do_set : R.string.not_set); + textRobot.setText(data.getAiStateState() ? R.string.robot_yes : R.string.robot_no); + } + + @Override + public void onError(String error) { + ToastUtil.show(error); + } + }); + + + } + + private LiveOpenCallBack callBack; + + public LiveOpenCustomPopup setCallBack(LiveOpenCallBack callBack) { + this.callBack = callBack; + return this; + } + + public interface LiveOpenCallBack { + //開播 + void startLive(LiveRoomTypeBean liveRoomTypeBean, LiveClassBean classBean); + + //選擇清晰度 + void selectClarity(int selectClarity); + + //打開機器人 + void openRobot(); + + //打開直播間類型 + void openLiveRoomType(LiveRoomTypeBean liveRoomTypeBean); + + //打開直播類型 + void openLiveClass(LiveClassBean classBean); + + //打開心願單 + void openWishlist(); + } +} diff --git a/common/src/main/java/com/yunbao/common/views/LiveRobotSettingCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveRobotSettingCustomPopup.java index f954a8ce7..e8e195c49 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveRobotSettingCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveRobotSettingCustomPopup.java @@ -1,7 +1,6 @@ package com.yunbao.common.views; import android.content.Context; -import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.EditorInfo; @@ -24,8 +23,6 @@ import com.yunbao.common.http.base.HttpCallback; import com.yunbao.common.http.live.LiveNetManager; import com.yunbao.common.utils.ToastUtil; -import java.util.List; - public class LiveRobotSettingCustomPopup extends BottomPopupView implements View.OnClickListener { private static String TAG = "AI机器人"; private EditText robotNameSetting; @@ -36,6 +33,10 @@ public class LiveRobotSettingCustomPopup extends BottomPopupView implements View private int robotStateInt = 1; + public int getRobotStateInt() { + return robotStateInt; + } + public LiveRobotSettingCustomPopup(@NonNull Context context) { super(context); } diff --git a/common/src/main/res/drawable/backgroud_live_open_lfet.xml b/common/src/main/res/drawable/backgroud_live_open_lfet.xml new file mode 100644 index 000000000..d35f34c4c --- /dev/null +++ b/common/src/main/res/drawable/backgroud_live_open_lfet.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/common/src/main/res/drawable/backgroud_live_open_right.xml b/common/src/main/res/drawable/backgroud_live_open_right.xml new file mode 100644 index 000000000..314b5166d --- /dev/null +++ b/common/src/main/res/drawable/backgroud_live_open_right.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/common/src/main/res/layout/view_live_open.xml b/common/src/main/res/layout/view_live_open.xml new file mode 100644 index 000000000..d40b58280 --- /dev/null +++ b/common/src/main/res/layout/view_live_open.xml @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/live/src/main/res/mipmap-mdpi/icon_live_type_normal_1.png b/common/src/main/res/mipmap-xxhdpi/icon_live_type_normal_1.png similarity index 100% rename from live/src/main/res/mipmap-mdpi/icon_live_type_normal_1.png rename to common/src/main/res/mipmap-xxhdpi/icon_live_type_normal_1.png diff --git a/live/src/main/res/mipmap-mdpi/icon_live_type_normal_2.png b/common/src/main/res/mipmap-xxhdpi/icon_live_type_normal_2.png similarity index 100% rename from live/src/main/res/mipmap-mdpi/icon_live_type_normal_2.png rename to common/src/main/res/mipmap-xxhdpi/icon_live_type_normal_2.png diff --git a/live/src/main/res/mipmap-mdpi/icon_live_type_pay_1.png b/common/src/main/res/mipmap-xxhdpi/icon_live_type_pay_1.png similarity index 100% rename from live/src/main/res/mipmap-mdpi/icon_live_type_pay_1.png rename to common/src/main/res/mipmap-xxhdpi/icon_live_type_pay_1.png diff --git a/live/src/main/res/mipmap-mdpi/icon_live_type_pay_2.png b/common/src/main/res/mipmap-xxhdpi/icon_live_type_pay_2.png similarity index 100% rename from live/src/main/res/mipmap-mdpi/icon_live_type_pay_2.png rename to common/src/main/res/mipmap-xxhdpi/icon_live_type_pay_2.png diff --git a/live/src/main/res/mipmap-mdpi/icon_live_type_pwd_1.png b/common/src/main/res/mipmap-xxhdpi/icon_live_type_pwd_1.png similarity index 100% rename from live/src/main/res/mipmap-mdpi/icon_live_type_pwd_1.png rename to common/src/main/res/mipmap-xxhdpi/icon_live_type_pwd_1.png diff --git a/live/src/main/res/mipmap-mdpi/icon_live_type_pwd_2.png b/common/src/main/res/mipmap-xxhdpi/icon_live_type_pwd_2.png similarity index 100% rename from live/src/main/res/mipmap-mdpi/icon_live_type_pwd_2.png rename to common/src/main/res/mipmap-xxhdpi/icon_live_type_pwd_2.png diff --git a/live/src/main/res/mipmap-mdpi/icon_live_type_time_1.png b/common/src/main/res/mipmap-xxhdpi/icon_live_type_time_1.png similarity index 100% rename from live/src/main/res/mipmap-mdpi/icon_live_type_time_1.png rename to common/src/main/res/mipmap-xxhdpi/icon_live_type_time_1.png diff --git a/live/src/main/res/mipmap-mdpi/icon_live_type_time_2.png b/common/src/main/res/mipmap-xxhdpi/icon_live_type_time_2.png similarity index 100% rename from live/src/main/res/mipmap-mdpi/icon_live_type_time_2.png rename to common/src/main/res/mipmap-xxhdpi/icon_live_type_time_2.png diff --git a/common/src/main/res/mipmap-xxhdpi/icon_more_open.png b/common/src/main/res/mipmap-xxhdpi/icon_more_open.png new file mode 100644 index 0000000000000000000000000000000000000000..36f5f84f322ad836b7b5b95eb6787de9d8a5aced GIT binary patch literal 632 zcmV-;0*C#HP)Px%GD$>1R7gw3*H1_kVHgJR=b3h;s4O8uf)IBsFbd5icZML$2s%eb5J3lzMMk$S z9lTbQojTMZIz$u^1mP{R{Z^6wK^NVbI;T-awX4{?;b==b-#Rn$MSK1B{qYR*?)Sb+ zd24UQPq_o&00cu=SKr6IZ@yxcABt+e4?%CWo*c#&>o9keW>#ZTRBjp~^~;JM!0}Iz zl(Z2jA6*}I<^q|W1L*#0W!n1Tg+)RT~LH{; z$;*Kb)q;y?A0)V?Pr~bT{qw27MRWiXT+*WC1v>t<fDFF1!5k`Lje|h>qIZ zF&7j8Y||w5v35{V2Fn(?E-ls$fjW)KJ{^^Oy%R!WF?)nmCo4a6*jsT-W z%IFxC*X^58nJyR^^hQ?^nC+h>+cy??QA8eWNwFYSi^R{REafH>d! SN902Q0000流暢 超高清 確定清晰度開播後,需要重新開播才能更改 + 開播設置確認 + 清晰度 + 直播頻道 + 開播 + 機器人 + 已設置 + 未設置 + + diff --git a/live/src/main/java/com/yunbao/live/activity/LiveTRTCAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveTRTCAnchorActivity.java index 4694aa2bc..205fd0032 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveTRTCAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveTRTCAnchorActivity.java @@ -31,7 +31,7 @@ import com.yunbao.common.utils.StringUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.WordUtil; import com.yunbao.live.R; -import com.yunbao.live.bean.LiveRoomTypeBean; +import com.yunbao.common.bean.LiveRoomTypeBean; import com.yunbao.live.dialog.LiveBeautyDialogFragment; import com.yunbao.live.dialog.LiveRoomTypeDialogFragment; import com.yunbao.live.http.LiveHttpUtil; @@ -213,7 +213,7 @@ public class LiveTRTCAnchorActivity extends TRTCBaseActivity { return; } String title = mEditTitle.getText().toString().trim(); - LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, null, new HttpCallback() { + LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, null,0, new HttpCallback() { @Override public void onSuccess(int code, String msg, final String[] info) { if (code == 0 && info.length > 0) { diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveRoomTypeAdapter.java b/live/src/main/java/com/yunbao/live/adapter/LiveRoomTypeAdapter.java index 431ea0971..61dc2da23 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveRoomTypeAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveRoomTypeAdapter.java @@ -15,7 +15,7 @@ import com.yunbao.common.CommonAppConfig; import com.yunbao.common.bean.ConfigBean; import com.yunbao.common.interfaces.OnItemClickListener; import com.yunbao.live.R; -import com.yunbao.live.bean.LiveRoomTypeBean; +import com.yunbao.common.bean.LiveRoomTypeBean; import java.util.ArrayList; import java.util.Arrays; diff --git a/live/src/main/java/com/yunbao/live/dialog/LiveNewRoomClassDialogFragment.java b/live/src/main/java/com/yunbao/live/dialog/LiveNewRoomClassDialogFragment.java index 6bf49ae81..f2ba058b5 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LiveNewRoomClassDialogFragment.java +++ b/live/src/main/java/com/yunbao/live/dialog/LiveNewRoomClassDialogFragment.java @@ -18,7 +18,6 @@ import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.OnItemClickListener; import com.yunbao.live.R; import com.yunbao.live.adapter.LiveReadyClassAdapter; -import com.yunbao.live.bean.LiveRoomTypeBean; import java.util.ArrayList; import java.util.List; diff --git a/live/src/main/java/com/yunbao/live/dialog/LiveNewRoomTypeDialogFragment.java b/live/src/main/java/com/yunbao/live/dialog/LiveNewRoomTypeDialogFragment.java index 7f853b10e..946af6304 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LiveNewRoomTypeDialogFragment.java +++ b/live/src/main/java/com/yunbao/live/dialog/LiveNewRoomTypeDialogFragment.java @@ -19,7 +19,7 @@ import com.yunbao.common.interfaces.OnItemClickListener; import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.WordUtil; import com.yunbao.live.R; -import com.yunbao.live.bean.LiveRoomTypeBean; +import com.yunbao.common.bean.LiveRoomTypeBean; import java.util.ArrayList; import java.util.Arrays; diff --git a/live/src/main/java/com/yunbao/live/dialog/LiveRoomTypeDialogFragment.java b/live/src/main/java/com/yunbao/live/dialog/LiveRoomTypeDialogFragment.java index be42aaecf..933dd3339 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LiveRoomTypeDialogFragment.java +++ b/live/src/main/java/com/yunbao/live/dialog/LiveRoomTypeDialogFragment.java @@ -14,7 +14,7 @@ import com.yunbao.common.interfaces.OnItemClickListener; import com.yunbao.common.utils.DpUtil; import com.yunbao.live.R; import com.yunbao.live.adapter.LiveRoomTypeAdapter; -import com.yunbao.live.bean.LiveRoomTypeBean; +import com.yunbao.common.bean.LiveRoomTypeBean; /** * Created by cxf on 2018/10/8. diff --git a/live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java b/live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java index 864ec1fe6..39b9b26d5 100644 --- a/live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java +++ b/live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java @@ -47,10 +47,11 @@ public class LiveHttpUtil { /** * 获取直播用户日榜/周榜 - * @param liveUid 主播uid + * + * @param liveUid 主播uid * @param callback 回调 */ - public static void getUserRankList(String liveUid,HttpCallback callback){ + public static void getUserRankList(String liveUid, HttpCallback callback) { HttpClient.getInstance().get("Contribute.index", LiveHttpConsts.GET_USER_LIST) .params("uid", liveUid) .execute(callback); @@ -685,7 +686,7 @@ public class LiveHttpUtil { * @param file 封面图片文件 * @param callback */ - public static void newcreateRoom(String title, int liveClassId, int type, int typeVal, File file, HttpCallback callback) { + public static void newcreateRoom(String title, int liveClassId, int type, int typeVal, File file, int clarityType, HttpCallback callback) { PostRequest request = HttpClient.getInstance().post("Live.createRoom2", LiveHttpConsts.CREATE_ROOM) .params("title", title) @@ -693,7 +694,8 @@ public class LiveHttpUtil { .params("type", type) .params("landscape", "2") .params("class_type", "0") - .params("type_val", typeVal); + .params("type_val", typeVal) + .params("clarityType ", clarityType); if (file != null) { request.params("file", file); } @@ -902,16 +904,17 @@ public class LiveHttpUtil { /** * 获取用户贵族喇叭的数量 */ - public static void nobleUseTrumpet(String trumpet_msg,String anchor_id,HttpCallback callback) { + public static void nobleUseTrumpet(String trumpet_msg, String anchor_id, HttpCallback callback) { HttpClient.getInstance().get("Noble.nobleUseTrumpet", "nobleUseTrumpet") .params("", trumpet_msg) .params("", anchor_id) .execute(callback); } + /** * 获取用户贵族喇叭的数量 */ - public static void getStarChallengeStatus(String liveUid,HttpCallback callback) { + public static void getStarChallengeStatus(String liveUid, HttpCallback callback) { HttpClient.getInstance().get("StarChallenge.getStarChallengeStatus", "StarChallengeStatus") .params("liveUid", liveUid) .execute(callback); diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index 019a85805..202f538fe 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -1,5 +1,7 @@ package com.yunbao.live.views; +import static com.yunbao.live.event.LiveAudienceEvent.LiveAudienceType.WISH_LIST_UPDATE; + import android.app.Dialog; import android.content.Context; import android.graphics.drawable.Drawable; @@ -23,6 +25,7 @@ import com.lxj.xpopup.interfaces.XPopupCallback; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.Constants; import com.yunbao.common.bean.LiveClassBean; +import com.yunbao.common.bean.LiveRoomTypeBean; import com.yunbao.common.bean.UserBean; import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; @@ -37,21 +40,25 @@ import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.WordUtil; import com.yunbao.common.views.AbsViewHolder; import com.yunbao.common.views.LiveClarityCustomPopup; +import com.yunbao.common.views.LiveOpenCustomPopup; import com.yunbao.common.views.LiveRobotSettingCustomPopup; import com.yunbao.common.views.weight.ViewClicksAntiShake; import com.yunbao.faceunity.FaceManager; import com.yunbao.live.R; import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveRyAnchorActivity; -import com.yunbao.live.bean.LiveRoomTypeBean; import com.yunbao.live.dialog.LiveFaceUnityDialogFragment; import com.yunbao.live.dialog.LiveNewRoomClassDialogFragment; import com.yunbao.live.dialog.LiveNewRoomTypeDialogFragment; import com.yunbao.live.dialog.LiveNewWishListDialogFragment; import com.yunbao.live.dialog.LiveTimeDialogFragment; +import com.yunbao.live.event.LiveAudienceEvent; import com.yunbao.live.http.LiveHttpConsts; import com.yunbao.live.http.LiveHttpUtil; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + import java.io.File; import cn.rongcloud.rtc.api.RCRTCEngine; @@ -78,6 +85,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl private TextView faceTextView;//提示人脸未检测到的TextView private ImageView imgClarity; private int selectClarity = 1; + private LiveOpenCustomPopup liveOpenCustomPopup; public LiveNewReadyRyViewHolder(Context context, ViewGroup parentView, int liveSdk) { super(context, parentView, liveSdk); @@ -269,6 +277,9 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl liveClarity.setText(R.string.ultra_hd); break; } + if (liveOpenCustomPopup != null) { + liveOpenCustomPopup.setSelectClarity(selectClarity); + } } public void setManager(FaceManager manager) { @@ -299,8 +310,156 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl } else if (i == R.id.btn_room_type) { chooseLiveType(); } else if (i == R.id.btn_start_live) { - startLive(); +// startLive(); + liveOpenCustomPopup = new LiveOpenCustomPopup(mContext, selectClarity, classBean, liveRoomTypeBean) + .setCallBack(new LiveOpenCustomPopup.LiveOpenCallBack() { + @Override + public void startLive(LiveRoomTypeBean liveRoomTypeModel, LiveClassBean classModel) { + if (classModel != null) { + classBean = classModel; + mLiveClassID = classBean.getId(); + } + liveRoomTypeBean = liveRoomTypeModel; + mLiveType = liveRoomTypeModel.getId(); + startLiveInit(); + liveOpenCustomPopup = null; + } + @Override + public void selectClarity(int selectClarity) { + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, selectClarity); + new XPopup.Builder(mContext) + .setPopupCallback(new XPopupCallback() { + @Override + public void onCreated(BasePopupView popupView) { + + } + + @Override + public void beforeShow(BasePopupView popupView) { + + } + + @Override + public void onShow(BasePopupView popupView) { + + } + + @Override + public void onDismiss(BasePopupView popupView) { + setSelectClarity(liveClarityCustomPopup.getSelectClarity()); + } + + @Override + public void beforeDismiss(BasePopupView popupView) { + + } + + @Override + public boolean onBackPressed(BasePopupView popupView) { + return false; + } + + @Override + public void onKeyBoardStateChanged(BasePopupView popupView, int height) { + + } + + @Override + public void onDrag(BasePopupView popupView, int value, float percent, boolean upOrLeft) { + + } + + @Override + public void onClickOutside(BasePopupView popupView) { + + } + }) + .asCustom(liveClarityCustomPopup) + .show(); + } + + @Override + public void openRobot() { + LiveRobotSettingCustomPopup liveRobotSettingCustomPopup = new LiveRobotSettingCustomPopup(mContext); + new XPopup.Builder(mContext) + .setPopupCallback(new XPopupCallback() { + @Override + public void onCreated(BasePopupView popupView) { + + } + + @Override + public void beforeShow(BasePopupView popupView) { + + } + + @Override + public void onShow(BasePopupView popupView) { + + } + + @Override + public void onDismiss(BasePopupView popupView) { + if (liveOpenCustomPopup != null) { + liveOpenCustomPopup.initDate(); + } + } + + @Override + public void beforeDismiss(BasePopupView popupView) { + + } + + @Override + public boolean onBackPressed(BasePopupView popupView) { + return false; + } + + @Override + public void onKeyBoardStateChanged(BasePopupView popupView, int height) { + + } + + @Override + public void onDrag(BasePopupView popupView, int value, float percent, boolean upOrLeft) { + + } + + @Override + public void onClickOutside(BasePopupView popupView) { + + } + }) + .asCustom(liveRobotSettingCustomPopup) + .show(); + } + + @Override + public void openLiveRoomType(LiveRoomTypeBean liveRoomTypeModel) { + liveRoomTypeBean = liveRoomTypeModel; + mLiveType = liveRoomTypeModel.getId(); + chooseLiveType(); + } + + @Override + public void openLiveClass(LiveClassBean classModel) { + if (classModel != null) { + classBean = classModel; + mLiveClassID = classBean.getId(); + } + chooseLiveClass(); + } + + @Override + public void openWishlist() { + //点击心愿单 + openWishListWindow(); + } + }); + new XPopup.Builder(mContext) + .asCustom(liveOpenCustomPopup) + .show(); } else if (i == R.id.btn_locaiton) { switchLocation(); } else if (i == R.id.btn_horizontally) { @@ -337,6 +496,16 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl if (mContext instanceof LiveRyAnchorActivity) { fragment.show(((LiveRyAnchorActivity) mContext).getSupportFragmentManager(), "RY"); + + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void updateStart(LiveAudienceEvent event) { + if (event.getType() == WISH_LIST_UPDATE) { + if (liveOpenCustomPopup != null) { + liveOpenCustomPopup.initDate(); + } } } @@ -424,6 +593,9 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl classBean = bean; mLiveClassID = classBean.getId(); mLiveClass.setText(bean.getName()); + if (liveOpenCustomPopup != null) { + liveOpenCustomPopup.setClassBean(classBean); + } } }); fragment.show(((LiveRyAnchorActivity) mContext).getSupportFragmentManager(), "LiveRoomTypeDialogFragment"); @@ -443,6 +615,8 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl /** * 选择直播类型 */ + private LiveRoomTypeBean liveRoomTypeBean = new LiveRoomTypeBean(0, WordUtil.getString(R.string.live_room_public)); + private void chooseLiveType() { Bundle bundle = new Bundle(); bundle.putInt(Constants.CHECKED_ID, mLiveType); @@ -451,6 +625,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl fragment.setCallback(new CommonCallback() { @Override public void callback(LiveRoomTypeBean bean) { + liveRoomTypeBean = bean; switch (bean.getId()) { case Constants.LIVE_TYPE_NORMAL: onLiveTypeNormal(bean); @@ -465,6 +640,9 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl onLiveTypeTime(bean); break; } + if (liveOpenCustomPopup != null) { + liveOpenCustomPopup.setLiveRoomTypeBean(liveRoomTypeBean); + } } }); fragment.show(((LiveRyAnchorActivity) mContext).getSupportFragmentManager(), "LiveRoomTypeDialogFragment"); @@ -560,7 +738,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl /** * 点击开始直播按钮 */ - private void startLive() { + private void startLiveInit() { boolean startPreview = ((LiveRyAnchorActivity) mContext).isStartPreview(); // if (!startPreview) { // ToastUtil.show(R.string.please_wait); @@ -586,7 +764,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl return; } String title = mEditTitle.getText().toString().trim(); - LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, mAvatarFile, new HttpCallback() { + LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, mAvatarFile, selectClarity + 1, new HttpCallback() { @Override public void onSuccess(int code, String msg, final String[] info) { if (code == 0 && info.length > 0) { diff --git a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java index a3c663c54..6d0da307f 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java @@ -565,7 +565,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX //设置分辨率 .setVideoResolution(RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_640) //设置帧率 - .setVideoFps(RCRTCParamsType.RCRTCVideoFps.Fps_30) + .setVideoFps(RCRTCParamsType.RCRTCVideoFps.Fps_24) //设置最小码率,480P下推荐200 .setMinRate(250) //设置最大码率,480P下推荐900 @@ -732,7 +732,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX int height = 1280; normal.setWidth(width); //视频宽 normal.setHeight(height); //视频高 - normal.setFps(fps); //视频帧率 + normal.setFps(25); //视频帧率 //2. 合流画布设置 //(请参照画布和声音配置示例代码) diff --git a/live/src/main/java/com/yunbao/live/views/LiveReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveReadyRyViewHolder.java index 33eb8b29c..6575c81cb 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveReadyRyViewHolder.java @@ -36,7 +36,7 @@ import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveChooseClassActivity; import com.yunbao.live.activity.LiveRyAnchorActivity; import com.yunbao.live.adapter.LiveReadyShareAdapter; -import com.yunbao.live.bean.LiveRoomTypeBean; +import com.yunbao.common.bean.LiveRoomTypeBean; import com.yunbao.live.dialog.LiveRoomTypeDialogFragment; import com.yunbao.live.dialog.LiveTimeDialogFragment; import com.yunbao.live.dialog.LiveWishListDialogFragment; @@ -471,7 +471,7 @@ public class LiveReadyRyViewHolder extends AbsViewHolder implements View.OnClick return; } String title = mEditTitle.getText().toString().trim(); - LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, mAvatarFile, new HttpCallback() { + LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, mAvatarFile,0, new HttpCallback() { @Override public void onSuccess(int code, String msg, final String[] info) { if (code == 0 && info.length > 0) { diff --git a/live/src/main/java/com/yunbao/live/views/LiveReadyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveReadyViewHolder.java index 1918953a4..4da9ea036 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveReadyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveReadyViewHolder.java @@ -1,12 +1,13 @@ package com.yunbao.live.views; +import static com.tencent.trtc.TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_DISABLE; +import static com.tencent.trtc.TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_ENABLE; +import static com.yunbao.live.views.LivePushTxViewHolder.mTRTCCloud; + import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import androidx.core.content.ContextCompat; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -17,12 +18,17 @@ import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import com.lzy.okgo.model.Response; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMSendCallback; import com.tencent.trtc.TRTCCloudDef; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.Constants; +import com.yunbao.common.bean.LiveRoomTypeBean; import com.yunbao.common.bean.UserBean; import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; @@ -42,7 +48,6 @@ import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveAnchorActivity; import com.yunbao.live.activity.LiveChooseClassActivity; import com.yunbao.live.adapter.LiveReadyShareAdapter; -import com.yunbao.live.bean.LiveRoomTypeBean; import com.yunbao.live.dialog.LiveRoomTypeDialogFragment; import com.yunbao.live.dialog.LiveTimeDialogFragment; import com.yunbao.live.dialog.LiveWishListDialogFragment; @@ -51,10 +56,6 @@ import com.yunbao.live.http.LiveHttpUtil; import java.io.File; -import static com.tencent.trtc.TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_DISABLE; -import static com.tencent.trtc.TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_ENABLE; -import static com.yunbao.live.views.LivePushTxViewHolder.mTRTCCloud; - /** * Created by cxf on 2018/10/7. * 开播前准备 @@ -491,7 +492,7 @@ public class LiveReadyViewHolder extends AbsViewHolder implements View.OnClickLi return; } String title = mEditTitle.getText().toString().trim(); - LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, mAvatarFile, new HttpCallback() { + LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, mAvatarFile, 0, new HttpCallback() { @Override public void onSuccess(int code, String msg, final String[] info) { if (code == 0 && info.length > 0) { @@ -535,7 +536,7 @@ public class LiveReadyViewHolder extends AbsViewHolder implements View.OnClickLi @Override public void onError(Response response) { super.onError(response); - System.out.println("tx 开播失败 = "+response); + System.out.println("tx 开播失败 = " + response); } }); } From 0b5598346ec68e70ae9c46d06d15c2235811c590 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 29 Dec 2022 17:55:41 +0800 Subject: [PATCH 017/118] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E7=BD=91=E9=80=9F=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/common/utils/DeviceUtils.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/yunbao/common/utils/DeviceUtils.java b/common/src/main/java/com/yunbao/common/utils/DeviceUtils.java index 40f76b35d..b80cfd3cb 100644 --- a/common/src/main/java/com/yunbao/common/utils/DeviceUtils.java +++ b/common/src/main/java/com/yunbao/common/utils/DeviceUtils.java @@ -6,10 +6,15 @@ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Point; +import android.net.TrafficStats; import android.text.format.Formatter; import android.util.DisplayMetrics; import android.view.WindowManager; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStreamReader; + /** * 设备通用类 */ @@ -97,10 +102,38 @@ public class DeviceUtils { return mi.lowMemory; } - public static String getMemory(Context context) { + /** + * 获取可用内存 格式化 + */ + public static String getMemoryToFormat(Context context) { ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); am.getMemoryInfo(mi); return Formatter.formatFileSize(context, mi.availMem);// 将获取的内存大小规格化 } + + /** + * 获取可用内存 + */ + public static String getMemory(Context context) { + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); + am.getMemoryInfo(mi); + return mi.availMem + ""; + } + + private static long lastTotalRxBytes = 0; + private static long lastTimeStamp = 0; + + /** + * 获取上传网速 + */ + public static long getNetSpeed(Context context) { + long nowTotalRxBytes = TrafficStats.getUidTxBytes(context.getApplicationInfo().uid) == TrafficStats.UNSUPPORTED ? 0 : (TrafficStats.getTotalTxBytes() / 1024); + long nowTimeStamp = System.currentTimeMillis(); + long speed = ((nowTotalRxBytes - lastTotalRxBytes) * 1000 / (nowTimeStamp - lastTimeStamp));//毫秒转换 + lastTimeStamp = nowTimeStamp; + lastTotalRxBytes = nowTotalRxBytes; + return speed; + } } \ No newline at end of file From 06b5f999300968c495030bf26279e3ddfc6d37c2 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 29 Dec 2022 18:27:24 +0800 Subject: [PATCH 018/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=88=86=E8=BE=A8?= =?UTF-8?q?=E7=8E=87=E5=8F=82=E6=95=B0=20=E7=A7=BB=E9=99=A4=E8=B0=83?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/views/LiveRoomPlayViewHolder.java | 5 +++-- .../java/com/yunbao/live/views/LiveRoomViewHolder.java | 7 +------ .../java/com/yunbao/live/views/PortraitLiveManager.java | 3 --- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index aa28c3378..78df9fb2f 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -20,8 +20,8 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL public static final int PLAY_MODEL_1080 = 2; public static int PLAY_MODEL = PLAY_MODEL_DEF; - public static final String[] videoRatioHorizontal = new String[]{"_640_480", "_1280_720", "_1920_1080", "_180_180"}; - public static final String[] videoRatioVertical = new String[]{"_480_640", "_720_1280", "_1080_1920", "_180_180"}; + public static final String[] videoRatioHorizontal = new String[]{"_848_480", "_1280_720", "_1920_1080"}; + public static final String[] videoRatioVertical = new String[]{"_480_848", "_720_1280", "_1080_1920"}; public static final String[] videoFps = new String[]{"_24", "_30"}; OnMicCallback onMicCallback;//连麦回调 public EnterRoomNewModel roomModel; @@ -31,6 +31,7 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL } public abstract void play(String url, int playModel); + public abstract void switchStream(String url, int playModel); public abstract void stopPlay(); diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 13075c098..6fa9eaa4a 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -837,12 +837,7 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mLiveUserAdapter.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(UserBean bean, int position) { - if (position < 4) { - ToastUtil.show("切换:" + LiveRoomPlayViewHolder.videoRatioVertical[position]); - PortraitLiveManager.portraitLiveManager.test(position); - } else { - showUserDialog(bean.getId()); - } + showUserDialog(bean.getId()); } }); mUserRecyclerView.setAdapter(mLiveUserAdapter); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index f91dcd5db..6f9d9d03a 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -330,9 +330,6 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe } - public void test(int model) { - mLivePlayViewHolder.play(mLiveBean.getPull(), model); - } private Runnable sendFIm = new Runnable() { @Override From 8b357233c2de9ea04bc192959e252749d039c3e9 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 30 Dec 2022 14:47:25 +0800 Subject: [PATCH 019/118] =?UTF-8?q?=E9=96=8B=E6=92=AD=E8=A8=AD=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=96=8B=E6=92=AD=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=86=E8=BE=A8=E7=8E=87=E8=A8=AD=E7=BD=AE?= =?UTF-8?q?=E5=8F=83=E6=95=B8,=E7=B6=B2=E7=B5=A1=E5=85=A7=E5=AD=98?= =?UTF-8?q?=E6=AA=A2=E6=B8=AC=E5=92=8C=E6=8F=90=E7=A4=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/common/utils/DeviceUtils.java | 2 + .../yunbao/common/views/HintCustomPopup.java | 70 +++++++++++ .../common/views/LiveClarityCustomPopup.java | 88 ++++++++++++-- .../src/main/res/layout/hint_custom_popup.xml | 71 +++++++++++ .../main/res/layout/input_custom_popup.xml | 4 +- common/src/main/res/values-en/strings.xml | 60 ++++++++++ common/src/main/res/values/strings.xml | 89 +++++++------- .../live/activity/LiveRyAnchorActivity.java | 25 ++++ .../live/views/LiveNewReadyRyViewHolder.java | 47 +++++++- .../live/views/LivePushRyViewHolder.java | 111 ++++++++++++------ 10 files changed, 477 insertions(+), 90 deletions(-) create mode 100644 common/src/main/java/com/yunbao/common/views/HintCustomPopup.java create mode 100644 common/src/main/res/layout/hint_custom_popup.xml diff --git a/common/src/main/java/com/yunbao/common/utils/DeviceUtils.java b/common/src/main/java/com/yunbao/common/utils/DeviceUtils.java index b80cfd3cb..d298abdac 100644 --- a/common/src/main/java/com/yunbao/common/utils/DeviceUtils.java +++ b/common/src/main/java/com/yunbao/common/utils/DeviceUtils.java @@ -136,4 +136,6 @@ public class DeviceUtils { lastTotalRxBytes = nowTotalRxBytes; return speed; } + + } \ No newline at end of file diff --git a/common/src/main/java/com/yunbao/common/views/HintCustomPopup.java b/common/src/main/java/com/yunbao/common/views/HintCustomPopup.java new file mode 100644 index 000000000..874c3d1db --- /dev/null +++ b/common/src/main/java/com/yunbao/common/views/HintCustomPopup.java @@ -0,0 +1,70 @@ +package com.yunbao.common.views; + +import android.content.Context; +import android.text.TextUtils; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.lxj.xpopup.core.CenterPopupView; +import com.yunbao.common.R; +import com.yunbao.common.views.weight.ViewClicksAntiShake; + +public class HintCustomPopup extends CenterPopupView { + private String title, contest; + + public HintCustomPopup(@NonNull Context context, String title, String contest) { + super(context); + this.title = title; + this.contest = contest; + } + + public HintCustomPopup(@NonNull Context context) { + super(context); + } + + // 返回自定义弹窗的布局 + @Override + protected int getImplLayoutId() { + return R.layout.hint_custom_popup; + } + + // 执行初始化操作,比如:findView,设置点击,或者任何你弹窗内的业务逻辑 + @Override + protected void onCreate() { + super.onCreate(); + TextView titleText = findViewById(R.id.title); + TextView contestText = findViewById(R.id.contest); + if (!TextUtils.isEmpty(title)) { + titleText.setText(title); + } + if (!TextUtils.isEmpty(contest)) { + contestText.setText(contest); + } + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.live_open_ok), () -> { + if (callBack != null) { + callBack.onSure(); + } + dismiss(); + }); + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.live_open_cancel), () -> { + if (callBack != null) { + callBack.onCancel(); + } + dismiss(); + }); + } + + private HintCustomCallBack callBack; + + public HintCustomPopup setCallBack(HintCustomCallBack callBack) { + this.callBack = callBack; + return this; + } + + public interface HintCustomCallBack { + void onSure(); + + void onCancel(); + } +} diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index 57e701de3..66c537258 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -1,20 +1,27 @@ package com.yunbao.common.views; import android.content.Context; +import android.os.Handler; +import android.text.format.Formatter; +import android.util.Log; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; +import com.lxj.xpopup.XPopup; import com.lxj.xpopup.core.BottomPopupView; import com.yunbao.common.R; -import com.yunbao.common.utils.ToastUtil; +import com.yunbao.common.utils.DeviceUtils; import com.yunbao.common.views.weight.ViewClicksAntiShake; +import java.util.ArrayList; +import java.util.Collections; +import java.util.DoubleSummaryStatistics; +import java.util.List; + public class LiveClarityCustomPopup extends BottomPopupView implements View.OnClickListener { public static final int BAN_720 = 1; public static final int BAN_1080 = 2; @@ -91,16 +98,51 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl }); //高清 ViewClicksAntiShake.clicksAntiShake(lineHd, () -> { - selectClarity = 1; - selectClarity(selectClarity); - dismiss(); + String memorg = formateFileSize(Long.parseLong(DeviceUtils.getMemory(getContext()))); + if (Double.parseDouble(memorg) > 7 && netAverage > 100) { + selectClarity = 1; + selectClarity(selectClarity); + dismiss(); + } else { + new XPopup.Builder(getContext()) + .asCustom(new HintCustomPopup(getContext(), getContext().getString(R.string.net_hint), getContext().getString(R.string.net_hint2)).setCallBack(new HintCustomPopup.HintCustomCallBack() { + @Override + public void onSure() { + selectClarity = 1; + selectClarity(selectClarity); + dismiss(); + } + + @Override + public void onCancel() { + + } + })) + .show(); + } + }); //超高清 ViewClicksAntiShake.clicksAntiShake(lineFhd, () -> { - selectClarity = 2; - selectClarity(selectClarity); - dismiss(); + + new XPopup.Builder(getContext()) + .asCustom(new HintCustomPopup(getContext()).setCallBack(new HintCustomPopup.HintCustomCallBack() { + @Override + public void onSure() { + selectClarity = 2; + selectClarity(selectClarity); + dismiss(); + } + + @Override + public void onCancel() { + + } + })) + .show(); + + }); if (banSelect == BAN_720) { lineFhd.setEnabled(false); @@ -116,6 +158,12 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl } } + //调用系统函数,字符串转换 long -String KB/MB + private String formateFileSize(long size) { + String fileSize = Formatter.formatFileSize(getContext(), size); + return fileSize.substring(0, fileSize.length() - 3); + } + /** * 状态选择 * @@ -150,6 +198,28 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl } } + private Handler netHandler = new Handler(); + private Runnable netRunnable = new Runnable() { + @Override + public void run() { + if (netSpeeds.size() < 11) { + netSpeeds.add(DeviceUtils.getNetSpeed(getContext())); + netHandler.postDelayed(netRunnable, 100); + } else { + long min = Collections.min(netSpeeds); + long max = Collections.max(netSpeeds); + + DoubleSummaryStatistics statistics = netSpeeds.stream().mapToDouble(Number::doubleValue).summaryStatistics(); + netAverage = statistics.getAverage(); + Log.e("网络速度", "最大值:" + max + " 最小值:" + min + " 平均值:" + netAverage); + } + + } + }; + private List netSpeeds = new ArrayList<>(); + private double netAverage = 0; + private void initDate() { + netHandler.postDelayed(netRunnable, 100); } } diff --git a/common/src/main/res/layout/hint_custom_popup.xml b/common/src/main/res/layout/hint_custom_popup.xml new file mode 100644 index 000000000..8b7059e50 --- /dev/null +++ b/common/src/main/res/layout/hint_custom_popup.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/layout/input_custom_popup.xml b/common/src/main/res/layout/input_custom_popup.xml index a7d7aeabb..82ed67cb9 100644 --- a/common/src/main/res/layout/input_custom_popup.xml +++ b/common/src/main/res/layout/input_custom_popup.xml @@ -46,10 +46,10 @@ android:layout_width="87dp" android:layout_height="33dp" android:layout_marginRight="7dp" - android:background="@mipmap/tipbox_btn_gray" + android:background="@drawable/backgroud_live_open_lfet" android:gravity="center" android:text="@string/cancel" - android:textColor="#B1B1B1" + android:textColor="#FFC621" android:textSize="14sp" /> diff --git a/common/src/main/res/values-en/strings.xml b/common/src/main/res/values-en/strings.xml index 6dda75eff..be4a81f99 100644 --- a/common/src/main/res/values-en/strings.xml +++ b/common/src/main/res/values-en/strings.xml @@ -934,4 +934,64 @@ Limited ride And limited avatar frame Blocking gift effects Blocking seat effects If you want to Minimize Play,\nYou can go to set the license. + + + In a batch + Chat + Congratulations %s have won %s in the Lucky Angel! The next lucky angel will be you! + Guardian group %s people + receive + 去完成 + 已領取 + 畫質選擇 + 更多設置 + 查看更多 + 礼物正在获取中... + 開始PK + 剩餘次數:%s + 是否確認進行多人PK(確認後扣除1點次數)當日剩餘次數: %s + 邀請\n主播 + 結束\nPK + 時間 %s + + 接受 + 拒绝 + 坚持拒绝 + 随机PK提示 + + 自動發言機器人設置 + 機器人開關 + 機器人名字設置 + 字數限制2-8個字 + 自動打招呼設置 + 已配置條數 + 自動發消息設置 + 前往設置 + 感謝送禮、PK開始、PK結束的自動機器人消息,\n暫不支持自定義。 + 添加內容 + 每隔一段時間,機器人自動隨機以下一句話發出。 + 填寫內容推薦,如:求送心願單、加粉絲團等 + 自動發言間隔時間(分鐘) + 最少間隔5分鐘1次 + 當有用戶進入直播間時,機器人會@該用戶並自動 + 隨機以下一句話。最少設置1條,最多20條。 + 機器人設置 + 高清 + 流暢 + 超高清 + 確定清晰度開播後,需要重新開播才能更改 + 開播設置確認 + 清晰度 + 直播頻道 + 開播 + 機器人 + 已設置 + 未設置 + + + 超高清提示 + 在網速不穩定的情況下,選擇超高清將會有可能導致直播間畫面卡頓,是否確認選擇? + 堅持選擇 + 網絡提示 + 系統監測到您的網絡不穩定,設備內存不足將會影響到您的直播流暢度,因此建議您選擇流暢清晰度。 diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index baa28ab81..01237fa89 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -723,7 +723,7 @@ 心願單 娛樂整蠱 多人PK - 随机PK + 随机PK 語音連麥 周星榜 暫時離開 @@ -958,13 +958,13 @@ 換一批 聊聊天 想在其他APP上方也顯示小窗,\n可前往設置進行授權。 - 恭喜 %s 在幸運天使中抽中 %s!下一個幸運天使就是你哦! - 守護團%s人 - 領取 - 去完成 - 已領取 - 畫質選擇 - 更多設置 + 恭喜 %s 在幸運天使中抽中 %s!下一個幸運天使就是你哦! + 守護團%s人 + 領取 + 去完成 + 已領取 + 畫質選擇 + 更多設置 查看更多 礼物正在获取中... 開始PK @@ -974,39 +974,44 @@ 結束\nPK 時間 %s - 接受 - 拒绝 - 坚持拒绝 - 随机PK提示 + 接受 + 拒绝 + 坚持拒绝 + 随机PK提示 - 自動發言機器人設置 - 機器人開關 - 機器人名字設置 - 字數限制2-8個字 - 自動打招呼設置 - 已配置條數 - 自動發消息設置 - 前往設置 - 感謝送禮、PK開始、PK結束的自動機器人消息,\n暫不支持自定義。 - 添加內容 - 每隔一段時間,機器人自動隨機以下一句話發出。 - 填寫內容推薦,如:求送心願單、加粉絲團等 - 自動發言間隔時間(分鐘) - 最少間隔5分鐘1次 - 當有用戶進入直播間時,機器人會@該用戶並自動 - 隨機以下一句話。最少設置1條,最多20條。 - 機器人設置 - 高清 - 流暢 - 超高清 - 確定清晰度開播後,需要重新開播才能更改 - 開播設置確認 - 清晰度 - 直播頻道 - 開播 - 機器人 - 已設置 - 未設置 - - + 自動發言機器人設置 + 機器人開關 + 機器人名字設置 + 字數限制2-8個字 + 自動打招呼設置 + 已配置條數 + 自動發消息設置 + 前往設置 + 感謝送禮、PK開始、PK結束的自動機器人消息,\n暫不支持自定義。 + 添加內容 + 每隔一段時間,機器人自動隨機以下一句話發出。 + 填寫內容推薦,如:求送心願單、加粉絲團等 + 自動發言間隔時間(分鐘) + 最少間隔5分鐘1次 + 當有用戶進入直播間時,機器人會@該用戶並自動 + 隨機以下一句話。最少設置1條,最多20條。 + 機器人設置 + 高清 + 流暢 + 超高清 + 確定清晰度開播後,需要重新開播才能更改 + 開播設置確認 + 清晰度 + 直播頻道 + 開播 + 機器人 + 已設置 + 未設置 + + + 超高清提示 + 在網速不穩定的情況下,選擇超高清將會有可能導致直播間畫面卡頓,是否確認選擇? + 堅持選擇 + 網絡提示 + 系統監測到您的網絡不穩定,設備內存不足將會影響到您的直播流暢度,因此建議您選擇流暢清晰度。 diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index f4f8b8178..782aa7d2e 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -112,10 +112,14 @@ import org.greenrobot.eventbus.ThreadMode; import java.io.File; import java.util.List; +import java.util.Map; import java.util.Random; import cn.rongcloud.rtc.api.RCRTCEngine; import cn.rongcloud.rtc.api.callback.IRCRTCResultCallback; +import cn.rongcloud.rtc.api.callback.IRCRTCStatusReportListener; +import cn.rongcloud.rtc.api.report.StatusBean; +import cn.rongcloud.rtc.api.report.StatusReport; import cn.rongcloud.rtc.base.RCRTCRect; import cn.rongcloud.rtc.base.RTCErrorCode; import io.rong.imlib.IRongCallback; @@ -208,6 +212,27 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl Bus.getOn(this); Intent intent = getIntent(); initFaceManager(); +// RCRTCEngine.getInstance().registerStatusReportListener(new IRCRTCStatusReportListener() { +// +// @Override +// public void onConnectionStats(StatusReport statusReport) { +// //视频发送信息 +// for (Map.Entry entry : statusReport.statusVideoSends.entrySet()) { +// StatusBean statusBean = entry.getValue(); +// //获取userID +// String userId = statusBean.uid; +// //获取视频 宽x高@帧率 +// String resolution = statusBean.frameWidth + "x" + statusBean.frameHeight + "@" + statusBean.frameRate; +// //获取码率 +// long bitRate = statusBean.bitRate; +// //丢包率 +// long lossRate = statusBean.packetLostRate; +// //带宽 +// String googAvailableSendBandwidth = statusReport.googAvailableSendBandwidth; +// Log.e("网速和内存", "码率:" +bitRate+ " 丢包率:" + lossRate+" 带宽:"+googAvailableSendBandwidth); +// } +// } +// }); leave_img = findViewById(R.id.leave_img); mLiveSDK = intent.getIntExtra(Constants.LIVE_SDK, Constants.LIVE_SDK_KSY); mLiveKsyConfigBean = intent.getParcelableExtra(Constants.LIVE_KSY_CONFIG); diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index 202f538fe..f1b802e43 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -9,6 +9,8 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; +import android.text.format.Formatter; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; @@ -32,6 +34,7 @@ import com.yunbao.common.http.HttpCallback; import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.ImageResultCallback; import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.utils.DeviceUtils; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.L; import com.yunbao.common.utils.ProcessImageUtil; @@ -60,9 +63,15 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.io.File; +import java.util.Map; import cn.rongcloud.rtc.api.RCRTCEngine; +import cn.rongcloud.rtc.api.callback.IRCRTCStatusReportListener; +import cn.rongcloud.rtc.api.report.StatusBean; +import cn.rongcloud.rtc.api.report.StatusReport; import cn.rongcloud.rtc.api.stream.RCRTCCameraOutputStream; +import cn.rongcloud.rtc.api.stream.RCRTCVideoStreamConfig; +import cn.rongcloud.rtc.base.RCRTCParamsType; public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnClickListener { @@ -202,12 +211,16 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl } //设置清晰度 +// DeviceUtils.getMemory(mContext); //获取可用内存 +// DeviceUtils.getNetSpeed(mContext);//获取当前上传网速 +// Log.e("网速和内存", "内存:" + + " 网速:" + DeviceUtils.getNetSpeed(mContext)); + selectClarity = IMLoginManager.get(mContext).getSelectClarity(); setSelectClarity(selectClarity); ViewClicksAntiShake .clicksAntiShake( findViewById(R.id.btn_live_clarity), () -> { - LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, selectClarity); + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, IMLoginManager.get(mContext).getSelectClarity()); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override @@ -261,6 +274,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl } private void setSelectClarity(int selectClarity) { + this.selectClarity = selectClarity; IMLoginManager.get(mContext).setSelectClarity(selectClarity); switch (selectClarity) { @@ -280,12 +294,43 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl if (liveOpenCustomPopup != null) { liveOpenCustomPopup.setSelectClarity(selectClarity); } + //設置開播分辨率 + RCRTCParamsType.RCRTCVideoResolution rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; + int minRate = 200; + int maxRate = 900; + switch (selectClarity) { + case 0: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; + minRate = 200; + maxRate = 900; + break; + case 1: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_720_1280; + minRate = 250; + maxRate = 2200; + break; + case 2: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_1080_1920; + minRate = 400; + maxRate = 4000; + break; + } + RCRTCVideoStreamConfig config = + RCRTCVideoStreamConfig.Builder.create() + .setMinRate(minRate) + .setMaxRate(maxRate) + .setVideoFps(RCRTCParamsType.RCRTCVideoFps.Fps_15) + .setVideoResolution(rcrtcVideoResolution) + .build(); + RCRTCEngine.getInstance().getDefaultVideoStream().setVideoConfig(config); } public void setManager(FaceManager manager) { this.manager = manager; } + + @Override public void onClick(View v) { if (!canClick()) { diff --git a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java index 6d0da307f..b7fc7d1cb 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java @@ -25,7 +25,6 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.alibaba.fastjson.JSONObject; -import com.makeramen.roundedimageview.RoundedImageView; import com.tencent.liteav.device.TXDeviceManager; import com.tencent.rtmp.ITXLivePushListener; import com.tencent.rtmp.TXLiveConstants; @@ -35,11 +34,11 @@ import com.yunbao.common.Constants; import com.yunbao.common.bean.HttpCallbackModel; import com.yunbao.common.bean.UserBean; import com.yunbao.common.event.AnchorInfoEvent; -import com.yunbao.common.event.FollowEvent; import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.http.live.LiveNetManager; +import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.IMRTCManager; import com.yunbao.common.manager.RandomPkManager; import com.yunbao.common.utils.DialogUitl; @@ -72,12 +71,14 @@ import cn.rongcloud.rtc.api.RCRTCRoomConfig; import cn.rongcloud.rtc.api.callback.IRCRTCResultCallback; import cn.rongcloud.rtc.api.callback.IRCRTCResultDataCallback; import cn.rongcloud.rtc.api.callback.IRCRTCRoomEventsListener; +import cn.rongcloud.rtc.api.callback.IRCRTCVideoOutputFrameListener; import cn.rongcloud.rtc.api.stream.RCRTCInputStream; import cn.rongcloud.rtc.api.stream.RCRTCLiveInfo; import cn.rongcloud.rtc.api.stream.RCRTCVideoStreamConfig; import cn.rongcloud.rtc.api.stream.RCRTCVideoView; import cn.rongcloud.rtc.base.RCRTCParamsType; import cn.rongcloud.rtc.base.RCRTCRoomType; +import cn.rongcloud.rtc.base.RCRTCVideoFrame; import cn.rongcloud.rtc.base.RTCErrorCode; import cn.rongcloud.rtc.core.CameraVideoCapturer; import cn.rongcloud.rtc.core.RendererCommon; @@ -114,11 +115,11 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX @Subscribe(threadMode = ThreadMode.MAIN) public void onUPAnchorInfo(AnchorInfoEvent e) { if (e != null) { - if(e.isClear()==false) { + if (e.isClear() == false) { tv_avatarOther_name.setText(e.getUserNiceName()); ImgLoader.displayAvatar(mContext, e.getAvatar(), avatarOther); goto_room_view.setVisibility(View.VISIBLE); - }else{ + } else { goto_room_view.setVisibility(View.GONE); } @@ -417,7 +418,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX @Override public void onConfirmClick(Dialog dialog, String content) { //断开连麦 - LiveRyAnchorActivity.isDRPK=0; + LiveRyAnchorActivity.isDRPK = 0; HttpClient.getInstance().post("livepk.setliveuserout", "livepk.setliveuserout") .execute(new HttpCallback() { @Override @@ -560,16 +561,37 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX RCRTCEngine.getInstance().init(contexts, config); RCRTCEngine.getInstance().getDefaultAudioStream().setAudioQuality(RCRTCParamsType.AudioQuality.MUSIC_HIGH, RCRTCParamsType.AudioScenario.MUSIC_CHATROOM); + //設置開播分辨率 + RCRTCParamsType.RCRTCVideoResolution rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; + int minRate = 200; + int maxRate = 900; + switch (IMLoginManager.get(mContext).getSelectClarity()) { + case 0: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; + minRate = 200; + maxRate = 900; + break; + case 1: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_720_1280; + minRate = 250; + maxRate = 2200; + break; + case 2: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_1080_1920; + minRate = 400; + maxRate = 4000; + break; + } RCRTCVideoStreamConfig videoConfigBuilder = RCRTCVideoStreamConfig.Builder.create() //设置分辨率 - .setVideoResolution(RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_640) + .setVideoResolution(rcrtcVideoResolution) //设置帧率 .setVideoFps(RCRTCParamsType.RCRTCVideoFps.Fps_24) //设置最小码率,480P下推荐200 - .setMinRate(250) + .setMinRate(minRate) //设置最大码率,480P下推荐900 - .setMaxRate(5000) + .setMaxRate(maxRate) .build(); // 创建本地视频显示视图 @@ -595,7 +617,6 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX mPreView.addView(rongRTCVideoView); tencentTRTCBeautyManager = new TencentTRTCBeautyManager(mContext); - //加入房间成功后可以通过 RCRTCLocalUser 对象发布本地默认音视频流,包括:麦克风采集的音频和摄像头采集的视频。 RCRTCEngine.getInstance().getDefaultVideoStream().setEncoderMirror(true); if (rtcRoom == null || rtcRoom.getLocalUser() == null) { @@ -615,20 +636,13 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX room.registerRoomListener(roomEventsListener); //美颜 - new Handler(Looper.getMainLooper()).post(new Runnable() { - public void run() { - //旧美颜不需要了 - /*RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(new IRCRTCVideoOutputFrameListener() { - @Override - public RCRTCVideoFrame processVideoFrame(RCRTCVideoFrame rtcVideoFrame) { - // 使用数据进行美颜/录像等处理后,需要把数据再返回给 SDK 做发送。 - rtcVideoFrame.setTextureId(tencentTRTCBeautyManager.renderWithTexture(rtcVideoFrame.getTextureId(), rtcVideoFrame.getWidth(), rtcVideoFrame.getHeight(), false)); - return rtcVideoFrame; - } - });*/ - - } - }); +// new Handler(Looper.getMainLooper()).post(new Runnable() { +// public void run() { +// //旧美颜不需要了 +// +// +// } +// }); } @Override @@ -716,24 +730,38 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX RCRTCMixConfig config = new RCRTCMixConfig(); RCRTCMixConfig.MediaConfig mediaConfig = new RCRTCMixConfig.MediaConfig(); config.setMediaConfig(mediaConfig); -//视频输出配置 + //视频输出配置 RCRTCMixConfig.MediaConfig.VideoConfig videoConfig = new RCRTCMixConfig.MediaConfig.VideoConfig(); mediaConfig.setVideoConfig(videoConfig); -//大流视频的输出参数 + //大流视频的输出参数 RCRTCMixConfig.MediaConfig.VideoConfig.VideoLayout normal = new RCRTCMixConfig.MediaConfig.VideoConfig.VideoLayout(); - videoConfig.setVideoLayout(normal); -//推荐宽、高、帧率参数值可以通过默认视频流的配置获取,也可以根据实际需求来自定义设置 -//如不设置宽高值则服务端将使用默认宽高 360 * 640 -//例:发布的视频分辨率为720 * 1280,如果不设置则观众端看到的视频分辨率为 360 * 640, -//所以如果想让观众端看到的视频分辨率和发布视频分辨率一致,则应从发布的视频流中获取分辨率配置并设置到 mediaConfig 中 - RCRTCVideoStreamConfig defaultVideoConfig = RCRTCEngine.getInstance().getDefaultVideoStream().getVideoConfig(); - int fps = defaultVideoConfig.getVideoFps().getFps(); - int width = 720; - int height = 1280; + + //推荐宽、高、帧率参数值可以通过默认视频流的配置获取,也可以根据实际需求来自定义设置 + //如不设置宽高值则服务端将使用默认宽高 360 * 640 + //例:发布的视频分辨率为720 * 1280,如果不设置则观众端看到的视频分辨率为 360 * 640, + //所以如果想让观众端看到的视频分辨率和发布视频分辨率一致,则应从发布的视频流中获取分辨率配置并设置到 mediaConfig 中 + //設置開播分辨率 + //設置開播分辨率 + RCRTCParamsType.RCRTCVideoResolution rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; + int minRate = 200; + int maxRate = 900; + switch (IMLoginManager.get(mContext).getSelectClarity()) { + case 0: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_480_848; + break; + case 1: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_720_1280; + break; + case 2: + rcrtcVideoResolution = RCRTCParamsType.RCRTCVideoResolution.RESOLUTION_1080_1920; + break; + } + int width = rcrtcVideoResolution.getWidth(); + int height = rcrtcVideoResolution.getHeight(); normal.setWidth(width); //视频宽 normal.setHeight(height); //视频高 - normal.setFps(25); //视频帧率 - + normal.setFps(15); //视频帧率 + videoConfig.setVideoLayout(normal); //2. 合流画布设置 //(请参照画布和声音配置示例代码) //3. 假设以画布设置的宽高为 300 * 300为例(应以真实设置的宽高为准),设置每个视频流小窗口的坐标及宽高 @@ -747,6 +775,16 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX videoLayout1.setY(0); //Y 坐标 videoLayout1.setWidth(720); // 视频窗口的宽 videoLayout1.setHeight(1280); // 视频窗口的高 + RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(new IRCRTCVideoOutputFrameListener() { + @Override + public RCRTCVideoFrame processVideoFrame(RCRTCVideoFrame rtcVideoFrame) { + // 使用数据进行美颜/录像等处理后,需要把数据再返回给 SDK 做发送。 +// rtcVideoFrame.setTextureId(tencentTRTCBeautyManager.renderWithTexture(rtcVideoFrame.getTextureId(), rtcVideoFrame.getWidth(), rtcVideoFrame.getHeight(), false)); + Log.e("视频流", "Width---------------------" + rtcVideoFrame.getWidth()); + Log.e("视频流", "Height---------------------" + rtcVideoFrame.getHeight()); + return rtcVideoFrame; + } + }); //2. 合流画布设置 rcrtcLiveInfo.setMixConfig(config, new IRCRTCResultCallback() { @Override @@ -762,6 +800,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX }); } + } @Override From 54923304dc47be872410bf401aa5f980e872e0af Mon Sep 17 00:00:00 2001 From: 18142669586 <1669783059@qq.com> Date: Fri, 30 Dec 2022 14:57:47 +0800 Subject: [PATCH 020/118] =?UTF-8?q?=E5=96=AE=E4=BA=BAPK=E5=8D=A10=E5=88=86?= =?UTF-8?q?=20=E5=84=AA=E5=8C=96=E8=A8=88=E7=AE=97=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java | 4 ++-- .../java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java | 4 ++-- live/src/main/res/layout/view_live_push_ry.xml | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index 0c457eab4..942d7f701 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -385,7 +385,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { */ private void changePkTime() { mPkTimeCount--; - if (mPkTimeCount > 0) {// + if (mPkTimeCount >= 0) {// nextPkTimeCountDown(); } else { if (mIsPkEnd) { @@ -398,7 +398,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { // mLiveLinkMicPkViewHolder.removeFromParent(); // mLiveLinkMicPkViewHolder.release(); // } - mLiveLinkMicPkViewHolder = null; +// mLiveLinkMicPkViewHolder = null; } } } diff --git a/live/src/main/java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java index c83022461..0a83e1c49 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveLinkMicPkViewHolder.java @@ -191,8 +191,8 @@ public class LiveLinkMicPkViewHolder extends AbsViewHolder { public void setTime(String content) { if (mTime != null) { Log.i("vvvs",content); - if(content.trim().equals("00:01")||content.trim().equals("00:00")){ - mTime.setText("計算中"); + if(content.trim().equals("00:00")){ + mTime.setText("結算中"); }else { mTime.setText(content); } diff --git a/live/src/main/res/layout/view_live_push_ry.xml b/live/src/main/res/layout/view_live_push_ry.xml index 733b3d72f..550226de5 100644 --- a/live/src/main/res/layout/view_live_push_ry.xml +++ b/live/src/main/res/layout/view_live_push_ry.xml @@ -112,6 +112,7 @@ android:layout_alignParentRight="true" android:layout_marginTop="122dp" android:layout_marginRight="9dp" + android:visibility="gone" android:background="@drawable/bg_live_other_ico" android:gravity="center"> From 488bee514d38c2d0777734d0b909112d51fe7655 Mon Sep 17 00:00:00 2001 From: 18142669586 <1669783059@qq.com> Date: Fri, 30 Dec 2022 16:36:40 +0800 Subject: [PATCH 021/118] =?UTF-8?q?=E5=96=AE=E4=BA=BAPK=E5=8D=A10=E5=88=86?= =?UTF-8?q?=20=E5=84=AA=E5=8C=96=E8=A8=88=E7=AE=97=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/presenter/LiveRyLinkMicPkPresenter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index 942d7f701..ff2473388 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -312,10 +312,10 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { if (mLiveLinkMicPkViewHolder != null) { String s = mIsPkEnd ? mPkTimeString2 : mPkTimeString1; String s1 = StringUtil.getDurationText(mPkTimeCount * 1000); - if (i == 1 && s1.equals("00:01")) { - s1 = "00:00"; - i = 0; - } +// if (i == 1 && s1.equals("00:01")) { +// s1 = "00:00"; +// i = 0; +// } if (rtcRoom != null) { ScreenDimenUtil util = ScreenDimenUtil.getInstance(); int mScreenWdith = util.getScreenWdith(); From 4a0901ea93d8390515cc9d47b38238bf69c26287 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 30 Dec 2022 17:24:46 +0800 Subject: [PATCH 022/118] =?UTF-8?q?=E4=BF=AE=E8=A4=87=E8=B8=A2=E4=BA=BA?= =?UTF-8?q?=E9=82=8F=E8=BC=AF=EF=BC=8C=E5=A2=9E=E5=8A=A0=E7=BF=BB=E8=AD=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/manager/IMLoginManager.java | 4 +- .../views/LiveRobotMessageCustomPopup.java | 37 ++++--- common/src/main/res/values-en/strings.xml | 102 +++++++++--------- .../live/views/LiveNewReadyRyViewHolder.java | 5 + .../live/views/PortraitLiveManager.java | 2 +- 5 files changed, 82 insertions(+), 68 deletions(-) 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 cb0e8a0c6..17ca385cc 100644 --- a/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java +++ b/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java @@ -55,7 +55,9 @@ public class IMLoginManager extends BaseCacheManager { * @return */ public int getSelectClarity() { - return getInt(SELECT_CLARITY, 1); + + return getInt(SELECT_CLARITY, 0); + } public boolean isHint() { diff --git a/common/src/main/java/com/yunbao/common/views/LiveRobotMessageCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveRobotMessageCustomPopup.java index f4652a3d6..7a84549d7 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveRobotMessageCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveRobotMessageCustomPopup.java @@ -111,21 +111,28 @@ public class LiveRobotMessageCustomPopup extends BottomPopupView { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { - // 修改助手名字 - LiveNetManager.get(getContext()) - .setAiRobotDate("ai_time", robotNameSetting.getText().toString(), new HttpCallback() { - @Override - public void onSuccess(HttpCallbackModel data) { - robotNameSetting.setVisibility(GONE); - robotTime.setVisibility(VISIBLE); - robotTime.setText(robotNameSetting.getText().toString()); - } + String time = robotNameSetting.getText().toString(); + int timeInt = Integer.parseInt(time); + if (timeInt > 5) { + // 修改助手名字 + LiveNetManager.get(getContext()) + .setAiRobotDate("ai_time", time, new HttpCallback() { + @Override + public void onSuccess(HttpCallbackModel data) { + robotNameSetting.setVisibility(GONE); + robotTime.setVisibility(VISIBLE); + robotTime.setText(robotNameSetting.getText().toString()); + } + + @Override + public void onError(String error) { + ToastUtil.show(error); + } + }); + } else { + ToastUtil.show(R.string.robot_minimum_interval); + } - @Override - public void onError(String error) { - ToastUtil.show(error); - } - }); } return false; @@ -136,7 +143,7 @@ public class LiveRobotMessageCustomPopup extends BottomPopupView { @Override public void onClick(View v) { new XPopup.Builder(getContext()) - .asCustom(new InputCustomPopup(getContext(),R.string.automatic_message_sending).setListener(new InputCustomPopup.InputCustomListener() { + .asCustom(new InputCustomPopup(getContext(), R.string.automatic_message_sending).setListener(new InputCustomPopup.InputCustomListener() { @Override public void onConfirm(String text) { //添加消息语 diff --git a/common/src/main/res/values-en/strings.xml b/common/src/main/res/values-en/strings.xml index be4a81f99..07b3a9a90 100644 --- a/common/src/main/res/values-en/strings.xml +++ b/common/src/main/res/values-en/strings.xml @@ -941,57 +941,57 @@ Limited ride And limited avatar frame Congratulations %s have won %s in the Lucky Angel! The next lucky angel will be you! Guardian group %s people receive - 去完成 - 已領取 - 畫質選擇 - 更多設置 - 查看更多 - 礼物正在获取中... - 開始PK - 剩餘次數:%s - 是否確認進行多人PK(確認後扣除1點次數)當日剩餘次數: %s - 邀請\n主播 - 結束\nPK - 時間 %s + To complete + Already collected + Image quality selection + More Settings + view more + The gift is on the way... + The gift is on the way + Remaining count :%s + Whether to confirm multiple PK (deduct 1 point after confirmation) remaining times on the day: %s + Invite \n anchor + End \nPK + Time %s - 接受 - 拒绝 - 坚持拒绝 - 随机PK提示 + accept + refuse + Persist in refusing + Random PK hint - 自動發言機器人設置 - 機器人開關 - 機器人名字設置 - 字數限制2-8個字 - 自動打招呼設置 - 已配置條數 - 自動發消息設置 - 前往設置 - 感謝送禮、PK開始、PK結束的自動機器人消息,\n暫不支持自定義。 - 添加內容 - 每隔一段時間,機器人自動隨機以下一句話發出。 - 填寫內容推薦,如:求送心願單、加粉絲團等 - 自動發言間隔時間(分鐘) - 最少間隔5分鐘1次 - 當有用戶進入直播間時,機器人會@該用戶並自動 - 隨機以下一句話。最少設置1條,最多20條。 - 機器人設置 - 高清 - 流暢 - 超高清 - 確定清晰度開播後,需要重新開播才能更改 - 開播設置確認 - 清晰度 - 直播頻道 - 開播 - 機器人 - 已設置 - 未設置 - - - 超高清提示 - 在網速不穩定的情況下,選擇超高清將會有可能導致直播間畫面卡頓,是否確認選擇? - 堅持選擇 - 網絡提示 - 系統監測到您的網絡不穩定,設備內存不足將會影響到您的直播流暢度,因此建議您選擇流暢清晰度。 + Automatic speech robot setup + Robot switch + Robot name setting + The word limit is 2 to 8 word + Automatic greeting setting + Number of configured items + Set automatic message sending + Go to set + Thank you for sending gifts, PK start, PK end automatic robot message, \n does not support customization. + Add content + At regular intervals, the robot automatically says the following sentence at random。 + Fill in the content recommendation, such as: send wish list, add fan group, etc + Automatic speech interval (minutes) + At least once every 5 minutes + When a user enters the studio, the robot will @the user and automatically + The following sentence is random. Set a minimum of 1 to a maximum of 20. + Robot setup + High definition + fluency + Ultra hd + After determining the definition of the broadcast, you need to restart the broadcast to change + Confirmation of broadcast Settings + clarity + Live channel + broadcast + robot + set + Not set + no + yes + Ultra HD hint + In the case of unstable network speed, the selection of ultra HD may lead to the delay of the picture in the broadcast room. Do you confirm the selection? + Stick to choice + Network prompt + The system detects that your network is unstable and insufficient device memory will affect the fluency of your live broadcast. Therefore, it is recommended that you choose fluency and clarity. diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index f1b802e43..418673747 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -355,10 +355,15 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl } else if (i == R.id.btn_room_type) { chooseLiveType(); } else if (i == R.id.btn_start_live) { + if (mLiveClassID == 0) { + ToastUtil.show(R.string.live_choose_live_class); + return; + } // startLive(); liveOpenCustomPopup = new LiveOpenCustomPopup(mContext, selectClarity, classBean, liveRoomTypeBean) .setCallBack(new LiveOpenCustomPopup.LiveOpenCallBack() { @Override + public void startLive(LiveRoomTypeBean liveRoomTypeModel, LiveClassBean classModel) { if (classModel != null) { classBean = classModel; diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 6f9d9d03a..63aa213a2 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -1094,8 +1094,8 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe public void onKick(String touid) { if (!TextUtils.isEmpty(touid) && touid.equals(CommonAppConfig.getInstance().getUid())) {//被踢的是自己 kick = true; - exitLiveRoom(true); ToastUtil.show(WordUtil.getString(R.string.live_kicked_2)); + onRemove(true); } } From 2143e3eb7725f0763e446f074c8390b3f133d2fe Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 3 Jan 2023 09:42:33 +0800 Subject: [PATCH 023/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=AD=85=E5=8A=9B?= =?UTF-8?q?=E6=A6=9C=E8=BF=94=E5=9B=9Eicon=E4=B8=8D=E8=A7=81=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/src/main/res/layout/view_main_list.xml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/main/src/main/res/layout/view_main_list.xml b/main/src/main/res/layout/view_main_list.xml index 50267d721..6b8a4600e 100644 --- a/main/src/main/res/layout/view_main_list.xml +++ b/main/src/main/res/layout/view_main_list.xml @@ -29,10 +29,8 @@ android:id="@+id/btn_back" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginEnd="377dp" - app:layout_constraintBottom_toBottomOf="@+id/indicator" - app:layout_constraintEnd_toEndOf="parent" + android:layout_marginStart="24dp" + android:layout_marginTop="8dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/indicator" app:srcCompat="@mipmap/icon_back_white" /> From 76055543c31b7fd02a5f63319d82483fb3c21ae6 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 3 Jan 2023 11:35:34 +0800 Subject: [PATCH 024/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=94=BB=E8=B4=A8?= =?UTF-8?q?=E9=80=89=E6=8B=A9UI=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/views/LiveClarityCustomPopup.java | 4 +++- .../live/views/LivePlayRyViewHolder.java | 22 +++---------------- .../live/views/LiveRoomPlayViewHolder.java | 1 - .../live/views/PortraitLiveManager.java | 2 +- 4 files changed, 7 insertions(+), 22 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index 66c537258..4a589f89a 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -31,6 +31,7 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl private ImageView titleSDImg, titleHDImg, titleFHDImg; private TextView titleSDText, titleHDText, titleFHDText; private int banSelect; + private boolean isUser = false; public int getSelectClarity() { return selectClarity; @@ -42,6 +43,7 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl if (selectClarity == -1) { selectClarity = 0; } + this.isUser = true; this.selectClarity = selectClarity; } @@ -99,7 +101,7 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl //高清 ViewClicksAntiShake.clicksAntiShake(lineHd, () -> { String memorg = formateFileSize(Long.parseLong(DeviceUtils.getMemory(getContext()))); - if (Double.parseDouble(memorg) > 7 && netAverage > 100) { + if ((Double.parseDouble(memorg) > 7 && netAverage > 100) || isUser) { selectClarity = 1; selectClarity(selectClarity); dismiss(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 62d157f9e..45788c763 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -708,25 +708,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void onDismiss(BasePopupView popupView) { int selectClarity = liveClarityCustomPopup.getSelectClarity(); - if (selectClarity == PLAY_MODEL) return; - if (selectClarity == 2) { - new DialogUitl.Builder(mContext) - .setTitle("超高清提示") - .setContent("在網速不穩定的情況下,選擇超高清將會有可能導致直播間畫面卡頓,是否確認選擇?") - .setConfrimString("堅持選擇") - .setCancelString("返回") - .setClickCallback(new DialogUitl.SimpleCallback() { - @Override - public void onConfirmClick(Dialog dialog, String content) { - switchStream(srcUrl, selectClarity); - dialog.dismiss(); - showToast(); - } - }).build().show(); - } else { - switchStream(srcUrl, selectClarity); - showToast(); - } + if (selectClarity == PLAY_MODEL || PLAY_MODEL == PLAY_MODEL_DEF) return; + switchStream(srcUrl, selectClarity); + showToast(); } private void showToast() { diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index 78df9fb2f..420351b89 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -71,7 +71,6 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL } public void setLiveEnterRoomNewModel(EnterRoomNewModel data) { - data.setClarityType(2); this.roomModel = data; } diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 63aa213a2..0b480f961 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -357,7 +357,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe landscape = data.getLiveInfo().getLandscape(); mLivePlayViewHolder.setLiveBeanLandscape(landscape); mLivePlayViewHolder.setLiveEnterRoomNewModel(data); - mLivePlayViewHolder.switchStream(mLiveBean.getPull(), data.getClarityType() - 1); + mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1)==2?1:(data.getClarityType() - 1)); //是否热度卡加成 liveHandler.postDelayed(() -> mLiveRoomViewHolder.getIsHot(data.getIsUseHotCard()), 700); From 1db24dae4baba5a6f45b8cb6e3d6910afcf88eb3 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 3 Jan 2023 14:26:52 +0800 Subject: [PATCH 025/118] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A7=82=E4=BC=97?= =?UTF-8?q?=E7=AB=AF=E9=80=89=E6=8B=A9=E5=88=86=E8=BE=A8=E7=8E=87=E5=BC=B9?= =?UTF-8?q?=E6=A1=86=E7=9A=84=E4=BB=A3=E7=A0=81=E5=8F=AF=E8=AF=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/views/LivePlayRyViewHolder.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 45788c763..98751cbb3 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -686,7 +686,17 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Subscribe(threadMode = ThreadMode.MAIN) public void onOpenDrawer(LiveAudienceEvent event) { if (event.getType() == LiveAudienceEvent.LiveAudienceType.LIVE_VIDEO) { - int ban = roomModel.getClarityType() - 1 == PLAY_MODEL_720 ? LiveClarityCustomPopup.BAN_1080 : roomModel.getClarityType() - 1 == PLAY_MODEL_480 ? LiveClarityCustomPopup.BAN_720 : 0; + int ban = 0;//全模式都可以选择 + switch (roomModel.getClarityType() - 1) { + case PLAY_MODEL_720://仅允许720(高清),ban掉1080(超高清)模式 + ban = LiveClarityCustomPopup.BAN_1080; + break; + case -1://没有该字段 + case PLAY_MODEL_480://仅允许480(流畅),ban掉1080(超高清)和720(高清)模式 + ban = LiveClarityCustomPopup.BAN_720; + break; + + } LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL, ban); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @@ -1050,7 +1060,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); - // ToastUtil.show("分辨率: width = " + videoSize.width + " height = " + videoSize.height); + // ToastUtil.show("分辨率: width = " + videoSize.width + " height = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { From 4ad2020b57990b3e1294d836525c1dd47dc90140 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 3 Jan 2023 14:35:13 +0800 Subject: [PATCH 026/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A7=82=E4=BC=97?= =?UTF-8?q?=E7=AB=AF=E9=80=89=E6=8B=A9=E5=88=86=E8=BE=A8=E7=8E=87=E6=97=B6?= =?UTF-8?q?=E4=BC=9A=E6=98=BE=E7=A4=BA=E4=B8=BB=E6=92=AD=E7=AB=AF=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E7=9A=84=E6=8F=90=E7=A4=BA=E8=AF=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/common/views/LiveClarityCustomPopup.java | 6 +++++- common/src/main/res/layout/dialog_live_clarity.xml | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index 4a589f89a..e1faf4ba3 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -29,7 +29,7 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl private RelativeLayout lineSd, lineHd, lineFhd; private ImageView iconSd, iconHd, iconFhd; private ImageView titleSDImg, titleHDImg, titleFHDImg; - private TextView titleSDText, titleHDText, titleFHDText; + private TextView titleSDText, titleHDText, titleFHDText, mTips; private int banSelect; private boolean isUser = false; @@ -91,6 +91,10 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl titleSDText = findViewById(R.id.sd_text); titleHDText = findViewById(R.id.hd_text); titleFHDText = findViewById(R.id.fhd_text); + mTips = findViewById(R.id.tips); + if (isUser) { + mTips.setVisibility(INVISIBLE); + } selectClarity(selectClarity); //流畅 ViewClicksAntiShake.clicksAntiShake(lineSd, () -> { diff --git a/common/src/main/res/layout/dialog_live_clarity.xml b/common/src/main/res/layout/dialog_live_clarity.xml index 04d3d5a58..1a45a6d62 100644 --- a/common/src/main/res/layout/dialog_live_clarity.xml +++ b/common/src/main/res/layout/dialog_live_clarity.xml @@ -131,6 +131,7 @@ Date: Tue, 3 Jan 2023 15:11:20 +0800 Subject: [PATCH 027/118] =?UTF-8?q?=E6=96=B0=E5=A2=9EAPk=E5=86=85=E7=BD=AE?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/http/CommonHttpUtil.java | 9 + .../yunbao/common/manager/IMLoginManager.java | 28 +++ .../common/views/APKUpdateCustomPopup.java | 194 ++++++++++++++++++ .../main/res/drawable/bg_apk_update_btn.xml | 5 + common/src/main/res/drawable/progress_bg.xml | 21 ++ .../res/layout/apk_update_custom_popup.xml | 75 +++++++ .../main/res/mipmap-xxhdpi/update_tip_box.png | Bin 0 -> 235610 bytes common/src/main/res/values-en/strings.xml | 4 + common/src/main/res/values/strings.xml | 4 + config.gradle | 2 +- .../yunbao/main/activity/SettingActivity.java | 16 +- .../yunbao/main/adapter/SettingAdapter.java | 35 ++-- .../yunbao/main/views/MainMeViewHolder.java | 19 +- main/src/main/res/layout/view_main_me.xml | 29 ++- 14 files changed, 409 insertions(+), 32 deletions(-) create mode 100644 common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java create mode 100644 common/src/main/res/drawable/bg_apk_update_btn.xml create mode 100644 common/src/main/res/drawable/progress_bg.xml create mode 100644 common/src/main/res/layout/apk_update_custom_popup.xml create mode 100644 common/src/main/res/mipmap-xxhdpi/update_tip_box.png diff --git a/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java b/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java index ccc77a95f..114d2452e 100644 --- a/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java +++ b/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java @@ -199,6 +199,15 @@ public class CommonHttpUtil { JSONArray levelArray = obj.getJSONArray("levelanchor_new"); new NewLevelManager(context).UpAnchorDataLevel(levelArray.toJSONString()); } + if (obj.containsKey("apk_ver")) { + IMLoginManager.get(context).setApkVer(obj.getString("apk_ver")); + } + if (obj.containsKey("apk_url")) { + IMLoginManager.get(context).setAPKUrl(obj.getString("apk_url")); + } + if (obj.containsKey("apk_des")) { + IMLoginManager.get(context).setAPKDes(obj.getString("apk_des")); + } } catch (Exception e) { String error = "info[0]:" + info[0] + "\n\n\n" + "Exception:" + e.getClass() + "---message--->" + e.getMessage(); ErrorActivity.forward("GetConfig接口返回数据异常", error); 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 17ca385cc..846d7afa0 100644 --- a/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java +++ b/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java @@ -18,6 +18,7 @@ import com.yunbao.common.manager.base.BaseCacheManager; import com.yunbao.common.manager.imrongcloud.MessageIMManager; import com.yunbao.common.manager.imrongcloud.RongcloudIMManager; import com.yunbao.common.utils.SpUtil; +import com.yunbao.common.utils.VersionUtil; import com.yunbao.common.views.floatingview.APPEasyFloat; import org.greenrobot.eventbus.EventBus; @@ -39,6 +40,33 @@ public class IMLoginManager extends BaseCacheManager { private final String IS_HINT = "is_hint"; private final String IS_HINT2 = "is_hint2"; private final String SELECT_CLARITY = "selectClarity"; + private final String APK_VER = "apk_ver"; + private final String APK_URL = "apk_url"; + private final String APK_DES = "apk_des"; + + public void setAPKUrl(String apkUrl) { + put(APK_URL, apkUrl); + } + + public void setAPKDes(String apkDes) { + put(APK_DES, apkDes); + } + + public String getAPKUrl() { + return getString(APK_URL); + } + + public String getAPKDes() { + return getString(APK_DES); + } + + public void setApkVer(String apkVer) { + put(APK_VER, apkVer); + } + + public boolean getApkVerNew() { + return TextUtils.equals(VersionUtil.getVersion(), getString(APK_VER)); + } /** * 设置清晰度 diff --git a/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java b/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java new file mode 100644 index 000000000..429be45e7 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java @@ -0,0 +1,194 @@ +package com.yunbao.common.views; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.content.FileProvider; + +import com.lxj.xpopup.core.CenterPopupView; +import com.yunbao.common.CommonAppConfig; +import com.yunbao.common.R; +import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.utils.APKDownloadUtil; +import com.yunbao.common.utils.ToastUtil; +import com.yunbao.common.views.weight.ViewClicksAntiShake; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +/** + * apk更新弹窗 + */ +public class APKUpdateCustomPopup extends CenterPopupView { + private TextView updateText, versionImmediateUse; + private LinearLayout updateLine; + private ProgressBar progressBar; + private Activity mContext; + + public APKUpdateCustomPopup(@NonNull Activity context) { + super(context); + mContext = context; + } + + // 返回自定义弹窗的布局 + @Override + protected int getImplLayoutId() { + return R.layout.apk_update_custom_popup; + } + + // 执行初始化操作,比如:findView,设置点击,或者任何你弹窗内的业务逻辑 + @Override + protected void onCreate() { + super.onCreate(); + initView(); + initData(); + } + + private void initData() { + + } + + private void initView() { + updateText = findViewById(R.id.update_text); + versionImmediateUse = findViewById(R.id.version_immediate_use); + updateLine = findViewById(R.id.update_line); + progressBar = findViewById(R.id.progressBar); + versionImmediateUse.setVisibility(VISIBLE); + updateLine.setVisibility(GONE); + updateText.setText(IMLoginManager.get(getContext()).getAPKDes()); + ViewClicksAntiShake.clicksAntiShake(versionImmediateUse, new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + //不是谷歌 + if (!CommonAppConfig.IS_GOOGLE_PLAY) { + versionImmediateUse.setVisibility(GONE); + updateLine.setVisibility(VISIBLE); + downloadAPK(mContext, IMLoginManager.get(getContext()).getAPKUrl(), new APKDownloadUtil.OnUpdateListener() { + @Override + public void updateFailure(int code, String error) { + ToastUtil.show(error); + } + }); + } else { + Intent i = new Intent(android.content.Intent.ACTION_VIEW); + i.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.pdlive.shayu")); + mContext.startActivity(i); + mContext.finish(); + } + + } + }); + } + + public void downloadAPK(Activity context, String url, APKDownloadUtil.OnUpdateListener listener) { + Request request = new Request.Builder().url(url) + .addHeader("Accept-Encoding", "identity").build(); + File downloadFile = new File(context.getCacheDir(), "update_app.apk"); + try { + if (!downloadFile.exists() + && !downloadFile.createNewFile()) { + return; + } + } catch (IOException e) { + e.printStackTrace(); + } + new OkHttpClient().newCall(request).enqueue(new Callback() { + private Handler handler = new Handler(); + + @Override + public void onFailure(Call call, IOException e) { + // 下载失败 + handler.post(() -> { + listener.updateFailure(-1, e.getMessage()); + dismiss(); + }); + } + + @Override + public void onResponse(Call call, Response response) { + Looper.prepare(); + byte[] buf = new byte[2048]; + int len; + try (InputStream inputStream = response.body().byteStream(); + FileOutputStream outputStream = new FileOutputStream(downloadFile)) { + long total = response.body().contentLength(); + long sum = 0; + while ((len = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, len); + sum += len; + int progress = (int) (sum * 1.0f / total * 100); + // 下载中 + handler.post(new Runnable() { + @Override + public void run() { + progressBar.setProgress(progress); + } + }); + } + outputStream.flush(); + //启动安装app + installApk(context, downloadFile, context.getPackageName() + ".fileprovider"); + handler.post(() -> dismiss()); + } catch (Exception e) { + e.printStackTrace(); + new Handler().post(() -> { + listener.updateFailure(-1, e.getMessage()); + dismiss(); + }); + } + } + }); + } + + /** + * 安装apk + * + * @param context + * @param file + */ + public void installApk(Context context, File file, String authority) { + Intent intent = getInstallIntent(context, file, authority); + context.startActivity(intent); + } + + /** + * 获取安装Intent + * + * @param context + * @param file + * @param authority + * @return + */ + public Intent getInstallIntent(Context context, File file, String authority) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addCategory(Intent.CATEGORY_DEFAULT); + Uri uriData; + String type = "application/vnd.android.package-archive"; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + uriData = FileProvider.getUriForFile(context, authority, file); + } else { + uriData = Uri.fromFile(file); + } + intent.setDataAndType(uriData, type); + return intent; + } +} diff --git a/common/src/main/res/drawable/bg_apk_update_btn.xml b/common/src/main/res/drawable/bg_apk_update_btn.xml new file mode 100644 index 000000000..57831085d --- /dev/null +++ b/common/src/main/res/drawable/bg_apk_update_btn.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/common/src/main/res/drawable/progress_bg.xml b/common/src/main/res/drawable/progress_bg.xml new file mode 100644 index 000000000..97b90eb75 --- /dev/null +++ b/common/src/main/res/drawable/progress_bg.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/layout/apk_update_custom_popup.xml b/common/src/main/res/layout/apk_update_custom_popup.xml new file mode 100644 index 000000000..4a4f1f9a7 --- /dev/null +++ b/common/src/main/res/layout/apk_update_custom_popup.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/mipmap-xxhdpi/update_tip_box.png b/common/src/main/res/mipmap-xxhdpi/update_tip_box.png new file mode 100644 index 0000000000000000000000000000000000000000..7bcfaad417d6b929a0827d1d069f4ff96b366825 GIT binary patch literal 235610 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 z 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

KzKRllaqY$R%bkPuY(!CfpTs{= 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

D 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 OOwU=ItuVUs_x}OYqFe+3 literal 0 HcmV?d00001 diff --git a/common/src/main/res/values-en/strings.xml b/common/src/main/res/values-en/strings.xml index 07b3a9a90..47c22d55e 100644 --- a/common/src/main/res/values-en/strings.xml +++ b/common/src/main/res/values-en/strings.xml @@ -994,4 +994,8 @@ Limited ride And limited avatar frame Stick to choice Network prompt The system detects that your network is unstable and insufficient device memory will affect the fluency of your live broadcast. Therefore, it is recommended that you choose fluency and clarity. + check version + Update + Latest Version + updating diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 01237fa89..5bc7c5f05 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1014,4 +1014,8 @@ 堅持選擇 網絡提示 系統監測到您的網絡不穩定,設備內存不足將會影響到您的直播流暢度,因此建議您選擇流暢清晰度。 + 检查新版本 + 發現新版本,點此更新 + 已是最新版本 + 更新中 diff --git a/config.gradle b/config.gradle index ac60b7e57..9c0a1cfbb 100644 --- a/config.gradle +++ b/config.gradle @@ -5,7 +5,7 @@ ext { minSdkVersion : 21, targetSdkVersion : 31, versionCode : 402, - versionName : "6.4.7" + versionName : "6.4.6" ] manifestPlaceholders = [ //正式 diff --git a/main/src/main/java/com/yunbao/main/activity/SettingActivity.java b/main/src/main/java/com/yunbao/main/activity/SettingActivity.java index 7d1d599b6..f45bd0653 100644 --- a/main/src/main/java/com/yunbao/main/activity/SettingActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/SettingActivity.java @@ -19,19 +19,18 @@ import androidx.recyclerview.widget.RecyclerView; import com.alibaba.android.arouter.facade.annotation.Route; import com.alibaba.fastjson.JSON; +import com.lxj.xpopup.XPopup; import com.lzf.easyfloat.interfaces.OnPermissionResult; import com.lzf.easyfloat.permission.PermissionUtils; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.Constants; import com.yunbao.common.activity.AbsActivity; import com.yunbao.common.activity.WebViewActivity; -import com.yunbao.common.bean.ConfigBean; import com.yunbao.common.bean.IMLoginModel; import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.CommonHttpConsts; import com.yunbao.common.http.CommonHttpUtil; import com.yunbao.common.http.HttpCallback; -import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.OnItemClickListener; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.utils.DialogUitl; @@ -40,6 +39,7 @@ import com.yunbao.common.utils.RouteUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.VersionUtil; import com.yunbao.common.utils.WordUtil; +import com.yunbao.common.views.APKUpdateCustomPopup; import com.yunbao.common.views.floatingview.APPEasyFloat; import com.yunbao.common.views.weight.ViewClicksAntiShake; import com.yunbao.main.R; @@ -99,6 +99,11 @@ public class SettingActivity extends AbsActivity implements OnItemClickListener< data1.setName(WordUtil.getString(R.string.versions)); list.add(data1); + SettingBean data2 = new SettingBean(); + data2.setId(25); + data2.setName(WordUtil.getString(R.string.check_the_new_version)); + list.add(data2); + SettingBean bean = new SettingBean(); bean.setName(WordUtil.getString(R.string.setting_exit)); bean.setLast(true); @@ -280,6 +285,13 @@ public class SettingActivity extends AbsActivity implements OnItemClickListener< clearCache(position); } else if (bean.getId() == 21) {//清除缓存 startActivity(new Intent(SettingActivity.this, MsgSettActivity.class)); + } else if (bean.getId() == 25) {//版本更新 + if (!IMLoginManager.get(mContext).getApkVerNew()) { + new XPopup.Builder(mContext) + .asCustom(new APKUpdateCustomPopup(mContext)) + .show(); + } + } } else { if (bean.getId() == 17) {//意见反馈要在url上加版本号和设备号 diff --git a/main/src/main/java/com/yunbao/main/adapter/SettingAdapter.java b/main/src/main/java/com/yunbao/main/adapter/SettingAdapter.java index 22e04c560..6ab9de77f 100644 --- a/main/src/main/java/com/yunbao/main/adapter/SettingAdapter.java +++ b/main/src/main/java/com/yunbao/main/adapter/SettingAdapter.java @@ -12,10 +12,9 @@ import androidx.recyclerview.widget.RecyclerView; import com.yunbao.common.Constants; import com.yunbao.common.interfaces.OnItemClickListener; +import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.utils.DeviceUtils; import com.yunbao.common.utils.LogUtil; -import com.yunbao.common.views.weight.ViewClicksAntiShake; -import com.yunbao.main.BuildConfig; import com.yunbao.main.R; import com.yunbao.main.bean.SettingBean; @@ -47,17 +46,17 @@ public class SettingAdapter extends RecyclerView.Adapter { @Override public void onClick(View v) { - Object tag = v.getTag(); - if (tag != null) { - int position = (int) tag; - SettingBean bean = mList.get(position); - if(bean.getId()==19){ - LogUtil.shareFile(context); - } - if (mOnItemClickListener != null) { - mOnItemClickListener.onItemClick(bean, position); - } + Object tag = v.getTag(); + if (tag != null) { + int position = (int) tag; + SettingBean bean = mList.get(position); + if (bean.getId() == 19) { + LogUtil.shareFile(context); } + if (mOnItemClickListener != null) { + mOnItemClickListener.onItemClick(bean, position); + } + } } @@ -75,7 +74,7 @@ public class SettingAdapter extends RecyclerView.Adapter { @Override public int getItemViewType(int position) { SettingBean bean = mList.get(position); - if (bean.getId() == 19 || bean.getId() == Constants.SETTING_UPDATE_ID || bean.getId() == Constants.SETTING_CLEAR_CACHE) { + if (bean.getId() == 19 || bean.getId() == 25|| bean.getId() == Constants.SETTING_UPDATE_ID || bean.getId() == Constants.SETTING_CLEAR_CACHE) { return VERSION; } else if (bean.isLast()) { return LAST; @@ -147,6 +146,16 @@ public class SettingAdapter extends RecyclerView.Adapter { } else if (bean.getId() == 19) { mText.setText(DeviceUtils.getVersionName(itemView.getContext())); mText.setTextColor(Color.parseColor("#969696")); + } else if (bean.getId() == 25) { + if (IMLoginManager.get(itemView.getContext()).getApkVerNew()) { + mText.setText(itemView.getContext().getString(R.string.latest_version)); + mText.setTextColor(Color.parseColor("#969696")); + + } else { + mText.setText(itemView.getContext().getString(R.string.discover_a_new_version)); + mText.setTextColor(Color.parseColor("#b3d465")); + } + } else { mText.setText(mVersionString); } diff --git a/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java b/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java index 3e8df3710..1346e2103 100644 --- a/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java +++ b/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java @@ -1,5 +1,6 @@ package com.yunbao.main.views; +import android.annotation.SuppressLint; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; @@ -38,6 +39,7 @@ import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.OnItemClickListener; +import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.utils.RouteUtil; import com.yunbao.common.utils.SVGAViewUtils; import com.yunbao.common.utils.ToastUtil; @@ -99,6 +101,7 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi private boolean firstInto = true; private Banner banner_me; private LinearLayout lt_advertisement; + private View redPoint; public MainMeViewHolder(Context context, ViewGroup parentView) { super(context, parentView); @@ -109,9 +112,11 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi return R.layout.view_main_me; } + @SuppressLint("WrongViewCast") @Override public void init() { mAvatar = (ImageView) findViewById(R.id.avatar); + redPoint = findViewById(R.id.red_point); ViewClicksAntiShake.clicksAntiShake(mAvatar, new ViewClicksAntiShake.ViewClicksCallBack() { @Override public void onViewClicks() { @@ -175,6 +180,7 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 10); } }); + redPoint.setVisibility(IMLoginManager.get(mContext).getApkVerNew() ? View.GONE : View.VISIBLE); } @Override @@ -312,7 +318,7 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi public void onComplete(SVGAVideoEntity videoItem) { SVGADrawable drawable = new SVGADrawable(videoItem); gift_svga.setImageDrawable(drawable); - SVGAViewUtils.playEndClear(gift_svga,false); + SVGAViewUtils.playEndClear(gift_svga, false); } @Override @@ -441,11 +447,11 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi } else if (bean.getId() == 4) { url = HtmlConfig.SHOP + "?t=" + Math.random() + "&uid=" + CommonAppConfig.getInstance().getUid() + "&token=" + CommonAppConfig.getInstance().getToken(); WebViewActivity.forward(mContext, url); - } else if(bean.getId() == 3) {//我的等级 - Constants.myIntoIndex=2; + } else if (bean.getId() == 3) {//我的等级 + Constants.myIntoIndex = 2; Constants.isTitle = false; ZhuangBanActivity.forward(mContext, url); - }else{ + } else { WebViewActivity.forward(mContext, url); } @@ -462,8 +468,7 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi mContext.startActivity(new Intent(mContext, EditProfileActivity.class)); } else if (i == R.id.signature) { mContext.startActivity(new Intent(mContext, EditProfileActivity.class)); - } - else if (i == R.id.lt_star_coin) { + } else if (i == R.id.lt_star_coin) { mContext.startActivity(new Intent(mContext, MyWalletActivity.class).putExtra("p", 1)); } else if (i == R.id.btn_coin) { mContext.startActivity(new Intent(mContext, MyWalletActivity.class).putExtra("p", 0)); @@ -483,8 +488,6 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi } - - } /** diff --git a/main/src/main/res/layout/view_main_me.xml b/main/src/main/res/layout/view_main_me.xml index 6e54a3206..9a0ef092d 100644 --- a/main/src/main/res/layout/view_main_me.xml +++ b/main/src/main/res/layout/view_main_me.xml @@ -476,18 +476,18 @@ android:layout_marginTop="12dp" android:layout_marginRight="15dp" android:background="@drawable/bg_me_data" - android:gravity="center" android:clickable="true" - android:focusableInTouchMode="true" android:focusable="true" + android:focusableInTouchMode="true" + android:gravity="center" android:orientation="horizontal"> @@ -534,10 +534,10 @@ android:layout_width="18dp" android:layout_height="18dp" android:layout_marginRight="30dp" + android:background="@mipmap/icon_more_gray" android:clickable="false" - android:focusableInTouchMode="false" android:focusable="false" - android:background="@mipmap/icon_more_gray" /> + android:focusableInTouchMode="false" /> + + Date: Tue, 3 Jan 2023 16:17:48 +0800 Subject: [PATCH 028/118] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=BB=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2APk=E6=9B=B4=E6=96=B0=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=8C=BA=E5=88=86=E5=BC=BA=E5=88=B6=E9=9D=9E=E5=BC=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/http/CommonHttpUtil.java | 13 +++- .../com/yunbao/common/manager/APKManager.java | 73 ++++++++++++++++++ .../yunbao/common/manager/IMLoginManager.java | 25 ------ .../common/views/APKUpdateCustomPopup.java | 30 ++++++- .../res/layout/apk_update_custom_popup.xml | 8 ++ .../main/res/mipmap-xxhdpi/icon_close_tip.png | Bin 0 -> 1276 bytes config.gradle | 2 +- .../yunbao/main/activity/MainActivity.java | 17 ++-- .../yunbao/main/activity/SettingActivity.java | 5 +- .../yunbao/main/adapter/SettingAdapter.java | 3 +- .../yunbao/main/views/MainMeViewHolder.java | 4 +- 11 files changed, 136 insertions(+), 44 deletions(-) create mode 100644 common/src/main/java/com/yunbao/common/manager/APKManager.java create mode 100644 common/src/main/res/mipmap-xxhdpi/icon_close_tip.png diff --git a/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java b/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java index 114d2452e..6e74a4db4 100644 --- a/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java +++ b/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java @@ -17,6 +17,7 @@ import com.yunbao.common.activity.ErrorActivity; import com.yunbao.common.bean.ConfigBean; import com.yunbao.common.event.FollowEvent; import com.yunbao.common.interfaces.CommonCallback; +import com.yunbao.common.manager.APKManager; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.NewLevelManager; import com.yunbao.common.utils.L; @@ -200,13 +201,19 @@ public class CommonHttpUtil { new NewLevelManager(context).UpAnchorDataLevel(levelArray.toJSONString()); } if (obj.containsKey("apk_ver")) { - IMLoginManager.get(context).setApkVer(obj.getString("apk_ver")); + APKManager.get().setApkVer(obj.getString("apk_ver")); } if (obj.containsKey("apk_url")) { - IMLoginManager.get(context).setAPKUrl(obj.getString("apk_url")); + APKManager.get().setAPKUrl(obj.getString("apk_url")); } if (obj.containsKey("apk_des")) { - IMLoginManager.get(context).setAPKDes(obj.getString("apk_des")); + APKManager.get().setAPKDes(obj.getString("apk_des")); + } + if (obj.containsKey("google_isup")) { + APKManager.get().setAPKGoogleIsUp(obj.getInteger("google_isup")); + } + if (obj.containsKey("isup")) { + APKManager.get().setAPKIsUp(obj.getInteger("isup")); } } catch (Exception e) { String error = "info[0]:" + info[0] + "\n\n\n" + "Exception:" + e.getClass() + "---message--->" + e.getMessage(); diff --git a/common/src/main/java/com/yunbao/common/manager/APKManager.java b/common/src/main/java/com/yunbao/common/manager/APKManager.java new file mode 100644 index 000000000..266e22827 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/manager/APKManager.java @@ -0,0 +1,73 @@ +package com.yunbao.common.manager; + +import android.content.Context; +import android.text.TextUtils; + +import com.yunbao.common.CommonAppContext; +import com.yunbao.common.manager.base.BaseCacheManager; +import com.yunbao.common.utils.VersionUtil; + +public class APKManager extends BaseCacheManager { + private static APKManager manager; + private final String APK_VER = "apk_ver"; + private final String APK_URL = "apk_url"; + private final String APK_DES = "apk_des"; + private final String APK_IS_UP = "isup"; + private final String APK_GOOGLE_IS_UP = "google_isup"; + + public APKManager(Context context) { + super(context); + } + + /** + * 获取单利 + * + * @return + */ + public static APKManager get() { + if (null == manager) { + manager = new APKManager(CommonAppContext.sInstance.getBaseContext()); + } + return manager; + } + + public void setAPKUrl(String apkUrl) { + put(APK_URL, apkUrl); + } + + public void setAPKDes(String apkDes) { + put(APK_DES, apkDes); + } + + public String getAPKUrl() { + return getString(APK_URL); + } + + public String getAPKDes() { + return getString(APK_DES); + } + + public void setApkVer(String apkVer) { + put(APK_VER, apkVer); + } + + public boolean getApkVerNew() { + return TextUtils.equals(VersionUtil.getVersion(), getString(APK_VER)); + } + + public void setAPKIsUp(int apkIsUp) { + put(APK_IS_UP, apkIsUp); + } + + public void setAPKGoogleIsUp(int apkGoogleIsUp) { + put(APK_GOOGLE_IS_UP, apkGoogleIsUp); + } + + public int getApkIsUp() { + return getInt(APK_IS_UP, 0); + } + + public int getAPKGoogleIsUp() { + return getInt(APK_GOOGLE_IS_UP, 0); + } +} 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 846d7afa0..84f7b7879 100644 --- a/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java +++ b/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java @@ -40,33 +40,8 @@ public class IMLoginManager extends BaseCacheManager { private final String IS_HINT = "is_hint"; private final String IS_HINT2 = "is_hint2"; private final String SELECT_CLARITY = "selectClarity"; - private final String APK_VER = "apk_ver"; - private final String APK_URL = "apk_url"; - private final String APK_DES = "apk_des"; - public void setAPKUrl(String apkUrl) { - put(APK_URL, apkUrl); - } - public void setAPKDes(String apkDes) { - put(APK_DES, apkDes); - } - - public String getAPKUrl() { - return getString(APK_URL); - } - - public String getAPKDes() { - return getString(APK_DES); - } - - public void setApkVer(String apkVer) { - put(APK_VER, apkVer); - } - - public boolean getApkVerNew() { - return TextUtils.equals(VersionUtil.getVersion(), getString(APK_VER)); - } /** * 设置清晰度 diff --git a/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java b/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java index 429be45e7..025bdd14e 100644 --- a/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java @@ -17,7 +17,7 @@ import androidx.core.content.FileProvider; import com.lxj.xpopup.core.CenterPopupView; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.R; -import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.manager.APKManager; import com.yunbao.common.utils.APKDownloadUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.views.weight.ViewClicksAntiShake; @@ -41,10 +41,12 @@ public class APKUpdateCustomPopup extends CenterPopupView { private LinearLayout updateLine; private ProgressBar progressBar; private Activity mContext; + private boolean mInside; - public APKUpdateCustomPopup(@NonNull Activity context) { + public APKUpdateCustomPopup(@NonNull Activity context, boolean inside) { super(context); mContext = context; + mInside = inside; } // 返回自定义弹窗的布局 @@ -66,13 +68,33 @@ public class APKUpdateCustomPopup extends CenterPopupView { } private void initView() { + if (!mInside) { + if (!CommonAppConfig.IS_GOOGLE_PLAY && APKManager.get().getAPKGoogleIsUp() == 1) { + findViewById(R.id.dialog_close).setVisibility(GONE); + } + if (!CommonAppConfig.IS_GOOGLE_PLAY && APKManager.get().getAPKGoogleIsUp() == 1) { + findViewById(R.id.dialog_close).setVisibility(GONE); + } + } updateText = findViewById(R.id.update_text); versionImmediateUse = findViewById(R.id.version_immediate_use); updateLine = findViewById(R.id.update_line); progressBar = findViewById(R.id.progressBar); versionImmediateUse.setVisibility(VISIBLE); updateLine.setVisibility(GONE); - updateText.setText(IMLoginManager.get(getContext()).getAPKDes()); + updateText.setText(APKManager.get().getAPKDes()); + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.dialog_close), new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + if (CommonAppConfig.IS_GOOGLE_PLAY && APKManager.get().getAPKGoogleIsUp() != 1) { + dismiss(); + } + if (!CommonAppConfig.IS_GOOGLE_PLAY && APKManager.get().getApkIsUp() != 1) { + dismiss(); + } + } + } + ); ViewClicksAntiShake.clicksAntiShake(versionImmediateUse, new ViewClicksAntiShake.ViewClicksCallBack() { @Override public void onViewClicks() { @@ -80,7 +102,7 @@ public class APKUpdateCustomPopup extends CenterPopupView { if (!CommonAppConfig.IS_GOOGLE_PLAY) { versionImmediateUse.setVisibility(GONE); updateLine.setVisibility(VISIBLE); - downloadAPK(mContext, IMLoginManager.get(getContext()).getAPKUrl(), new APKDownloadUtil.OnUpdateListener() { + downloadAPK(mContext, APKManager.get().getAPKUrl(), new APKDownloadUtil.OnUpdateListener() { @Override public void updateFailure(int code, String error) { ToastUtil.show(error); diff --git a/common/src/main/res/layout/apk_update_custom_popup.xml b/common/src/main/res/layout/apk_update_custom_popup.xml index 4a4f1f9a7..a59817e4d 100644 --- a/common/src/main/res/layout/apk_update_custom_popup.xml +++ b/common/src/main/res/layout/apk_update_custom_popup.xml @@ -71,5 +71,13 @@ android:textSize="11sp" /> + \ No newline at end of file diff --git a/common/src/main/res/mipmap-xxhdpi/icon_close_tip.png b/common/src/main/res/mipmap-xxhdpi/icon_close_tip.png new file mode 100644 index 0000000000000000000000000000000000000000..f64e53e8288b005083135ed6a8938e3a59ac4476 GIT binary patch literal 1276 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGojKx9jP7LeL$-HD>VA=@dJk$`XaLRC6o6>L`D57DK0La-s~DEvb6Z!lHzxK$!Ag-o^RIqU11>; z_wdAit7hK=$BrHQYHe-(o}uDV1GDVa(%K{&x&JrBTc%E(y7TAHpXLlU?0=sBU$}4W z>t8=AZ2qlV|L5?x(`pLmKYwSmF@4COZ}t4$`c<#mZwN^J09y9E$537E&F^rAY?m+5 zZ~l1xP8OW-{3lz(`Y4%*5>DNR@58I-cFfDaXnadZk8wR?Ms>nPm6DeG4u4xa^19u& zAMJ}^5pn%EvH0CZvD$CbS-d|q+)uGqI%V~RC+?I|LT&9|-Q+VX`*QcHRvgNI_1DqG zyyT7KmN~8tfg=5u&(Bqwywy=;s0)5CtWwSYn(F^S@nQi(?3d>qD+x68H+E}vRHXoaD`Fh2kf*U_0-^{5mRs0rwVLvxZ zobasW%Qwq~A4qx7?RUU#hXZHqPjyy%PDVjL_gqyKc6&)i9-&Ds^QSb(sj6_>TQb^u zcu3VvVp8(*kgMCoG%G1PJNx^YGiN3|U#r$*xIQO0cW!2N>$E8KU$zf6H0SMmsHdY- z^J0#*9K*9kTfa44%=l7!z^>}Pi6!I22k)D`sKQ1orR^ND{ z&M6&u{FfpBN28FA;8_;Iw>u2G8*I+sXZuicI`7~IW|bJVMN6mIF4lQ0^g*S8Kgy(! z?SAl~beAsy-SaL^+rSYK7dJ0HCPv2c`MX&cY^?tD3BA%e{Z5*%-Oil*o>K&i$y;Fj z-;VmN+7Qi`@q2plyO7Y(v#Zza{qy$jqB_0@FBln1i@SYX-hUIaOI)7A^iAbX$n~$M zkIk6OkjMI=`t!0~#qUgx&(>VMdbRnvbLaLkJSb$?&iq68K&#H_a|QLEzR%sj_26HL puk$=Efo)5unVWHx1wZyPX7k(CZ{8Sm4_KTrc)I$ztaD0e0sz*VKvw_& literal 0 HcmV?d00001 diff --git a/config.gradle b/config.gradle index 9c0a1cfbb..88d9c1761 100644 --- a/config.gradle +++ b/config.gradle @@ -25,7 +25,7 @@ ext { baiduAppSecretKey: "nEVSgmuGpU0pjPr6VleEGGAl0hzGW52S", // true表示谷歌支付 false - isGooglePlay : true, + isGooglePlay : false, //是否上报异常日志 isUploadLog : false ] 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 b69a1bab3..584273828 100644 --- a/main/src/main/java/com/yunbao/main/activity/MainActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/MainActivity.java @@ -17,7 +17,6 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.os.Looper; import android.text.TextUtils; import android.util.Log; import android.view.Display; @@ -41,6 +40,7 @@ import com.google.firebase.messaging.FirebaseMessaging; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.jakewharton.rxbinding3.view.RxView; +import com.lxj.xpopup.XPopup; import com.lzf.easyfloat.EasyFloat; import com.lzf.easyfloat.permission.PermissionUtils; import com.tencent.imsdk.v2.V2TIMCallback; @@ -75,6 +75,7 @@ import com.yunbao.common.http.CommonHttpUtil; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.main.MainNetManager; import com.yunbao.common.interfaces.CommonCallback; +import com.yunbao.common.manager.APKManager; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.NoviceInstructorManager; import com.yunbao.common.manager.imrongcloud.RongcloudIMManager; @@ -88,16 +89,14 @@ import com.yunbao.common.utils.SpUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.VersionUtil; import com.yunbao.common.utils.WordUtil; +import com.yunbao.common.views.APKUpdateCustomPopup; import com.yunbao.common.views.AbsMainViewHolder; import com.yunbao.common.views.floatingview.APPEasyFloat; import com.yunbao.common.views.weight.LiveFloatView; import com.yunbao.live.activity.LiveAudienceActivity; -import com.yunbao.live.activity.LiveRyAnchorActivity; -import com.yunbao.live.dialog.RandomPkDialogFragment; import com.yunbao.live.http.LiveHttpConsts; import com.yunbao.live.http.LiveHttpUtil; import com.yunbao.live.presenter.LiveRoomCheckLivePresenter; -import com.yunbao.live.presenter.LiveRyLinkMicPkPresenter; import com.yunbao.live.utils.LiveStorge; import com.yunbao.live.views.ChatListViewHolder; import com.yunbao.main.R; @@ -682,8 +681,14 @@ public class MainActivity extends AbsActivity implements MainAppBarLayoutListene DialogUitl.showSimpleTipDialog(mContext, WordUtil.getString(R.string.main_maintain_notice), configBean.getMaintainTips()); } if (!VersionUtil.isLatest(configBean.getVersion())) { - VersionUtil versionUtil = new VersionUtil(); - versionUtil.showDialog(mContext, configBean, configBean.getDownloadApkUrl()); + if (!APKManager.get().getApkVerNew()) { + new XPopup.Builder(mContext) + .isDestroyOnDismiss(true) + .dismissOnBackPressed(false) // 按返回键是否关闭弹窗,默认为true + .dismissOnTouchOutside(false) // 点击外部是否关闭弹窗,默认为true + .asCustom(new APKUpdateCustomPopup(mContext, false)) + .show(); + } } else { requestBonus(); } diff --git a/main/src/main/java/com/yunbao/main/activity/SettingActivity.java b/main/src/main/java/com/yunbao/main/activity/SettingActivity.java index f45bd0653..1da67ee61 100644 --- a/main/src/main/java/com/yunbao/main/activity/SettingActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/SettingActivity.java @@ -32,6 +32,7 @@ import com.yunbao.common.http.CommonHttpConsts; import com.yunbao.common.http.CommonHttpUtil; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.interfaces.OnItemClickListener; +import com.yunbao.common.manager.APKManager; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.GlideCatchUtil; @@ -286,9 +287,9 @@ public class SettingActivity extends AbsActivity implements OnItemClickListener< } else if (bean.getId() == 21) {//清除缓存 startActivity(new Intent(SettingActivity.this, MsgSettActivity.class)); } else if (bean.getId() == 25) {//版本更新 - if (!IMLoginManager.get(mContext).getApkVerNew()) { + if (!APKManager.get().getApkVerNew()) { new XPopup.Builder(mContext) - .asCustom(new APKUpdateCustomPopup(mContext)) + .asCustom(new APKUpdateCustomPopup(mContext, true)) .show(); } diff --git a/main/src/main/java/com/yunbao/main/adapter/SettingAdapter.java b/main/src/main/java/com/yunbao/main/adapter/SettingAdapter.java index 6ab9de77f..f59ae20c1 100644 --- a/main/src/main/java/com/yunbao/main/adapter/SettingAdapter.java +++ b/main/src/main/java/com/yunbao/main/adapter/SettingAdapter.java @@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.yunbao.common.Constants; import com.yunbao.common.interfaces.OnItemClickListener; +import com.yunbao.common.manager.APKManager; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.utils.DeviceUtils; import com.yunbao.common.utils.LogUtil; @@ -147,7 +148,7 @@ public class SettingAdapter extends RecyclerView.Adapter { mText.setText(DeviceUtils.getVersionName(itemView.getContext())); mText.setTextColor(Color.parseColor("#969696")); } else if (bean.getId() == 25) { - if (IMLoginManager.get(itemView.getContext()).getApkVerNew()) { + if (APKManager.get().getApkVerNew()) { mText.setText(itemView.getContext().getString(R.string.latest_version)); mText.setTextColor(Color.parseColor("#969696")); diff --git a/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java b/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java index 1346e2103..4d8c38d39 100644 --- a/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java +++ b/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java @@ -39,7 +39,7 @@ import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.OnItemClickListener; -import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.manager.APKManager; import com.yunbao.common.utils.RouteUtil; import com.yunbao.common.utils.SVGAViewUtils; import com.yunbao.common.utils.ToastUtil; @@ -180,7 +180,7 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 10); } }); - redPoint.setVisibility(IMLoginManager.get(mContext).getApkVerNew() ? View.GONE : View.VISIBLE); + redPoint.setVisibility(APKManager.get().getApkVerNew() ? View.GONE : View.VISIBLE); } @Override From e0d71377274b374889da50685e01584e05a9dc0a Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 3 Jan 2023 16:22:20 +0800 Subject: [PATCH 029/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=BB=E6=92=AD?= =?UTF-8?q?=E7=AB=AF=E5=BC=80=E6=92=AD=E8=AE=BE=E7=BD=AEclarityType?= =?UTF-8?q?=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java b/live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java index 39b9b26d5..be47f5942 100644 --- a/live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java +++ b/live/src/main/java/com/yunbao/live/http/LiveHttpUtil.java @@ -695,7 +695,7 @@ public class LiveHttpUtil { .params("landscape", "2") .params("class_type", "0") .params("type_val", typeVal) - .params("clarityType ", clarityType); + .params("clarityType", clarityType); if (file != null) { request.params("file", file); } From 289c93d824bd8edcc38135b926ab19e09d9c152b Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Wed, 4 Jan 2023 17:22:39 +0800 Subject: [PATCH 030/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E6=BB=91=E5=8A=A8=E6=9C=AA=E6=B8=85=E7=A9=BA=E9=9D=93?= =?UTF-8?q?=E5=8F=B7=E6=A0=87=E8=AF=86=E5=92=8C=E9=9D=93=E5=8F=B7=E8=83=8C?= =?UTF-8?q?=E6=99=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 6fa9eaa4a..0952acacb 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -1197,6 +1197,8 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mRedVal.setVisibility(View.GONE); mBlueVal.setVisibility(View.GONE); mPkRankTopIcon.setVisibility(View.GONE); + mAnchorLayout.setBackgroundResource(R.drawable.bg_live_ico); + mGoodNumberIcon.setVisibility(View.GONE); } /** From 16d02c6936f6a60527af4adab2800c4cb93e0202 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 5 Jan 2023 14:13:56 +0800 Subject: [PATCH 031/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E8=A7=82=E4=BC=97=E7=AB=AF=E8=A7=86=E9=A2=91=E5=8F=98?= =?UTF-8?q?=E5=BD=A2=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/utils/LiveExoPlayerManager.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index ac2d8a8d7..7ca05a53f 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -1,5 +1,7 @@ package com.yunbao.live.utils; +import static com.google.android.exoplayer2.C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING; + import android.content.Context; import android.os.Handler; import android.os.Looper; @@ -10,8 +12,6 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.analytics.AnalyticsListener; -import com.google.android.exoplayer2.analytics.PlaybackStats; -import com.google.android.exoplayer2.analytics.PlaybackStatsListener; import com.google.android.exoplayer2.video.VideoSize; /** @@ -35,6 +35,8 @@ public class LiveExoPlayerManager { this.mContext = mContext; player1 = new ExoPlayer.Builder(mContext).build(); player2 = new ExoPlayer.Builder(mContext).build(); + player1.setVideoScalingMode(VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); + player2.setVideoScalingMode(VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); handler = new Handler(Looper.getMainLooper()); setListener(); setAnalyticsListener(); From 7cea6b4f8d3f2ccc0b81fd07fcb2a9357c631244 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 5 Jan 2023 17:28:21 +0800 Subject: [PATCH 032/118] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=A7=82=E4=BC=97?= =?UTF-8?q?=E7=AB=AF=E7=82=B9=E5=87=BB=E6=9C=AA=E5=90=AF=E7=94=A8=E6=B8=85?= =?UTF-8?q?=E6=99=B0=E5=BA=A6=E6=97=B6=E7=9A=84=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/views/LiveClarityCustomPopup.java | 25 ++++++++++++++++--- common/src/main/res/values-en/strings.xml | 2 ++ common/src/main/res/values/strings.xml | 2 ++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index e1faf4ba3..e0abd63d7 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -15,6 +15,8 @@ import com.lxj.xpopup.XPopup; import com.lxj.xpopup.core.BottomPopupView; import com.yunbao.common.R; import com.yunbao.common.utils.DeviceUtils; +import com.yunbao.common.utils.ToastUtil; +import com.yunbao.common.utils.WordUtil; import com.yunbao.common.views.weight.ViewClicksAntiShake; import java.util.ArrayList; @@ -104,6 +106,14 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl }); //高清 ViewClicksAntiShake.clicksAntiShake(lineHd, () -> { + if(lineHd.getTag()!=null){ + if(isUser){//用户端 + ToastUtil.show(R.string.live_user_ban_hd); + }else{//主播端 + ToastUtil.show(""); + } + return; + } String memorg = formateFileSize(Long.parseLong(DeviceUtils.getMemory(getContext()))); if ((Double.parseDouble(memorg) > 7 && netAverage > 100) || isUser) { selectClarity = 1; @@ -131,7 +141,14 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl }); //超高清 ViewClicksAntiShake.clicksAntiShake(lineFhd, () -> { - + if(lineFhd.getTag()!=null){ + if(isUser){//用户端 + ToastUtil.show(R.string.live_user_ban_fhd); + }else{//主播端 + ToastUtil.show(""); + } + return; + } new XPopup.Builder(getContext()) .asCustom(new HintCustomPopup(getContext()).setCallBack(new HintCustomPopup.HintCustomCallBack() { @Override @@ -151,14 +168,14 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl }); if (banSelect == BAN_720) { - lineFhd.setEnabled(false); - lineHd.setEnabled(false); + lineFhd.setTag(false); + lineHd.setTag(false); titleHDImg.setImageAlpha(40); titleFHDImg.setImageAlpha(40); titleHDText.setAlpha(0.2f); titleFHDText.setAlpha(0.2f); } else if (banSelect == BAN_1080) { - lineFhd.setEnabled(false); + lineFhd.setTag(false); titleFHDText.setAlpha(0.2f); titleFHDImg.setImageAlpha(20); } diff --git a/common/src/main/res/values-en/strings.xml b/common/src/main/res/values-en/strings.xml index 47c22d55e..867103039 100644 --- a/common/src/main/res/values-en/strings.xml +++ b/common/src/main/res/values-en/strings.xml @@ -998,4 +998,6 @@ Limited ride And limited avatar frame Update Latest Version updating + There is no choice, the anchor is not turned on FHD live. + There is no choice, the anchor is not turned on HD live. diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 5bc7c5f05..c5207ac34 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1018,4 +1018,6 @@ 發現新版本,點此更新 已是最新版本 更新中 + 無法選擇,該主播未開啟超高清直播。 + 無法選擇,該主播未開啟高清直播。 From 6fcb194995c5dbe7e3cc565313518bd74d4e824e Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 5 Jan 2023 17:48:10 +0800 Subject: [PATCH 033/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=B8=85=E6=99=B0=E5=BA=A6=E6=8F=90=E7=A4=BA=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E4=B8=BA=E9=BB=91=E5=BA=95=E7=99=BD=E5=AD=97=E7=9A=84=E8=80=8C?= =?UTF-8?q?=E4=B8=8D=E6=98=AFToast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/common/utils/ToastUtil.java | 39 +++++++++++++++++++ .../common/views/LiveClarityCustomPopup.java | 17 +++++--- .../live/views/LivePlayRyViewHolder.java | 2 +- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/utils/ToastUtil.java b/common/src/main/java/com/yunbao/common/utils/ToastUtil.java index cb4fb343f..d8245a7ab 100644 --- a/common/src/main/java/com/yunbao/common/utils/ToastUtil.java +++ b/common/src/main/java/com/yunbao/common/utils/ToastUtil.java @@ -1,10 +1,16 @@ package com.yunbao.common.utils; +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.os.Handler; +import android.os.Looper; import android.text.TextUtils; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; +import android.widget.TextView; import android.widget.Toast; import com.yunbao.common.CommonAppContext; @@ -38,6 +44,39 @@ public class ToastUtil { show(WordUtil.getString(res)); } + /** + * 显示黑底白字的提示 + * + * @param res 内容 + * @param delayMillis 显示时间 毫秒 + */ + public static void showStyle(int res, long delayMillis) { + showStyle(WordUtil.getString(res), delayMillis); + } + + /** + * 显示黑底白字的提示 + * + * @param content 内容 + * @param delayMillis 显示时间 毫秒 + */ + public static void showStyle(String content, long delayMillis) { + Dialog dialog = new Dialog(CommonAppContext.getTopActivity(), R.style.dialog); + dialog.setContentView(R.layout.dialog_toast); + dialog.setCancelable(false); + dialog.setCanceledOnTouchOutside(false); + if (!TextUtils.isEmpty(content)) { + TextView titleView = (TextView) dialog.findViewById(R.id.text); + if (titleView != null) { + titleView.setTextColor(Color.WHITE); + titleView.setGravity(Gravity.CENTER); + titleView.setText(content); + } + } + dialog.show(); + new Handler(Looper.getMainLooper()).postDelayed(dialog::dismiss, delayMillis); + } + public static void show(String s) { if (TextUtils.isEmpty(s)) { return; diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index e0abd63d7..5b06484b9 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -39,13 +39,18 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl return selectClarity; } - public LiveClarityCustomPopup(@NonNull Context context, int selectClarity, int banSelect) { + /** + * + * @param banSelect 禁止选项,{@link #BAN_720} 禁止高清和超高清。 {@link #BAN_1080} 禁止超高清 + * @param isUser 是否为观众,true 观众,false 主播 + */ + public LiveClarityCustomPopup(@NonNull Context context, int selectClarity, int banSelect,boolean isUser) { super(context); this.banSelect = banSelect; if (selectClarity == -1) { selectClarity = 0; } - this.isUser = true; + this.isUser = isUser; this.selectClarity = selectClarity; } @@ -108,9 +113,9 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl ViewClicksAntiShake.clicksAntiShake(lineHd, () -> { if(lineHd.getTag()!=null){ if(isUser){//用户端 - ToastUtil.show(R.string.live_user_ban_hd); + ToastUtil.showStyle(R.string.live_user_ban_hd,2000); }else{//主播端 - ToastUtil.show(""); + ToastUtil.showStyle("",2000); } return; } @@ -143,9 +148,9 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl ViewClicksAntiShake.clicksAntiShake(lineFhd, () -> { if(lineFhd.getTag()!=null){ if(isUser){//用户端 - ToastUtil.show(R.string.live_user_ban_fhd); + ToastUtil.showStyle(R.string.live_user_ban_fhd,2000); }else{//主播端 - ToastUtil.show(""); + ToastUtil.showStyle("",2000); } return; } diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 98751cbb3..b935e18da 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -697,7 +697,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { break; } - LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL, ban); + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL, ban,true); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override From 2f413e260e094020abdf7f8b2034fb06963dbc6a Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 5 Jan 2023 17:55:58 +0800 Subject: [PATCH 034/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=B8=85=E6=99=B0=E5=BA=A6=E6=8F=90=E7=A4=BA=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E6=94=B9=E5=9B=9EToast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/common/views/LiveClarityCustomPopup.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index 5b06484b9..5ee55d638 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -113,9 +113,9 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl ViewClicksAntiShake.clicksAntiShake(lineHd, () -> { if(lineHd.getTag()!=null){ if(isUser){//用户端 - ToastUtil.showStyle(R.string.live_user_ban_hd,2000); + ToastUtil.show(R.string.live_user_ban_hd); }else{//主播端 - ToastUtil.showStyle("",2000); + ToastUtil.show(""); } return; } @@ -148,9 +148,9 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl ViewClicksAntiShake.clicksAntiShake(lineFhd, () -> { if(lineFhd.getTag()!=null){ if(isUser){//用户端 - ToastUtil.showStyle(R.string.live_user_ban_fhd,2000); + ToastUtil.show(R.string.live_user_ban_fhd); }else{//主播端 - ToastUtil.showStyle("",2000); + ToastUtil.show(""); } return; } From d26a68738519672e5ab6650cf7ba5b4049ec5347 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Thu, 5 Jan 2023 18:13:43 +0800 Subject: [PATCH 035/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BB=E6=92=AD?= =?UTF-8?q?=E7=AB=AF=E9=80=89=E6=8B=A9=E5=88=86=E8=BE=A8=E7=8E=87=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E6=8E=A5=E5=8F=A3=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/http/CommonHttpUtil.java | 3 +++ .../yunbao/common/manager/IMLoginManager.java | 14 +++++++++++- .../common/views/LiveClarityCustomPopup.java | 22 +++++++++---------- common/src/main/res/values-en/strings.xml | 1 + common/src/main/res/values/strings.xml | 1 + config.gradle | 4 ++-- .../live/views/LiveNewReadyRyViewHolder.java | 19 ++++++++-------- 7 files changed, 39 insertions(+), 25 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java b/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java index 6e74a4db4..88af69746 100644 --- a/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java +++ b/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java @@ -215,6 +215,9 @@ public class CommonHttpUtil { if (obj.containsKey("isup")) { APKManager.get().setAPKIsUp(obj.getInteger("isup")); } + if (obj.containsKey("clarity")) { + IMLoginManager.get(context).setClarity(obj.getString("clarity")); + } } catch (Exception e) { String error = "info[0]:" + info[0] + "\n\n\n" + "Exception:" + e.getClass() + "---message--->" + e.getMessage(); ErrorActivity.forward("GetConfig接口返回数据异常", error); 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 84f7b7879..301dc6302 100644 --- a/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java +++ b/common/src/main/java/com/yunbao/common/manager/IMLoginManager.java @@ -18,7 +18,6 @@ import com.yunbao.common.manager.base.BaseCacheManager; import com.yunbao.common.manager.imrongcloud.MessageIMManager; import com.yunbao.common.manager.imrongcloud.RongcloudIMManager; import com.yunbao.common.utils.SpUtil; -import com.yunbao.common.utils.VersionUtil; import com.yunbao.common.views.floatingview.APPEasyFloat; import org.greenrobot.eventbus.EventBus; @@ -40,8 +39,21 @@ public class IMLoginManager extends BaseCacheManager { private final String IS_HINT = "is_hint"; private final String IS_HINT2 = "is_hint2"; private final String SELECT_CLARITY = "selectClarity"; + private final String CLARITY = "clarity"; + public void setClarity(String clarity) { + put(CLARITY, clarity); + } + + /** + * 1080p开播分辨率:clarity 0关闭 1开启 + * + * @return + */ + public boolean getClarity() { + return TextUtils.equals(getString(CLARITY), "1"); + } /** * 设置清晰度 diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index 5ee55d638..3e5edb01a 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -16,7 +16,6 @@ import com.lxj.xpopup.core.BottomPopupView; import com.yunbao.common.R; import com.yunbao.common.utils.DeviceUtils; import com.yunbao.common.utils.ToastUtil; -import com.yunbao.common.utils.WordUtil; import com.yunbao.common.views.weight.ViewClicksAntiShake; import java.util.ArrayList; @@ -40,11 +39,10 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl } /** - * * @param banSelect 禁止选项,{@link #BAN_720} 禁止高清和超高清。 {@link #BAN_1080} 禁止超高清 - * @param isUser 是否为观众,true 观众,false 主播 + * @param isUser 是否为观众,true 观众,false 主播 */ - public LiveClarityCustomPopup(@NonNull Context context, int selectClarity, int banSelect,boolean isUser) { + public LiveClarityCustomPopup(@NonNull Context context, int selectClarity, int banSelect, boolean isUser) { super(context); this.banSelect = banSelect; if (selectClarity == -1) { @@ -111,11 +109,11 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl }); //高清 ViewClicksAntiShake.clicksAntiShake(lineHd, () -> { - if(lineHd.getTag()!=null){ - if(isUser){//用户端 + if (lineHd.getTag() != null) { + if (isUser) {//用户端 ToastUtil.show(R.string.live_user_ban_hd); - }else{//主播端 - ToastUtil.show(""); + } else {//主播端 + ToastUtil.show(R.string.function_is_suspended); } return; } @@ -146,11 +144,11 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl }); //超高清 ViewClicksAntiShake.clicksAntiShake(lineFhd, () -> { - if(lineFhd.getTag()!=null){ - if(isUser){//用户端 + if (lineFhd.getTag() != null) { + if (isUser) {//用户端 ToastUtil.show(R.string.live_user_ban_fhd); - }else{//主播端 - ToastUtil.show(""); + } else {//主播端 + ToastUtil.show(R.string.function_is_suspended); } return; } diff --git a/common/src/main/res/values-en/strings.xml b/common/src/main/res/values-en/strings.xml index 867103039..fbe44671d 100644 --- a/common/src/main/res/values-en/strings.xml +++ b/common/src/main/res/values-en/strings.xml @@ -1000,4 +1000,5 @@ Limited ride And limited avatar frame updating There is no choice, the anchor is not turned on FHD live. There is no choice, the anchor is not turned on HD live. + Sorry, this feature is on hold. diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index c5207ac34..2c5c8b5e2 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1020,4 +1020,5 @@ 更新中 無法選擇,該主播未開啟超高清直播。 無法選擇,該主播未開啟高清直播。 + 抱歉,該功能暫停使用中。 diff --git a/config.gradle b/config.gradle index 88d9c1761..78cac4931 100644 --- a/config.gradle +++ b/config.gradle @@ -11,7 +11,7 @@ ext { //正式 // serverHost : "https://napi.yaoulive.com", -// 測試 +// serverHost : "https://ceshi.yaoulive.com", //腾讯地图 @@ -25,7 +25,7 @@ ext { baiduAppSecretKey: "nEVSgmuGpU0pjPr6VleEGGAl0hzGW52S", // true表示谷歌支付 false - isGooglePlay : false, + isGooglePlay : true, //是否上报异常日志 isUploadLog : false ] diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index 418673747..1d71091b1 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -9,8 +9,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; -import android.text.format.Formatter; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; @@ -34,7 +32,6 @@ import com.yunbao.common.http.HttpCallback; import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.ImageResultCallback; import com.yunbao.common.manager.IMLoginManager; -import com.yunbao.common.utils.DeviceUtils; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.L; import com.yunbao.common.utils.ProcessImageUtil; @@ -63,12 +60,8 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.io.File; -import java.util.Map; import cn.rongcloud.rtc.api.RCRTCEngine; -import cn.rongcloud.rtc.api.callback.IRCRTCStatusReportListener; -import cn.rongcloud.rtc.api.report.StatusBean; -import cn.rongcloud.rtc.api.report.StatusReport; import cn.rongcloud.rtc.api.stream.RCRTCCameraOutputStream; import cn.rongcloud.rtc.api.stream.RCRTCVideoStreamConfig; import cn.rongcloud.rtc.base.RCRTCParamsType; @@ -220,7 +213,11 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl ViewClicksAntiShake .clicksAntiShake( findViewById(R.id.btn_live_clarity), () -> { - LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, IMLoginManager.get(mContext).getSelectClarity()); + + LiveClarityCustomPopup liveClarityCustomPopup = + new LiveClarityCustomPopup(mContext, + IMLoginManager.get(mContext).getSelectClarity(), + IMLoginManager.get(mContext).getClarity() ? 0 : LiveClarityCustomPopup.BAN_1080, false); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override @@ -330,7 +327,6 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl } - @Override public void onClick(View v) { if (!canClick()) { @@ -377,7 +373,10 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl @Override public void selectClarity(int selectClarity) { - LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, selectClarity); + LiveClarityCustomPopup liveClarityCustomPopup = + new LiveClarityCustomPopup(mContext, + IMLoginManager.get(mContext).getSelectClarity(), + IMLoginManager.get(mContext).getClarity() ? 0 : LiveClarityCustomPopup.BAN_1080, false); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override From 0a3409f98aee18b46b0e48ea8f5bc9ed49e0ceee Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 6 Jan 2023 09:58:24 +0800 Subject: [PATCH 036/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BB=E6=92=AD?= =?UTF-8?q?=E7=AB=AF=E9=80=89=E6=8B=A9=E5=88=86=E8=BE=A8=E7=8E=87=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E6=8E=A5=E5=8F=A3=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/live/views/LiveNewReadyRyViewHolder.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index 1d71091b1..d8f3b76bb 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -9,6 +9,8 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; +import android.text.format.Formatter; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; @@ -32,6 +34,7 @@ import com.yunbao.common.http.HttpCallback; import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.ImageResultCallback; import com.yunbao.common.manager.IMLoginManager; +import com.yunbao.common.utils.DeviceUtils; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.L; import com.yunbao.common.utils.ProcessImageUtil; @@ -60,8 +63,12 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.io.File; +import java.util.Map; import cn.rongcloud.rtc.api.RCRTCEngine; +import cn.rongcloud.rtc.api.callback.IRCRTCStatusReportListener; +import cn.rongcloud.rtc.api.report.StatusBean; +import cn.rongcloud.rtc.api.report.StatusReport; import cn.rongcloud.rtc.api.stream.RCRTCCameraOutputStream; import cn.rongcloud.rtc.api.stream.RCRTCVideoStreamConfig; import cn.rongcloud.rtc.base.RCRTCParamsType; @@ -327,6 +334,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl } + @Override public void onClick(View v) { if (!canClick()) { From c3ddc62b95b64b394e5cb45629f50c98fdf5d692 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 6 Jan 2023 10:03:37 +0800 Subject: [PATCH 037/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BB=E6=92=AD?= =?UTF-8?q?=E7=AB=AF=E9=80=89=E6=8B=A9=E5=88=86=E8=BE=A8=E7=8E=87=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E6=8E=A5=E5=8F=A3=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index d8f3b76bb..d99df4d6f 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -384,7 +384,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, IMLoginManager.get(mContext).getSelectClarity(), - IMLoginManager.get(mContext).getClarity() ? 0 : LiveClarityCustomPopup.BAN_1080, false); + IMLoginManager.get(mContext).getClarity() ? 0 : LiveClarityCustomPopup.BAN_1080, false); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override From a37a92e211140bf1c4cbb8d9612ee14770c4d010 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Fri, 6 Jan 2023 15:04:27 +0800 Subject: [PATCH 038/118] =?UTF-8?q?=E4=BC=98=E5=8C=96PK=E6=97=B6=E7=82=B9?= =?UTF-8?q?=E5=87=BB=E7=A4=BC=E7=89=A9=E5=BC=B9=E7=AA=97=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E3=80=90=E5=BC=80=E9=80=9A=E8=B4=B5=E6=97=8F=E3=80=91=E6=8C=89?= =?UTF-8?q?=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/live/activity/LiveAudienceActivity.java | 9 +++++++++ .../com/yunbao/live/dialog/LiveGiftDialogFragment.java | 8 ++++++++ .../yunbao/live/presenter/LiveRyLinkMicPkPresenter.java | 6 ++++++ .../java/com/yunbao/live/views/LiveRoomViewHolder.java | 6 ++++++ .../java/com/yunbao/live/views/PortraitLiveManager.java | 8 +++++++- 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index d817ab129..deefce884 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -150,6 +150,7 @@ public class LiveAudienceActivity extends LiveActivity { private ImageView voicePress; private View titleLine; private boolean liveIndex = true; + private boolean isPk = false; @Override public T findViewById(@IdRes int id) { @@ -411,6 +412,7 @@ public class LiveAudienceActivity extends LiveActivity { return; } LiveGiftDialogFragment fragment = new LiveGiftDialogFragment(); + fragment.setPkStatus(isPk); fragment.setLiveGuardInfo(mLiveGuardInfo); Bundle bundle = new Bundle(); bundle.putString(Constants.LIVE_UID, mLiveUid); @@ -425,6 +427,7 @@ public class LiveAudienceActivity extends LiveActivity { return; } LiveGiftDialogFragment fragment = new LiveGiftDialogFragment(); + fragment.setPkStatus(isPk); fragment.setLiveGuardInfo(mLiveGuardInfo); Bundle bundle = new Bundle(); bundle.putString(Constants.LIVE_UID, mLiveUid); @@ -440,6 +443,7 @@ public class LiveAudienceActivity extends LiveActivity { } new Handler(Looper.getMainLooper()).post(() -> { LiveGiftDialogFragment fragment = new LiveGiftDialogFragment(); + fragment.setPkStatus(isPk); fragment.setLiveGuardInfo(mLiveGuardInfo); Bundle bundle = new Bundle(); bundle.putString(Constants.LIVE_UID, mLiveUid); @@ -673,6 +677,10 @@ public class LiveAudienceActivity extends LiveActivity { verticalViewPager.setEnableScroll(IMLoginManager.get(mContext).isSlide()); } + public void setPkStatus(boolean isPk) { + this.isPk = isPk; + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onLiveRoomChangeEvent(LiveRoomChangeEvent e) { if (verticalViewPager.ismEnableScroll()) { @@ -945,6 +953,7 @@ public class LiveAudienceActivity extends LiveActivity { return; } LiveGiftDialogFragment liveGiftDialogFragment = new LiveGiftDialogFragment(); + liveGiftDialogFragment.setPkStatus(isPk); liveGiftDialogFragment.setLiveGuardInfo(mLiveGuardInfo); bundle.putString(Constants.LIVE_UID, mLiveUid); bundle.putString(Constants.LIVE_STREAM, mStream); diff --git a/live/src/main/java/com/yunbao/live/dialog/LiveGiftDialogFragment.java b/live/src/main/java/com/yunbao/live/dialog/LiveGiftDialogFragment.java index c814aebb1..c0d56f7ae 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LiveGiftDialogFragment.java +++ b/live/src/main/java/com/yunbao/live/dialog/LiveGiftDialogFragment.java @@ -123,6 +123,7 @@ public class LiveGiftDialogFragment extends AbsDialogFragment implements View.On private TextView mVipGoldTitle; private TextView mVipGoldDesc; private TextView mGiftPackage; + private boolean isPk; @Override @@ -154,6 +155,10 @@ public class LiveGiftDialogFragment extends AbsDialogFragment implements View.On mLiveGuardInfo = liveGuardInfo; } + public void setPkStatus(boolean pk) { + isPk = pk; + } + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -276,6 +281,9 @@ public class LiveGiftDialogFragment extends AbsDialogFragment implements View.On } loadGiftListData(); loadUserVip(); + if (isPk) { + mVipGold.setVisibility(View.GONE); + } } /** diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index ff2473388..e421e7f35 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -387,12 +387,18 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { mPkTimeCount--; if (mPkTimeCount >= 0) {// nextPkTimeCountDown(); + if (mContext instanceof LiveAudienceActivity) { + ((LiveAudienceActivity)mContext).setPkStatus(true); + } } else { if (mIsPkEnd) { onLinkMicPkClose(0); if (mIsAnchor) { ((LiveRyAnchorActivity) mContext).setPkBtnVisible(true); } + if (mContext instanceof LiveAudienceActivity) { + ((LiveAudienceActivity)mContext).setPkStatus(false); + } //如果PK结束Im没有发送关闭PK的消息,倒计时结束自动关闭 // if (mLiveLinkMicPkViewHolder != null) { // mLiveLinkMicPkViewHolder.removeFromParent(); diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 0952acacb..80e7c6873 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -447,12 +447,18 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis String s1 = StringUtil.getDurationText(mPkTimeCount * 1000); time.setText("PK時間:" + s1); mHandler.sendEmptyMessageAtTime(WHAT_PK_TIME, getNextSecondTime()); + if (mContext instanceof LiveAudienceActivity) { + ((LiveAudienceActivity)mContext).setPkStatus(true); + } } } else { time.setVisibility(View.GONE); if (mHandler != null) { mHandler.removeCallbacksAndMessages(null); } + if (mContext instanceof LiveAudienceActivity) { + ((LiveAudienceActivity)mContext).setPkStatus(false); + } endDRGif(); } } diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 0b480f961..a4d8ce394 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -357,7 +357,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe landscape = data.getLiveInfo().getLandscape(); mLivePlayViewHolder.setLiveBeanLandscape(landscape); mLivePlayViewHolder.setLiveEnterRoomNewModel(data); - mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1)==2?1:(data.getClarityType() - 1)); + mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1) == 2 ? 1 : (data.getClarityType() - 1)); //是否热度卡加成 liveHandler.postDelayed(() -> mLiveRoomViewHolder.getIsHot(data.getIsUseHotCard()), 700); @@ -1269,6 +1269,9 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe if (mLivePlayViewHolder != null) { mLivePlayViewHolder.setLiveBeanLandscape(1); } + if (mContext instanceof LiveAudienceActivity) { + ((LiveAudienceActivity)mContext).setPkStatus(true); + } } @Override @@ -1283,6 +1286,9 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe if (mLiveRoomViewHolder != null) { mLivePlayViewHolder.setLiveBeanLandscape(landscape); } + if (mContext instanceof LiveAudienceActivity) { + ((LiveAudienceActivity)mContext).setPkStatus(false); + } } @Override From 42052b7465c3f17100f7755f47cc137147961f30 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 6 Jan 2023 15:49:00 +0800 Subject: [PATCH 039/118] =?UTF-8?q?=E8=BD=AF=E4=BB=B6=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/common/manager/APKManager.java | 4 ++-- .../yunbao/common/views/APKUpdateCustomPopup.java | 13 +++++++++---- config.gradle | 10 +++++----- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/manager/APKManager.java b/common/src/main/java/com/yunbao/common/manager/APKManager.java index 266e22827..d32f8211d 100644 --- a/common/src/main/java/com/yunbao/common/manager/APKManager.java +++ b/common/src/main/java/com/yunbao/common/manager/APKManager.java @@ -1,7 +1,6 @@ package com.yunbao.common.manager; import android.content.Context; -import android.text.TextUtils; import com.yunbao.common.CommonAppContext; import com.yunbao.common.manager.base.BaseCacheManager; @@ -52,7 +51,8 @@ public class APKManager extends BaseCacheManager { } public boolean getApkVerNew() { - return TextUtils.equals(VersionUtil.getVersion(), getString(APK_VER)); + + return VersionUtil.isLatest(getString(APK_VER)); } public void setAPKIsUp(int apkIsUp) { diff --git a/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java b/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java index 025bdd14e..c84312521 100644 --- a/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/APKUpdateCustomPopup.java @@ -86,12 +86,17 @@ public class APKUpdateCustomPopup extends CenterPopupView { ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.dialog_close), new ViewClicksAntiShake.ViewClicksCallBack() { @Override public void onViewClicks() { - if (CommonAppConfig.IS_GOOGLE_PLAY && APKManager.get().getAPKGoogleIsUp() != 1) { - dismiss(); - } - if (!CommonAppConfig.IS_GOOGLE_PLAY && APKManager.get().getApkIsUp() != 1) { + if (mInside){ dismiss(); + }else { + if (CommonAppConfig.IS_GOOGLE_PLAY && APKManager.get().getAPKGoogleIsUp() != 1) { + dismiss(); + } + if (!CommonAppConfig.IS_GOOGLE_PLAY && APKManager.get().getApkIsUp() != 1) { + dismiss(); + } } + } } ); diff --git a/config.gradle b/config.gradle index 78cac4931..1422bbd55 100644 --- a/config.gradle +++ b/config.gradle @@ -1,18 +1,18 @@ ext { android = [ compileSdkVersion: 31, - buildToolsVersion: "28.0.3", + buildToolsVersion: "29.0.2", minSdkVersion : 21, targetSdkVersion : 31, versionCode : 402, - versionName : "6.4.6" + versionName : "6.4.7" ] manifestPlaceholders = [ //正式 -// serverHost : "https://napi.yaoulive.com", + serverHost : "https://napi.yaoulive.com", // - serverHost : "https://ceshi.yaoulive.com", +// serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", @@ -25,7 +25,7 @@ ext { baiduAppSecretKey: "nEVSgmuGpU0pjPr6VleEGGAl0hzGW52S", // true表示谷歌支付 false - isGooglePlay : true, + isGooglePlay : false, //是否上报异常日志 isUploadLog : false ] From a0949f090397024892de517e71361b757fbe4da9 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Fri, 6 Jan 2023 15:53:09 +0800 Subject: [PATCH 040/118] =?UTF-8?q?=E6=9A=82=E6=97=B6=E5=8F=96=E6=B6=88?= =?UTF-8?q?=E8=A7=82=E4=BC=97=E7=AB=AF=E7=9B=91=E6=B5=8B=E5=8D=A1=E9=A1=BF?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=88=87=E6=8D=A2=E5=88=86=E8=BE=A8=E7=8E=87?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/views/LivePlayRyViewHolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index b935e18da..d3e391dcf 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -1072,7 +1072,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onPlaybackStateChanged(int playbackState) { Player.Listener.super.onPlaybackStateChanged(playbackState); if (playbackState == Player.STATE_BUFFERING) { - showLoadingDialog(); + //showLoadingDialog(); OkDownload.getInstance().pauseAll(); } } From 80993c7d2d59103e1bdd4c7011985fb274720eeb Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sat, 7 Jan 2023 09:54:37 +0800 Subject: [PATCH 041/118] =?UTF-8?q?=E6=9B=B4=E6=8D=A2=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E8=A7=86=E9=A2=91=E6=B8=B2=E6=9F=93=E5=B1=82=E4=BB=A5?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86=E6=9C=BA=E5=9E=8B=E5=92=8C?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8=E6=BB=91=E5=8A=A8=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=97=B6=E7=99=BD=E5=B1=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/utils/LiveExoPlayerManager.java | 16 +++++++++------ .../live/views/LivePlayRyViewHolder.java | 15 +++++--------- .../live/views/LiveRoomPlayViewHolder.java | 2 ++ .../live/views/PortraitLiveManager.java | 20 +++++++++++-------- .../main/res/layout/view_live_play_ksy.xml | 5 ++++- 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 7ca05a53f..deb8cba68 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -6,12 +6,12 @@ import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; -import android.view.SurfaceView; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.analytics.AnalyticsListener; +import com.google.android.exoplayer2.ui.StyledPlayerView; import com.google.android.exoplayer2.video.VideoSize; /** @@ -23,7 +23,7 @@ public class LiveExoPlayerManager { private final int MODEL_PLAY2 = 1;//当前子播放器 private Context mContext; private ExoPlayer player1, player2; - private SurfaceView mainView;//渲染视图 + private StyledPlayerView mainView;//渲染视图 private int status = MODEL_PLAY1; private Player.Listener listener; private boolean isSwitchUrl = false;//是否为主动切换播放器 @@ -42,11 +42,12 @@ public class LiveExoPlayerManager { setAnalyticsListener(); } + public void setListener(Player.Listener listener) { this.listener = listener; } - public void setMainView(SurfaceView mainView) { + public void setMainView(StyledPlayerView mainView) { this.mainView = mainView; } @@ -119,7 +120,8 @@ public class LiveExoPlayerManager { Player.Listener.super.onIsPlayingChanged(isPlaying); if (isPlaying) { Log.i(TAG, "onIsPlayingChanged1: 播放了"); - player1.setVideoSurfaceView(mainView); + //player1.setVideoSurfaceView(mainView); + mainView.setPlayer(player1); status = MODEL_PLAY1; isSwitchUrl = false; if (listener != null) { @@ -169,7 +171,8 @@ public class LiveExoPlayerManager { Player.Listener.super.onIsPlayingChanged(isPlaying); if (isPlaying) { Log.i(TAG, "onIsPlayingChanged2: 播放了"); - player2.setVideoSurfaceView(mainView); + //player2.setVideoSurfaceView(mainView); + mainView.setPlayer(player2); status = MODEL_PLAY2; isSwitchUrl = false; if (listener != null) { @@ -202,7 +205,8 @@ public class LiveExoPlayerManager { public void startUrl(String url) { isSwitchUrl = true; playBufferIndex = 0; - getNowPlayer().setVideoSurfaceView(mainView); + //getNowPlayer().setVideoSurfaceView(mainView); + mainView.setPlayer(getNowPlayer()); getNowPlayer().setMediaItem(createMediaItem(url)); getNowPlayer().prepare(); getNowPlayer().play(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index d3e391dcf..e550e8c64 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -13,7 +13,6 @@ import android.os.Looper; import android.text.TextUtils; import android.util.Log; import android.view.Gravity; -import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; @@ -22,13 +21,9 @@ import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; -import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.Tracks; +import com.google.android.exoplayer2.ui.StyledPlayerView; import com.google.android.exoplayer2.video.VideoSize; import com.lxj.xpopup.XPopup; import com.lxj.xpopup.core.BasePopupView; @@ -93,7 +88,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { private ViewGroup mLeftContainer; private ViewGroup mRightContainer; private RelativeLayout mPkContainer; - public static SurfaceView mVideoView; + public StyledPlayerView mVideoView; private View mLoading, mLoading2; private ImageView mCover; @@ -145,7 +140,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { mLeftContainer = (ViewGroup) findViewById(R.id.left_container); mRightContainer = (ViewGroup) findViewById(R.id.right_container); mPkContainer = (RelativeLayout) findViewById(R.id.pk_container); - mVideoView = (SurfaceView) findViewById(R.id.video_view); + mVideoView = (StyledPlayerView) findViewById(R.id.video_view); ry_view = (FrameLayout) findViewById(R.id.ry_view); leave = (ImageView) findViewById(R.id.leave); mLoading = findViewById(R.id.loading); @@ -353,8 +348,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void stopPlay2() { } - - public static void setViewUP(int i) { + @Override + public void setViewUP(int i) { if (mVideoView == null) return; Log.e("收", "整理" + i); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index 420351b89..49f7d01d8 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -62,6 +62,8 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL this.mLiveBean = data; } + public void setViewUP(int i){} + public OnMicCallback getOnMicCallback() { return onMicCallback; } diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index a4d8ce394..90bce1437 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -492,17 +492,17 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe } } - if (data.getEnterRoomInfo().getIsconnection() != null && data.getEnterRoomInfo().getIsconnection().equals("1")) { + if (mLivePlayViewHolder != null && data.getEnterRoomInfo().getIsconnection() != null && data.getEnterRoomInfo().getIsconnection().equals("1")) { - LivePlayRyViewHolder.setViewUP(1); + mLivePlayViewHolder.setViewUP(1); } if (mLiveRoomViewHolder != null) { mLiveRoomViewHolder.pkHandler = false; } - if (pkInfo.getIntValue("ifpk") == 1 && pkInfo.getString("end_pk_time").equals("0")) {//pk开始了 + if (mLivePlayViewHolder != null && pkInfo.getIntValue("ifpk") == 1 && pkInfo.getString("end_pk_time").equals("0")) {//pk开始了 - LivePlayRyViewHolder.setViewUP(2); + mLivePlayViewHolder.setViewUP(2); //pk排名数据 LivePKUserListBean livePKUserListBean = JSON.parseObject(pkInfo.getString("pk_top_users"), LivePKUserListBean.class); @@ -526,7 +526,9 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.pkHandler = true; mLiveRoomViewHolder.initPkRank(null); } - LivePlayRyViewHolder.setViewUP(3); + if(mLivePlayViewHolder != null) { + mLivePlayViewHolder.setViewUP(3); + } //pk排名数据 LivePKUserListBean livePKUserListBean = JSON.parseObject(pkInfo.getString("pk_top_users"), LivePKUserListBean.class); @@ -541,7 +543,9 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe if (mLiveRoomViewHolder != null) { mLiveRoomViewHolder.initPkRank(null); } - LivePlayRyViewHolder.setViewUP(4); + if(mLivePlayViewHolder != null) { + mLivePlayViewHolder.setViewUP(4); + } mLiveRoomViewHolder.UpPkBar(pkInfo.getJSONArray("userlist"), mLiveBean.getUid(), pkInfo.getIntValue("drpk_time")); } @@ -1270,7 +1274,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLivePlayViewHolder.setLiveBeanLandscape(1); } if (mContext instanceof LiveAudienceActivity) { - ((LiveAudienceActivity)mContext).setPkStatus(true); + ((LiveAudienceActivity) mContext).setPkStatus(true); } } @@ -1287,7 +1291,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLivePlayViewHolder.setLiveBeanLandscape(landscape); } if (mContext instanceof LiveAudienceActivity) { - ((LiveAudienceActivity)mContext).setPkStatus(false); + ((LiveAudienceActivity) mContext).setPkStatus(false); } } diff --git a/live/src/main/res/layout/view_live_play_ksy.xml b/live/src/main/res/layout/view_live_play_ksy.xml index 6dc70080c..a7b2b1a81 100644 --- a/live/src/main/res/layout/view_live_play_ksy.xml +++ b/live/src/main/res/layout/view_live_play_ksy.xml @@ -7,9 +7,12 @@ android:layout_height="match_parent"> - Date: Sat, 7 Jan 2023 10:13:34 +0800 Subject: [PATCH 042/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=A0=E4=B8=BA?= =?UTF-8?q?=E6=9B=B4=E6=8D=A2=E6=B8=B2=E6=9F=93=E5=B1=82=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E5=9C=A8=E5=88=87=E6=8D=A2=E5=88=86=E8=BE=A8=E7=8E=87=E6=97=B6?= =?UTF-8?q?=E4=BC=9A=E9=BB=91=E5=B1=8F=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/utils/LiveExoPlayerManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index deb8cba68..ae4887ba7 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -35,8 +35,6 @@ public class LiveExoPlayerManager { this.mContext = mContext; player1 = new ExoPlayer.Builder(mContext).build(); player2 = new ExoPlayer.Builder(mContext).build(); - player1.setVideoScalingMode(VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); - player2.setVideoScalingMode(VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); handler = new Handler(Looper.getMainLooper()); setListener(); setAnalyticsListener(); @@ -49,6 +47,7 @@ public class LiveExoPlayerManager { public void setMainView(StyledPlayerView mainView) { this.mainView = mainView; + this.mainView.setKeepContentOnPlayerReset(true); } private void setAnalyticsListener() { From 9f517199feaab15489a8e6ceff19f95235284993 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sat, 7 Jan 2023 14:24:57 +0800 Subject: [PATCH 043/118] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=A9=E6=A2=AFPK?= =?UTF-8?q?=E8=BF=9E=E8=83=9C=E6=A0=87=E8=AF=86=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- live/src/main/res/layout/view_live_room.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/live/src/main/res/layout/view_live_room.xml b/live/src/main/res/layout/view_live_room.xml index 3f8cca71b..1a4b20e95 100644 --- a/live/src/main/res/layout/view_live_room.xml +++ b/live/src/main/res/layout/view_live_room.xml @@ -1283,12 +1283,12 @@ android:layout_marginStart="13dp" android:layout_marginBottom="10dp" android:background="@drawable/bg_live_item_pk_rank_red" - android:paddingStart="17dp" - android:paddingTop="5dp" - android:paddingEnd="17dp" - android:paddingBottom="5dp" + android:paddingStart="10dp" + android:paddingTop="3dp" + android:paddingEnd="10dp" + android:paddingBottom="3dp" android:textColor="#FFFFFF" - android:textSize="15sp" + android:textSize="12sp" android:textStyle="bold" android:visibility="gone" /> @@ -1301,12 +1301,12 @@ android:layout_marginEnd="13dp" android:layout_marginBottom="10dp" android:background="@drawable/bg_live_item_pk_rank_blue" - android:paddingStart="17dp" - android:paddingTop="5dp" - android:paddingEnd="17dp" - android:paddingBottom="5dp" + android:paddingStart="10dp" + android:paddingTop="3dp" + android:paddingEnd="10dp" + android:paddingBottom="3dp" android:textColor="#FFFFFF" - android:textSize="15sp" + android:textSize="12sp" android:textStyle="bold" android:visibility="gone" /> From 0b7a3cc50e93757d3fb2f81025fc5c48cc0cce4e Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sat, 7 Jan 2023 14:43:35 +0800 Subject: [PATCH 044/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=AE=A4=E6=8A=BD=E6=90=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java | 2 +- live/src/main/res/layout/view_live_room.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 80e7c6873..ebe499371 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -874,7 +874,7 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mChatRecyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LiveChatRecyclerViewLayoutManager(mContext); - layoutManager.setStackFromEnd(true); + //layoutManager.setStackFromEnd(true); mChatRecyclerView.setLayoutManager(layoutManager); mChatRecyclerView.addItemDecoration(new TopGradual()); mChatRecyclerView.setItemViewCacheSize(10); diff --git a/live/src/main/res/layout/view_live_room.xml b/live/src/main/res/layout/view_live_room.xml index 1a4b20e95..c89183182 100644 --- a/live/src/main/res/layout/view_live_room.xml +++ b/live/src/main/res/layout/view_live_room.xml @@ -190,7 +190,7 @@ From 112bec58dffc57bc55966c6baee77c9049aaeddf Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Sat, 7 Jan 2023 14:53:12 +0800 Subject: [PATCH 045/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=83=AD=E5=BA=A6?= =?UTF-8?q?=E5=8A=A0=E6=88=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 2 +- .../yunbao/live/activity/LiveAudienceActivity.java | 3 +++ .../com/yunbao/live/views/LiveRoomViewHolder.java | 8 ++++++-- .../com/yunbao/live/views/PortraitLiveManager.java | 14 ++++++++++++-- live/src/main/res/layout/view_live_room.xml | 4 ++-- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/config.gradle b/config.gradle index 1422bbd55..b123cc49e 100644 --- a/config.gradle +++ b/config.gradle @@ -25,7 +25,7 @@ ext { baiduAppSecretKey: "nEVSgmuGpU0pjPr6VleEGGAl0hzGW52S", // true表示谷歌支付 false - isGooglePlay : false, + isGooglePlay : true, //是否上报异常日志 isUploadLog : false ] diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index deefce884..037ff8093 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -679,6 +679,9 @@ public class LiveAudienceActivity extends LiveActivity { public void setPkStatus(boolean isPk) { this.isPk = isPk; + if (manager != null) { + manager.setPkStatus(isPk); + } } @Subscribe(threadMode = ThreadMode.MAIN) diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index ebe499371..e7d5a5349 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -448,7 +448,7 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis time.setText("PK時間:" + s1); mHandler.sendEmptyMessageAtTime(WHAT_PK_TIME, getNextSecondTime()); if (mContext instanceof LiveAudienceActivity) { - ((LiveAudienceActivity)mContext).setPkStatus(true); + ((LiveAudienceActivity) mContext).setPkStatus(true); } } } else { @@ -457,12 +457,16 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mHandler.removeCallbacksAndMessages(null); } if (mContext instanceof LiveAudienceActivity) { - ((LiveAudienceActivity)mContext).setPkStatus(false); + ((LiveAudienceActivity) mContext).setPkStatus(false); } endDRGif(); } } + public void hotAddVisibility(boolean visibility) { + ft_hot_add.setVisibility(visibility ? View.GONE : View.VISIBLE); + } + public void endDRGif() { if (dr_pk_end_gif.getVisibility() == View.GONE) { dr_pk_end_gif.setVisibility(View.VISIBLE); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 90bce1437..086d842a8 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -526,7 +526,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.pkHandler = true; mLiveRoomViewHolder.initPkRank(null); } - if(mLivePlayViewHolder != null) { + if (mLivePlayViewHolder != null) { mLivePlayViewHolder.setViewUP(3); } @@ -543,7 +543,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe if (mLiveRoomViewHolder != null) { mLiveRoomViewHolder.initPkRank(null); } - if(mLivePlayViewHolder != null) { + if (mLivePlayViewHolder != null) { mLivePlayViewHolder.setViewUP(4); } @@ -1278,6 +1278,16 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe } } + /** + * pk状态 + * + * @param isPk + */ + public void setPkStatus(boolean isPk) { + if (mLiveRoomViewHolder != null) + mLiveRoomViewHolder.hotAddVisibility(isPk); + } + @Override public void onLinkMicPkClose(int i) { diff --git a/live/src/main/res/layout/view_live_room.xml b/live/src/main/res/layout/view_live_room.xml index c89183182..427922cf0 100644 --- a/live/src/main/res/layout/view_live_room.xml +++ b/live/src/main/res/layout/view_live_room.xml @@ -709,8 +709,8 @@ android:layout_height="27dp" android:layout_below="@id/live_time" android:layout_marginLeft="12dp" - android:layout_marginTop="12dp" - android:visibility="gone"> + android:layout_marginTop="-12dp" + android:visibility="visible"> Date: Sat, 7 Jan 2023 15:19:33 +0800 Subject: [PATCH 046/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E8=81=8A=E5=A4=A9=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/views/LiveRoomViewHolder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index e7d5a5349..99d82f70c 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -878,7 +878,9 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mChatRecyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LiveChatRecyclerViewLayoutManager(mContext); - //layoutManager.setStackFromEnd(true); + layoutManager.setOrientation(RecyclerView.VERTICAL); + layoutManager.setReverseLayout(false); + layoutManager.setStackFromEnd(true); mChatRecyclerView.setLayoutManager(layoutManager); mChatRecyclerView.addItemDecoration(new TopGradual()); mChatRecyclerView.setItemViewCacheSize(10); From 494aa6b52d3ed253e6797a60ae23ebb1992f290c Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sat, 7 Jan 2023 15:35:53 +0800 Subject: [PATCH 047/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E7=94=BB=E9=9D=A2=E5=8F=98=E5=BD=A2=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/utils/LiveExoPlayerManager.java | 7 ++++++- .../java/com/yunbao/live/views/PortraitLiveManager.java | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index ae4887ba7..d1536b002 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -7,6 +7,7 @@ import android.os.Handler; import android.os.Looper; import android.util.Log; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Player; @@ -27,7 +28,7 @@ public class LiveExoPlayerManager { private int status = MODEL_PLAY1; private Player.Listener listener; private boolean isSwitchUrl = false;//是否为主动切换播放器 - private String TAG = "播放"; + private String TAG = "播放器"; private int playBufferIndex = 0;//卡顿计数器 private Handler handler; @@ -35,6 +36,8 @@ public class LiveExoPlayerManager { this.mContext = mContext; player1 = new ExoPlayer.Builder(mContext).build(); player2 = new ExoPlayer.Builder(mContext).build(); + player1.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); + player2.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); handler = new Handler(Looper.getMainLooper()); setListener(); setAnalyticsListener(); @@ -132,6 +135,7 @@ public class LiveExoPlayerManager { @Override public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); + Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); if (listener != null) { listener.onVideoSizeChanged(videoSize); } @@ -202,6 +206,7 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void startUrl(String url) { + Log.i(TAG, "startUrl: "+url); isSwitchUrl = true; playBufferIndex = 0; //getNowPlayer().setVideoSurfaceView(mainView); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 086d842a8..1fee9e961 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -357,7 +357,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe landscape = data.getLiveInfo().getLandscape(); mLivePlayViewHolder.setLiveBeanLandscape(landscape); mLivePlayViewHolder.setLiveEnterRoomNewModel(data); - mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1) == 2 ? 1 : (data.getClarityType() - 1)); + //mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1) == 2 ? 1 : (data.getClarityType() - 1)); //是否热度卡加成 liveHandler.postDelayed(() -> mLiveRoomViewHolder.getIsHot(data.getIsUseHotCard()), 700); From 36248eaeef97e361346e06a3656c39f2acd9e6b8 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Sat, 7 Jan 2023 15:39:26 +0800 Subject: [PATCH 048/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E8=81=8A=E5=A4=A9=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/views/LiveRoomViewHolder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 99d82f70c..875f055ae 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -879,8 +879,8 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mChatRecyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LiveChatRecyclerViewLayoutManager(mContext); layoutManager.setOrientation(RecyclerView.VERTICAL); - layoutManager.setReverseLayout(false); - layoutManager.setStackFromEnd(true); +// layoutManager.setReverseLayout(false); +// layoutManager.setStackFromEnd(true); mChatRecyclerView.setLayoutManager(layoutManager); mChatRecyclerView.addItemDecoration(new TopGradual()); mChatRecyclerView.setItemViewCacheSize(10); From eadcaf826ba236e687256900df7ea0ee322e52fe Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Sat, 7 Jan 2023 16:46:11 +0800 Subject: [PATCH 049/118] =?UTF-8?q?xiu=E6=94=B9=E7=9B=B4=E6=92=AD=E9=97=B4?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=88=97=E8=A1=A8=E6=BB=9A=E5=8A=A8=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=83=AD=E5=BA=A6=E5=8A=A0?= =?UTF-8?q?=E6=88=90=E5=88=97=E8=A1=A8=E7=AD=89=E7=BA=A7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/live/adapter/LiveChatAdapter.java | 10 ++++++---- .../live/dialog/LiveGiveHotDialogFragment.java | 14 +++++++++++++- .../com/yunbao/live/views/LiveRoomViewHolder.java | 6 +++--- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java index 7cff740ac..cce3d4c7d 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java @@ -129,7 +129,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (isBottom && dy >= 0) return; - // Log.i(TAG, "onScrolled: " + dy); + Log.i(TAG, "onScrolled: " + dy); mRecyclerViewScrolledDy = dy; isBottom = false; } @@ -140,6 +140,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { if (newState == 0 && isSlideToBottom(recyclerView)) { // Log.i(TAG, "onScrollStateChanged: 到底部了"); mRecyclerViewScrolledDy = 0; + scrollToBottom(); isBottom = true; } else if (newState == 0) { // Log.i(TAG, "onScrollStateChanged: 不是底部"); @@ -394,7 +395,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { } @SuppressLint("NotifyDataSetChanged") - public void insertItem(LiveChatBean bean) { + public synchronized void insertItem(LiveChatBean bean) { if (bean == null) { return; } @@ -411,9 +412,9 @@ public class LiveChatAdapter extends RecyclerView.Adapter { } else { notifyItemInserted(getItemCount()); } - size = mList.size(); +// size = mList.size(); if (isBottom || mRecyclerViewScrolledDy == 0) { - scrollToBottom(); + scrollToBottom(); } else { Bus.get().post(new LiveAudienceEvent() .setType(LiveAudienceEvent.LiveAudienceType.NEW_MESSAGE_REMINDER)); @@ -428,6 +429,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { } + private void scrollToBottom(final RecyclerView recyclerView) { // scroll to last item to get the view of last item final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); diff --git a/live/src/main/java/com/yunbao/live/dialog/LiveGiveHotDialogFragment.java b/live/src/main/java/com/yunbao/live/dialog/LiveGiveHotDialogFragment.java index b82f1e3c8..691a1c4d4 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LiveGiveHotDialogFragment.java +++ b/live/src/main/java/com/yunbao/live/dialog/LiveGiveHotDialogFragment.java @@ -3,6 +3,7 @@ package com.yunbao.live.dialog; import android.annotation.SuppressLint; import android.app.ActionBar; import android.content.Context; +import android.graphics.drawable.Drawable; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; @@ -37,6 +38,7 @@ import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.bean.HotBean; import com.yunbao.live.custom.TopGradual; import com.yunbao.live.http.LiveHttpUtil; +import com.yunbao.live.utils.LiveTextRender; import java.net.MalformedURLException; import java.net.URL; @@ -205,7 +207,17 @@ public class LiveGiveHotDialogFragment extends AbsDialogFragment { viewHolder.sex.setImageResource(CommonIconUtil.getSexIcon(mDatas.get(position).getSex())); LevelBean levelBean = CommonAppConfig.getInstance().getLevel(mDatas.get(position).getLevel()); if (levelBean != null) { - ImgLoader.display(mContext, levelBean.getThumb(), viewHolder.level); + new LiveTextRender().getLevelImage(mContext, levelBean.getLevel(), new ImgLoader.DrawableCallback() { + @Override + public void onLoadSuccess(Drawable drawable) { + ImgLoader.display2(mContext, drawable, viewHolder.level); + } + + @Override + public void onLoadFailed() { + + } + }); } String hotStr = mDatas.get(position).getHot_score().substring(0, mDatas.get(position).getHot_score().length() - 3); viewHolder.tv_hot_number.setText(hotStr + "k"); diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 875f055ae..86c03492a 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -877,10 +877,10 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mChatRecyclerView.setLayoutParams(params1); mChatRecyclerView.setHasFixedSize(true); - LinearLayoutManager layoutManager = new LiveChatRecyclerViewLayoutManager(mContext); + LinearLayoutManager layoutManager = new LinearLayoutManager(mContext); layoutManager.setOrientation(RecyclerView.VERTICAL); -// layoutManager.setReverseLayout(false); -// layoutManager.setStackFromEnd(true); +// layoutManager.setReverseLayout(true); + layoutManager.setStackFromEnd(true); mChatRecyclerView.setLayoutManager(layoutManager); mChatRecyclerView.addItemDecoration(new TopGradual()); mChatRecyclerView.setItemViewCacheSize(10); From ddf56963bbd06742c1b1482d46f1c7103d66b6d0 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sat, 7 Jan 2023 16:54:05 +0800 Subject: [PATCH 050/118] =?UTF-8?q?=E8=B0=83=E6=95=B4PK=E5=A4=A9=E6=A2=AF?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../res/mipmap-mdpi/icon_rank_top_box.png | Bin 13121 -> 17902 bytes live/src/main/res/layout/view_live_room.xml | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/res/mipmap-mdpi/icon_rank_top_box.png b/common/src/main/res/mipmap-mdpi/icon_rank_top_box.png index 25e96cfa4d002ed61be4c2517e1aba1ea95defff..47838ee750f3da854bc65e1932cb846cde4c4b00 100644 GIT binary patch literal 17902 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 literal 13121 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 b6i^HRc8pa@kemw)00000NkvXXu0mjfb{EZ! diff --git a/live/src/main/res/layout/view_live_room.xml b/live/src/main/res/layout/view_live_room.xml index 427922cf0..b22fafbf0 100644 --- a/live/src/main/res/layout/view_live_room.xml +++ b/live/src/main/res/layout/view_live_room.xml @@ -1260,8 +1260,8 @@ Date: Sat, 7 Jan 2023 17:13:27 +0800 Subject: [PATCH 051/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E5=AE=A4=E6=BB=91=E5=8A=A8=E5=8A=A8=E7=94=BB=E6=95=88=E6=9E=9C?= =?UTF-8?q?=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/adapter/LiveChatRecyclerViewLayoutManager.java | 2 +- .../src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java | 2 +- .../main/java/com/yunbao/live/views/PortraitLiveManager.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveChatRecyclerViewLayoutManager.java b/live/src/main/java/com/yunbao/live/adapter/LiveChatRecyclerViewLayoutManager.java index fdd546e65..0f4bcc4a6 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveChatRecyclerViewLayoutManager.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveChatRecyclerViewLayoutManager.java @@ -10,7 +10,7 @@ import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.RecyclerView; public class LiveChatRecyclerViewLayoutManager extends LinearLayoutManager { - private static final float MILLISECONDS_PER_INCH = 200f; + private static final float MILLISECONDS_PER_INCH = 150f; public LiveChatRecyclerViewLayoutManager(Context context) { super(context); } diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 86c03492a..720e608c2 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -877,7 +877,7 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mChatRecyclerView.setLayoutParams(params1); mChatRecyclerView.setHasFixedSize(true); - LinearLayoutManager layoutManager = new LinearLayoutManager(mContext); + LinearLayoutManager layoutManager = new LiveChatRecyclerViewLayoutManager(mContext); layoutManager.setOrientation(RecyclerView.VERTICAL); // layoutManager.setReverseLayout(true); layoutManager.setStackFromEnd(true); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 1fee9e961..9fcf3ef3d 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -299,7 +299,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mask.setVisibility(View.VISIBLE); mLivePlayViewHolder.setLiveBean(mLiveBean); mLivePlayViewHolder.setCover(mLiveBean.getAvatar()); - mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_DEF); + mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_720); mLivePlayViewHolder.setOnMicCallback(new LiveRoomPlayViewHolder.OnMicCallback() { @Override public void onMikUpdate() { From 65efa88d4ae2fbf13275ba3a0f4da8b58abc99e9 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Sun, 8 Jan 2023 14:09:01 +0800 Subject: [PATCH 052/118] =?UTF-8?q?=E8=BD=AF=E4=BB=B6=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/src/main/res/layout/apk_update_custom_popup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/res/layout/apk_update_custom_popup.xml b/common/src/main/res/layout/apk_update_custom_popup.xml index a59817e4d..4ce8bf49e 100644 --- a/common/src/main/res/layout/apk_update_custom_popup.xml +++ b/common/src/main/res/layout/apk_update_custom_popup.xml @@ -59,7 +59,7 @@ android:layout_width="200dp" android:layout_height="9dp" android:max="100" - android:progress="40" + android:progress="0" android:progressDrawable="@drawable/progress_bg" /> Date: Sun, 8 Jan 2023 14:21:52 +0800 Subject: [PATCH 053/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=A7=82=E4=BC=97?= =?UTF-8?q?=E7=AB=AF=E9=80=89=E6=8B=A9=E5=88=86=E8=BE=A8=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/views/LiveClarityCustomPopup.java | 5 +++++ .../live/utils/LiveExoPlayerManager.java | 11 +++++++--- .../live/views/LivePlayRyViewHolder.java | 22 ++++++++++++++----- .../live/views/LiveRoomPlayViewHolder.java | 2 +- .../live/views/PortraitLiveManager.java | 3 ++- .../main/res/layout/view_live_play_ksy.xml | 1 - 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java index 3e5edb01a..f4ed86164 100644 --- a/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java +++ b/common/src/main/java/com/yunbao/common/views/LiveClarityCustomPopup.java @@ -49,6 +49,11 @@ public class LiveClarityCustomPopup extends BottomPopupView implements View.OnCl selectClarity = 0; } this.isUser = isUser; + if (banSelect == BAN_720) { + selectClarity = 0; + } else if (banSelect == BAN_1080 && selectClarity == 3) { + selectClarity = 2; + } this.selectClarity = selectClarity; } diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index d1536b002..4a810273e 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -1,7 +1,5 @@ package com.yunbao.live.utils; -import static com.google.android.exoplayer2.C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING; - import android.content.Context; import android.os.Handler; import android.os.Looper; @@ -12,6 +10,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.analytics.AnalyticsListener; +import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.StyledPlayerView; import com.google.android.exoplayer2.video.VideoSize; @@ -52,6 +51,10 @@ public class LiveExoPlayerManager { this.mainView = mainView; this.mainView.setKeepContentOnPlayerReset(true); } + public void setViewResizeMode(boolean isPhone){ + mainView.setResizeMode(isPhone?AspectRatioFrameLayout.RESIZE_MODE_ZOOM:AspectRatioFrameLayout.RESIZE_MODE_FIT); + mainView.requestLayout(); + } private void setAnalyticsListener() { player1.addAnalyticsListener(new AnalyticsListener() { @@ -135,6 +138,7 @@ public class LiveExoPlayerManager { @Override public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); + setViewResizeMode(videoSize.height>videoSize.width); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); if (listener != null) { listener.onVideoSizeChanged(videoSize); @@ -187,6 +191,7 @@ public class LiveExoPlayerManager { @Override public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); + setViewResizeMode(videoSize.height>videoSize.width); if (listener != null) { listener.onVideoSizeChanged(videoSize); } @@ -206,7 +211,7 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void startUrl(String url) { - Log.i(TAG, "startUrl: "+url); + Log.i(TAG, "startUrl: "+url+" > "+mainView.getResizeMode()); isSwitchUrl = true; playBufferIndex = 0; //getNowPlayer().setVideoSurfaceView(mainView); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index e550e8c64..6ae0bb65a 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -192,8 +192,11 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public synchronized void setLiveBeanLandscape(int landscape) { +// landscape=1; + Log.i(TAG, "setLiveBeanLandscape: " + landscape); this.landscape = landscape; this.videoLandscape = landscape; + mPlayer.setViewResizeMode(landscape==VIDEO_VERTICAL); if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); @@ -267,12 +270,16 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void play(String url, int playModel) { srcUrl = url; PLAY_MODEL = playModel; + Log.i(TAG, "play" + " url:" + url + " playModel: " + playModel + " landscape: " + videoLandscape); if (playModel != PLAY_MODEL_DEF) { - if (videoLandscape == VIDEO_VERTICAL) { + mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); + if (landscape == VIDEO_VERTICAL) { url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); - } else if (videoLandscape == VIDEO_HORIZONTAL) { + } else if (landscape == VIDEO_HORIZONTAL) { url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } + } else { + mPlayer.setViewResizeMode(false); } Log.e("purl121", url); @@ -295,12 +302,16 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void switchStream(String url, int playModel) { srcUrl = url; PLAY_MODEL = playModel; + Log.i(TAG, "switchStream: " + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape = " + videoLandscape); if (playModel != PLAY_MODEL_DEF) { - if (videoLandscape == VIDEO_VERTICAL) { + mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); + if (landscape == VIDEO_VERTICAL) { url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); - } else if (videoLandscape == VIDEO_HORIZONTAL) { + } else if (landscape == VIDEO_HORIZONTAL) { url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } + } else { + mPlayer.setViewResizeMode(false); } Log.e("purl121", url); @@ -348,6 +359,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void stopPlay2() { } + @Override public void setViewUP(int i) { if (mVideoView == null) return; @@ -692,7 +704,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { break; } - LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL, ban,true); + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL, ban, true); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index 49f7d01d8..a4dc4c9d2 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -20,7 +20,7 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL public static final int PLAY_MODEL_1080 = 2; public static int PLAY_MODEL = PLAY_MODEL_DEF; - public static final String[] videoRatioHorizontal = new String[]{"_848_480", "_1280_720", "_1920_1080"}; + public static final String[] videoRatioHorizontal = new String[]{"_640_480", "_960_720", "_1440_1080"}; public static final String[] videoRatioVertical = new String[]{"_480_848", "_720_1280", "_1080_1920"}; public static final String[] videoFps = new String[]{"_24", "_30"}; OnMicCallback onMicCallback;//连麦回调 diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 9fcf3ef3d..8c6c80337 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -299,6 +299,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mask.setVisibility(View.VISIBLE); mLivePlayViewHolder.setLiveBean(mLiveBean); mLivePlayViewHolder.setCover(mLiveBean.getAvatar()); + mLivePlayViewHolder.setLiveBeanLandscape(mLiveBean.getLandscape()); mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_720); mLivePlayViewHolder.setOnMicCallback(new LiveRoomPlayViewHolder.OnMicCallback() { @Override @@ -357,7 +358,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe landscape = data.getLiveInfo().getLandscape(); mLivePlayViewHolder.setLiveBeanLandscape(landscape); mLivePlayViewHolder.setLiveEnterRoomNewModel(data); - //mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1) == 2 ? 1 : (data.getClarityType() - 1)); + mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1) == 2 ? 1 : (data.getClarityType() - 1)); //是否热度卡加成 liveHandler.postDelayed(() -> mLiveRoomViewHolder.getIsHot(data.getIsUseHotCard()), 700); diff --git a/live/src/main/res/layout/view_live_play_ksy.xml b/live/src/main/res/layout/view_live_play_ksy.xml index a7b2b1a81..91b5d0346 100644 --- a/live/src/main/res/layout/view_live_play_ksy.xml +++ b/live/src/main/res/layout/view_live_play_ksy.xml @@ -11,7 +11,6 @@ android:id="@+id/video_view" android:layout_width="match_parent" app:surface_type="texture_view" - app:resize_mode="zoom" app:use_controller="false" android:layout_height="match_parent" /> From 9fcc04cef25edc0e88ab6ff72b8d3de4df4d46ce Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Sun, 8 Jan 2023 14:42:01 +0800 Subject: [PATCH 054/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E8=81=8A=E5=A4=A9=E8=AE=B0=E5=BD=95=E9=87=8D=E5=8F=A0?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/adapter/LiveChatAdapter.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java index cce3d4c7d..ac142a8e4 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java @@ -402,7 +402,8 @@ public class LiveChatAdapter extends RecyclerView.Adapter { // Log.i(TAG, "insertItem: " + bean.getContent()+" size = "+(mList.size()+1)); int size = mList.size(); //设置最大展示99条消息 - if (size == 100) { + if (size >= 100 && (isBottom || mRecyclerViewScrolledDy == 0)) { + mList.subList(0, 50).clear(); notifyItemRangeRemoved(0, 50); } @@ -414,7 +415,7 @@ public class LiveChatAdapter extends RecyclerView.Adapter { } // size = mList.size(); if (isBottom || mRecyclerViewScrolledDy == 0) { - scrollToBottom(); + scrollToBottom(); } else { Bus.get().post(new LiveAudienceEvent() .setType(LiveAudienceEvent.LiveAudienceType.NEW_MESSAGE_REMINDER)); From 27bd65d3daaa243f109775ffb38021e05667cb99 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 8 Jan 2023 15:50:40 +0800 Subject: [PATCH 055/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=BF=9B=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E9=97=B4loading=E7=95=8C=E9=9D=A2=E4=B8=8E=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E5=99=A8=E7=BB=91=E5=AE=9A=EF=BC=8C=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E5=87=86=E5=A4=87=E5=AE=8C=E6=88=90=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E9=9A=90=E8=97=8F=E3=80=82=20=E4=BC=98=E5=8C=96=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E5=99=A8=E5=8A=A0=E8=BD=BD=E9=80=9F=E5=BA=A61?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/utils/LiveExoPlayerManager.java | 4 ++-- .../yunbao/live/views/LivePlayRyViewHolder.java | 14 +++++++++++++- .../yunbao/live/views/LiveRoomPlayViewHolder.java | 12 +++++++++++- .../com/yunbao/live/views/PortraitLiveManager.java | 10 ++++++++-- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 4a810273e..76dd81632 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -106,7 +106,7 @@ public class LiveExoPlayerManager { Log.i(TAG, "onPlaybackStateChanged 1: " + playbackState); if (playbackState == Player.STATE_READY) { player2.stop(); - player2.setVideoSurface(null); + player2.clearVideoSurface(); player1.play(); Log.i(TAG, "切换播放器1"); handler.removeCallbacks(buffRunnable); @@ -159,7 +159,7 @@ public class LiveExoPlayerManager { Log.i(TAG, "onPlaybackStateChanged 2: " + playbackState); if (playbackState == Player.STATE_READY) { player1.stop(); - player1.setVideoSurface(null); + player1.clearVideoSurface(); player2.play(); Log.i(TAG, "切换播放器2 " + player2.isPlaying()); handler.removeCallbacks(buffRunnable); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 6ae0bb65a..6d1d43753 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -196,7 +196,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Log.i(TAG, "setLiveBeanLandscape: " + landscape); this.landscape = landscape; this.videoLandscape = landscape; - mPlayer.setViewResizeMode(landscape==VIDEO_VERTICAL); + mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); @@ -1031,6 +1031,11 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { }); } + @Override + public void setLoadViewListener(LoadingListener listener) { + super.setLoadViewListener(listener); + } + private void showLoadingDialog() { if (PLAY_MODEL == PLAY_MODEL_480) return; @@ -1081,6 +1086,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (playbackState == Player.STATE_BUFFERING) { //showLoadingDialog(); OkDownload.getInstance().pauseAll(); + Log.i(TAG, "onPlaybackStateChanged: 缓存中"); + }else{ + Log.i(TAG, "onPlaybackStateChanged: 播放中"); } } @@ -1089,7 +1097,11 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Player.Listener.super.onIsPlayingChanged(isPlaying); if (isPlaying) { hideCover(); + Log.i(TAG, "onIsPlayingChanged: 开始播放"); OkDownload.getInstance().startAll(); + if (loadingListener != null) { + loadingListener.onPlayer(); + } } } } diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index a4dc4c9d2..3a6fa1bc9 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -25,6 +25,7 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL public static final String[] videoFps = new String[]{"_24", "_30"}; OnMicCallback onMicCallback;//连麦回调 public EnterRoomNewModel roomModel; + LoadingListener loadingListener; public LiveRoomPlayViewHolder(Context context, ViewGroup parentView) { super(context, parentView); @@ -62,7 +63,8 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL this.mLiveBean = data; } - public void setViewUP(int i){} + public void setViewUP(int i) { + } public OnMicCallback getOnMicCallback() { return onMicCallback; @@ -76,9 +78,17 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL this.roomModel = data; } + public void setLoadViewListener(LoadingListener listener) { + this.loadingListener = listener; + } + public interface OnMicCallback { void onMikUpdate(); } + + public interface LoadingListener { + void onPlayer(); + } } diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 8c6c80337..a973827e4 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -276,6 +276,12 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRyLinkMicPkPresenter = new LiveRyLinkMicPkPresenter(mContext, mLivePlayViewHolder, false, null); mLivePlayViewHolder.addToParent(); mLivePlayViewHolder.subscribeActivityLifeCycle(); + mLivePlayViewHolder.setLoadViewListener(new LiveRoomPlayViewHolder.LoadingListener() { + @Override + public void onPlayer() { + loading.setVisibility(View.GONE); + } + }); mLiveRoomViewHolder.subscribeActivityLifeCycle(); mLiveAudienceViewHolder.addToParent(); mLiveRoomViewHolder.addToParent(); @@ -358,7 +364,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe landscape = data.getLiveInfo().getLandscape(); mLivePlayViewHolder.setLiveBeanLandscape(landscape); mLivePlayViewHolder.setLiveEnterRoomNewModel(data); - mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1) == 2 ? 1 : (data.getClarityType() - 1)); + //mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1) == 2 ? 1 : (data.getClarityType() - 1)); //是否热度卡加成 liveHandler.postDelayed(() -> mLiveRoomViewHolder.getIsHot(data.getIsUseHotCard()), 700); @@ -580,7 +586,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.showPrizePoolLevel(String.valueOf(giftPrizePoolLevel)); } } - liveHandler.postDelayed(() -> loading.setVisibility(View.GONE), 700); + //liveHandler.postDelayed(() -> loading.setVisibility(View.GONE), 700); } From 182e46799adef8ae86515d258efdbb1e76006682 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 8 Jan 2023 17:17:31 +0800 Subject: [PATCH 056/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8DPK=E6=97=B6=E7=94=BB?= =?UTF-8?q?=E9=9D=A2=E5=BC=82=E5=B8=B8=E9=97=AE=E9=A2=98=EF=BC=88=E5=88=86?= =?UTF-8?q?=E8=BE=A8=E7=8E=87=E6=9C=AA=E5=88=87=E5=88=B04:3=EF=BC=89=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=92=AD=E6=94=BE=E5=99=A8=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E9=80=9F=E5=BA=A62?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/utils/LiveExoPlayerManager.java | 46 ++++++++++++++++--- .../live/views/LivePlayRyViewHolder.java | 17 ++++++- .../live/views/PortraitLiveManager.java | 2 +- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 76dd81632..7a406fcd0 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -6,6 +6,7 @@ import android.os.Looper; import android.util.Log; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Player; @@ -13,6 +14,9 @@ import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.StyledPlayerView; import com.google.android.exoplayer2.video.VideoSize; +import com.yunbao.common.utils.ToastUtil; + +import java.util.Locale; /** * 直播间播放器管理器 @@ -30,13 +34,23 @@ public class LiveExoPlayerManager { private String TAG = "播放器"; private int playBufferIndex = 0;//卡顿计数器 private Handler handler; + private static double log_buffer_time = 0, log_buffer_max_time; public LiveExoPlayerManager(Context mContext) { this.mContext = mContext; - player1 = new ExoPlayer.Builder(mContext).build(); - player2 = new ExoPlayer.Builder(mContext).build(); + DefaultLoadControl control = new DefaultLoadControl.Builder() + .setPrioritizeTimeOverSizeThresholds(true) + .setBackBuffer(15_000, true) + .setBufferDurationsMs(100, + 15_000, + 50, + 100) + .build(); + player1 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); + player2 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); player1.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); player2.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); + handler = new Handler(Looper.getMainLooper()); setListener(); setAnalyticsListener(); @@ -51,8 +65,10 @@ public class LiveExoPlayerManager { this.mainView = mainView; this.mainView.setKeepContentOnPlayerReset(true); } - public void setViewResizeMode(boolean isPhone){ - mainView.setResizeMode(isPhone?AspectRatioFrameLayout.RESIZE_MODE_ZOOM:AspectRatioFrameLayout.RESIZE_MODE_FIT); + + public void setViewResizeMode(boolean isPhone) { + Log.i(TAG, "setViewResizeMode: "+isPhone); + mainView.setResizeMode(isPhone ? AspectRatioFrameLayout.RESIZE_MODE_ZOOM : AspectRatioFrameLayout.RESIZE_MODE_FIT); mainView.requestLayout(); } @@ -126,6 +142,14 @@ public class LiveExoPlayerManager { if (isPlaying) { Log.i(TAG, "onIsPlayingChanged1: 播放了"); //player1.setVideoSurfaceView(mainView); + if (log_buffer_time != -1) { + double tmp = (System.currentTimeMillis() - log_buffer_time) / 1000; + if (tmp > log_buffer_max_time) { + log_buffer_max_time = tmp; + } + ToastUtil.show(String.format(Locale.CHINA, "从加载到播放 = %.3f,最大耗时 = %.3f", tmp, log_buffer_max_time)); + log_buffer_time = -1; + } mainView.setPlayer(player1); status = MODEL_PLAY1; isSwitchUrl = false; @@ -138,7 +162,7 @@ public class LiveExoPlayerManager { @Override public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); - setViewResizeMode(videoSize.height>videoSize.width); + setViewResizeMode(videoSize.height > videoSize.width); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); if (listener != null) { listener.onVideoSizeChanged(videoSize); @@ -180,6 +204,12 @@ public class LiveExoPlayerManager { Log.i(TAG, "onIsPlayingChanged2: 播放了"); //player2.setVideoSurfaceView(mainView); mainView.setPlayer(player2); + double tmp = (System.currentTimeMillis() - log_buffer_time) / 1000; + if (tmp > log_buffer_max_time) { + log_buffer_max_time = tmp; + } + ToastUtil.show(String.format(Locale.CHINA, "从加载到播放 = %.3f,最大耗时 = %.3f", tmp, log_buffer_max_time)); + log_buffer_time = -1; status = MODEL_PLAY2; isSwitchUrl = false; if (listener != null) { @@ -191,7 +221,7 @@ public class LiveExoPlayerManager { @Override public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); - setViewResizeMode(videoSize.height>videoSize.width); + setViewResizeMode(videoSize.height > videoSize.width); if (listener != null) { listener.onVideoSizeChanged(videoSize); } @@ -211,9 +241,10 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void startUrl(String url) { - Log.i(TAG, "startUrl: "+url+" > "+mainView.getResizeMode()); + Log.i(TAG, "startUrl: " + url + " > " + mainView.getResizeMode()); isSwitchUrl = true; playBufferIndex = 0; + log_buffer_time = System.currentTimeMillis(); //getNowPlayer().setVideoSurfaceView(mainView); mainView.setPlayer(getNowPlayer()); getNowPlayer().setMediaItem(createMediaItem(url)); @@ -230,6 +261,7 @@ public class LiveExoPlayerManager { Log.i(TAG, "switchUrl: " + url); playBufferIndex = 0; isSwitchUrl = true; + log_buffer_time = System.currentTimeMillis(); getNextPlayer().setMediaItem(createMediaItem(url)); getNextPlayer().prepare(); } diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 6d1d43753..828767f4d 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -391,6 +391,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } else { height = DpUtil.dp2px(285); } + mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); @@ -441,6 +442,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void setPkview() { Log.i("收到socket--->", "变成16:9"); + String url=srcUrl; + url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + mPlayer.setViewResizeMode(false); + mPlayer.switchUrl(url); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = vHeight; params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); @@ -455,12 +460,22 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); + String url=srcUrl; + url = url.replace(".flv", videoRatioVertical[PLAY_MODEL] + videoFps[0] + ".flv"); + mPlayer.setViewResizeMode(true); + mPlayer.switchUrl(url); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = RelativeLayout.LayoutParams.MATCH_PARENT; params.topMargin = 0; mVideoView.requestLayout(); } else { + String url=srcUrl; + url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + mPlayer.setViewResizeMode(false); + mPlayer.switchUrl(url); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = vHeight; params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); @@ -1087,7 +1102,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { //showLoadingDialog(); OkDownload.getInstance().pauseAll(); Log.i(TAG, "onPlaybackStateChanged: 缓存中"); - }else{ + } else { Log.i(TAG, "onPlaybackStateChanged: 播放中"); } } diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index a973827e4..8530ba7c8 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -586,7 +586,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.showPrizePoolLevel(String.valueOf(giftPrizePoolLevel)); } } - //liveHandler.postDelayed(() -> loading.setVisibility(View.GONE), 700); + liveHandler.postDelayed(() -> loading.setVisibility(View.GONE), 5_000); } From cf858708101bfb4a47396a47617bfd7b2b811cd4 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 8 Jan 2023 18:08:00 +0800 Subject: [PATCH 057/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E9=BB=98=E8=AE=A4=E6=B5=81=E4=B8=8D=E6=8B=BC=E6=8E=A5?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/utils/LiveExoPlayerManager.java | 6 +++--- .../java/com/yunbao/live/views/PortraitLiveManager.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 7a406fcd0..114473fc2 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -39,10 +39,10 @@ public class LiveExoPlayerManager { public LiveExoPlayerManager(Context mContext) { this.mContext = mContext; DefaultLoadControl control = new DefaultLoadControl.Builder() - .setPrioritizeTimeOverSizeThresholds(true) + .setPrioritizeTimeOverSizeThresholds(false) .setBackBuffer(15_000, true) - .setBufferDurationsMs(100, - 15_000, + .setBufferDurationsMs(150, + 5_000, 50, 100) .build(); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 8530ba7c8..a57abcb1d 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -306,7 +306,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLivePlayViewHolder.setLiveBean(mLiveBean); mLivePlayViewHolder.setCover(mLiveBean.getAvatar()); mLivePlayViewHolder.setLiveBeanLandscape(mLiveBean.getLandscape()); - mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_720); + mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_DEF); mLivePlayViewHolder.setOnMicCallback(new LiveRoomPlayViewHolder.OnMicCallback() { @Override public void onMikUpdate() { From b3083cdd1874841ae5af7f5562b477087fa3bf35 Mon Sep 17 00:00:00 2001 From: Yutousama <583819556@qq.com> Date: Sun, 8 Jan 2023 21:49:07 +0800 Subject: [PATCH 058/118] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E9=80=89=E6=8B=A9=E5=88=86=E8=BE=A8=E7=8E=87?= =?UTF-8?q?=E7=9A=84=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/utils/LiveExoPlayerManager.java | 36 +++++++++---------- .../live/views/LivePlayRyViewHolder.java | 36 +++++++++++++------ .../live/views/LiveRoomPlayViewHolder.java | 12 +++++++ .../live/views/PortraitLiveManager.java | 13 +++++-- 4 files changed, 66 insertions(+), 31 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 114473fc2..6601dca54 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -14,9 +14,8 @@ import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.StyledPlayerView; import com.google.android.exoplayer2.video.VideoSize; -import com.yunbao.common.utils.ToastUtil; -import java.util.Locale; +import androidx.annotation.NonNull; /** * 直播间播放器管理器 @@ -25,19 +24,18 @@ import java.util.Locale; public class LiveExoPlayerManager { private final int MODEL_PLAY1 = 0;//当前主播放器 private final int MODEL_PLAY2 = 1;//当前子播放器 - private Context mContext; - private ExoPlayer player1, player2; + private final ExoPlayer player1; + private final ExoPlayer player2; private StyledPlayerView mainView;//渲染视图 private int status = MODEL_PLAY1; private Player.Listener listener; private boolean isSwitchUrl = false;//是否为主动切换播放器 - private String TAG = "播放器"; + private final String TAG = "播放器"; private int playBufferIndex = 0;//卡顿计数器 - private Handler handler; + private final Handler handler; private static double log_buffer_time = 0, log_buffer_max_time; public LiveExoPlayerManager(Context mContext) { - this.mContext = mContext; DefaultLoadControl control = new DefaultLoadControl.Builder() .setPrioritizeTimeOverSizeThresholds(false) .setBackBuffer(15_000, true) @@ -46,8 +44,8 @@ public class LiveExoPlayerManager { 50, 100) .build(); - player1 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); - player2 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); + player1 = new ExoPlayer.Builder(mContext).build(); + player2 = new ExoPlayer.Builder(mContext).build(); player1.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); player2.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); @@ -76,13 +74,13 @@ public class LiveExoPlayerManager { player1.addAnalyticsListener(new AnalyticsListener() { @Override public void onPlaybackStateChanged( - EventTime eventTime, int state) { + @NonNull EventTime eventTime, int state) { Log.d(TAG, "onPlaybackStateChanged(1) called with: eventTime = [" + eventTime + "], state = [" + state + "]"); } @Override public void onDroppedVideoFrames( - EventTime eventTime, int droppedFrames, long elapsedMs) { + @NonNull EventTime eventTime, int droppedFrames, long elapsedMs) { Log.d(TAG, "onDroppedVideoFrames(1) called with: eventTime = [" + eventTime + "], droppedFrames = [" + droppedFrames + "], elapsedMs = [" + elapsedMs + "]"); } }); @@ -90,13 +88,13 @@ public class LiveExoPlayerManager { player2.addAnalyticsListener(new AnalyticsListener() { @Override public void onPlaybackStateChanged( - EventTime eventTime, int state) { + @NonNull EventTime eventTime, int state) { Log.d(TAG, "onPlaybackStateChanged(2) called with: eventTime = [" + eventTime.totalBufferedDurationMs + "], state = [" + state + "]"); } @Override public void onDroppedVideoFrames( - EventTime eventTime, int droppedFrames, long elapsedMs) { + @NonNull EventTime eventTime, int droppedFrames, long elapsedMs) { Log.d(TAG, "onDroppedVideoFrames(2) called with: eventTime = [" + eventTime + "], droppedFrames = [" + droppedFrames + "], elapsedMs = [" + elapsedMs + "]"); } }); @@ -106,7 +104,7 @@ public class LiveExoPlayerManager { /** * 延迟1秒还未恢复播放则认为卡顿了,可以切分辨率了 */ - private Runnable buffRunnable = new Runnable() { + private final Runnable buffRunnable = new Runnable() { @Override public void run() { playBufferIndex = 0; @@ -147,7 +145,7 @@ public class LiveExoPlayerManager { if (tmp > log_buffer_max_time) { log_buffer_max_time = tmp; } - ToastUtil.show(String.format(Locale.CHINA, "从加载到播放 = %.3f,最大耗时 = %.3f", tmp, log_buffer_max_time)); + //ToastUtil.show(String.format(Locale.CHINA, "从加载到播放 = %.3f,最大耗时 = %.3f", tmp, log_buffer_max_time)); log_buffer_time = -1; } mainView.setPlayer(player1); @@ -160,7 +158,7 @@ public class LiveExoPlayerManager { } @Override - public void onVideoSizeChanged(VideoSize videoSize) { + public void onVideoSizeChanged(@NonNull VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); setViewResizeMode(videoSize.height > videoSize.width); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); @@ -208,7 +206,7 @@ public class LiveExoPlayerManager { if (tmp > log_buffer_max_time) { log_buffer_max_time = tmp; } - ToastUtil.show(String.format(Locale.CHINA, "从加载到播放 = %.3f,最大耗时 = %.3f", tmp, log_buffer_max_time)); + //ToastUtil.show(String.format(Locale.CHINA, "从加载到播放 = %.3f,最大耗时 = %.3f", tmp, log_buffer_max_time)); log_buffer_time = -1; status = MODEL_PLAY2; isSwitchUrl = false; @@ -219,7 +217,7 @@ public class LiveExoPlayerManager { } @Override - public void onVideoSizeChanged(VideoSize videoSize) { + public void onVideoSizeChanged(@NonNull VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); setViewResizeMode(videoSize.height > videoSize.width); if (listener != null) { @@ -246,7 +244,9 @@ public class LiveExoPlayerManager { playBufferIndex = 0; log_buffer_time = System.currentTimeMillis(); //getNowPlayer().setVideoSurfaceView(mainView); + mainView.setKeepContentOnPlayerReset(false); mainView.setPlayer(getNowPlayer()); + mainView.setKeepContentOnPlayerReset(true); getNowPlayer().setMediaItem(createMediaItem(url)); getNowPlayer().prepare(); getNowPlayer().play(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 828767f4d..aac9da7cd 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -32,6 +32,7 @@ import com.lzf.easyfloat.EasyFloat; import com.lzy.okserver.OkDownload; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; +import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.DpUtil; @@ -442,8 +443,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void setPkview() { Log.i("收到socket--->", "变成16:9"); - String url=srcUrl; - url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + String url = srcUrl; + if(PLAY_MODEL!=-1) { + url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + } mPlayer.setViewResizeMode(false); mPlayer.switchUrl(url); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); @@ -460,8 +463,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); - String url=srcUrl; - url = url.replace(".flv", videoRatioVertical[PLAY_MODEL] + videoFps[0] + ".flv"); + String url = srcUrl; + if (PLAY_MODEL != -1) { + url = url.replace(".flv", videoRatioVertical[PLAY_MODEL] + videoFps[0] + ".flv"); + } mPlayer.setViewResizeMode(true); mPlayer.switchUrl(url); @@ -471,8 +476,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { mVideoView.requestLayout(); } else { - String url=srcUrl; - url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + String url = srcUrl; + if(PLAY_MODEL!=-1) { + url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + } mPlayer.setViewResizeMode(false); mPlayer.switchUrl(url); @@ -719,7 +726,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { break; } - LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, PLAY_MODEL, ban, true); + LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, + IMLoginManager.get(mContext).getInt(PLAY_MODEL_KEY, PLAY_MODEL), + ban, + true); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override @@ -740,8 +750,14 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void onDismiss(BasePopupView popupView) { int selectClarity = liveClarityCustomPopup.getSelectClarity(); - if (selectClarity == PLAY_MODEL || PLAY_MODEL == PLAY_MODEL_DEF) return; - switchStream(srcUrl, selectClarity); + if (selectClarity == PLAY_MODEL) return; + if (selectClarity == PLAY_MODEL_ANCHOR) { + switchStream(srcUrl, PLAY_MODEL_DEF); + setAudiencePlayModel(selectClarity); + } else { + switchStream(srcUrl, selectClarity); + } + IMLoginManager.get(mContext).put(LiveRoomPlayViewHolder.PLAY_MODEL_KEY, selectClarity); showToast(); } @@ -1087,7 +1103,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); - // ToastUtil.show("分辨率: width = " + videoSize.width + " height = " + videoSize.height); + ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index 3a6fa1bc9..6aab89439 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -5,6 +5,7 @@ import android.view.ViewGroup; import com.yunbao.common.bean.EnterRoomNewModel; import com.yunbao.common.bean.LiveBean; +import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.views.AbsViewHolder; import com.yunbao.live.interfaces.ILiveLinkMicViewHolder; @@ -14,10 +15,12 @@ import com.yunbao.live.interfaces.ILiveLinkMicViewHolder; public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements ILiveLinkMicViewHolder { protected LiveBean mLiveBean; + public static final String PLAY_MODEL_KEY = "user_audience_play_model"; public static final int PLAY_MODEL_DEF = -1; public static final int PLAY_MODEL_480 = 0; public static final int PLAY_MODEL_720 = 1; public static final int PLAY_MODEL_1080 = 2; + public static int PLAY_MODEL_ANCHOR = -1;//主播设置的最高画质 public static int PLAY_MODEL = PLAY_MODEL_DEF; public static final String[] videoRatioHorizontal = new String[]{"_640_480", "_960_720", "_1440_1080"}; @@ -31,6 +34,15 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL super(context, parentView); } + public void setAnchorPlayModel(int model) { + PLAY_MODEL_ANCHOR = model; + } + + public void setAudiencePlayModel(int model) { + PLAY_MODEL = model; + } + + public abstract void play(String url, int playModel); public abstract void switchStream(String url, int playModel); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index a57abcb1d..205c5ba47 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -306,7 +306,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLivePlayViewHolder.setLiveBean(mLiveBean); mLivePlayViewHolder.setCover(mLiveBean.getAvatar()); mLivePlayViewHolder.setLiveBeanLandscape(mLiveBean.getLandscape()); - mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_DEF); + //mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_DEF); mLivePlayViewHolder.setOnMicCallback(new LiveRoomPlayViewHolder.OnMicCallback() { @Override public void onMikUpdate() { @@ -364,7 +364,14 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe landscape = data.getLiveInfo().getLandscape(); mLivePlayViewHolder.setLiveBeanLandscape(landscape); mLivePlayViewHolder.setLiveEnterRoomNewModel(data); - //mLivePlayViewHolder.switchStream(mLiveBean.getPull(), (data.getClarityType() - 1) == 2 ? 1 : (data.getClarityType() - 1)); + int userClarityType = IMLoginManager.get(mContext).getInt(LiveRoomPlayViewHolder.PLAY_MODEL_KEY, -1); + int anchorClarityType = data.getClarityType() - 1; + if (userClarityType != anchorClarityType) { + mLivePlayViewHolder.play(mLiveBean.getPull(), userClarityType); + } else { + mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_DEF); + } + mLivePlayViewHolder.setAnchorPlayModel(anchorClarityType); //是否热度卡加成 liveHandler.postDelayed(() -> mLiveRoomViewHolder.getIsHot(data.getIsUseHotCard()), 700); @@ -586,7 +593,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.showPrizePoolLevel(String.valueOf(giftPrizePoolLevel)); } } - liveHandler.postDelayed(() -> loading.setVisibility(View.GONE), 5_000); + liveHandler.postDelayed(() -> loading.setVisibility(View.GONE), 10_000); } From 13146595bfef891ecbde2ed368c07bf886b9fd2d Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Mon, 9 Jan 2023 10:23:21 +0800 Subject: [PATCH 059/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E8=81=8A=E5=A4=A9=E5=88=A0=E9=99=A4=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 +- .../yunbao/live/adapter/LiveChatAdapter.java | 3 + .../yunbao/live/views/LiveRoomViewHolder.java | 86 +++++++++---------- 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/config.gradle b/config.gradle index b123cc49e..7bd22a5fb 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", // -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java index ac142a8e4..ea7b6c472 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java @@ -463,9 +463,12 @@ public class LiveChatAdapter extends RecyclerView.Adapter { if (bean == null) { return; } + + mList.remove(bean.getHeart()); notifyItemRemoved(bean.getHeart()); notifyItemRangeChanged(bean.getHeart(), getItemCount()); + } public void scrollToBottom() { diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 720e608c2..cf87b203e 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -884,49 +884,49 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mChatRecyclerView.setLayoutManager(layoutManager); mChatRecyclerView.addItemDecoration(new TopGradual()); mChatRecyclerView.setItemViewCacheSize(10); - mChatRecyclerView.setItemAnimator(new SimpleItemAnimator() { - @Override - public boolean animateRemove(RecyclerView.ViewHolder holder) { - return false; - } - - @Override - public boolean animateAdd(RecyclerView.ViewHolder holder) { - Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.live_chat_msg_in); - holder.itemView.startAnimation(animation); - return false; - } - - @Override - public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { - return false; - } - - @Override - public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) { - return false; - } - - @Override - public void runPendingAnimations() { - - } - - @Override - public void endAnimation(@NonNull RecyclerView.ViewHolder item) { - - } - - @Override - public void endAnimations() { - - } - - @Override - public boolean isRunning() { - return false; - } - }); +// mChatRecyclerView.setItemAnimator(new SimpleItemAnimator() { +// @Override +// public boolean animateRemove(RecyclerView.ViewHolder holder) { +// return false; +// } +// +// @Override +// public boolean animateAdd(RecyclerView.ViewHolder holder) { +// Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.live_chat_msg_in); +// holder.itemView.startAnimation(animation); +// return false; +// } +// +// @Override +// public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { +// return false; +// } +// +// @Override +// public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) { +// return false; +// } +// +// @Override +// public void runPendingAnimations() { +// +// } +// +// @Override +// public void endAnimation(@NonNull RecyclerView.ViewHolder item) { +// +// } +// +// @Override +// public void endAnimations() { +// +// } +// +// @Override +// public boolean isRunning() { +// return false; +// } +// }); mLiveChatAdapter = new LiveChatAdapter(mContext); mChatRecyclerView.setAdapter(mLiveChatAdapter); mLiveChatAdapter.setOnItemClickListener(new OnItemClickListener() { From eaae58db31b34f540d9d4b5782ae311022242046 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Mon, 9 Jan 2023 10:56:49 +0800 Subject: [PATCH 060/118] =?UTF-8?q?pk=E5=80=92=E8=AE=A1=E6=97=B6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presenter/LiveRyLinkMicPkPresenter.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index e421e7f35..84452cf21 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -39,7 +39,6 @@ import com.tencent.trtc.TRTCCloud; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.bean.UserBean; import com.yunbao.common.event.AnchorInfoEvent; -import com.yunbao.common.event.FollowEvent; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.http.live.LiveNetManager; @@ -306,6 +305,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { int i = 0; private void nextPkTimeCountDown() { + Log.i("vvvs", "mHandler:" + (mHandler != null) ); if (mHandler != null) { mHandler.sendEmptyMessageAtTime(WHAT_PK_TIME, getNextSecondTime()); } @@ -384,11 +384,13 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * pk时间倒计时 */ private void changePkTime() { + if (mPkTimeCount<0)return; mPkTimeCount--; + Log.i("vvvs", "mPkTimeCount:" + mPkTimeCount); if (mPkTimeCount >= 0) {// nextPkTimeCountDown(); if (mContext instanceof LiveAudienceActivity) { - ((LiveAudienceActivity)mContext).setPkStatus(true); + ((LiveAudienceActivity) mContext).setPkStatus(true); } } else { if (mIsPkEnd) { @@ -397,7 +399,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { ((LiveRyAnchorActivity) mContext).setPkBtnVisible(true); } if (mContext instanceof LiveAudienceActivity) { - ((LiveAudienceActivity)mContext).setPkStatus(false); + ((LiveAudienceActivity) mContext).setPkStatus(false); } //如果PK结束Im没有发送关闭PK的消息,倒计时结束自动关闭 // if (mLiveLinkMicPkViewHolder != null) { @@ -616,7 +618,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * 主播与主播PK PK主播发过来的已经接受 */ public void onLinkMicToPk(UserBean u) { - EventBus.getDefault().post(new AnchorInfoEvent(false,u.getId(), u.getUserNiceName(),u.getAvatar())); + EventBus.getDefault().post(new AnchorInfoEvent(false, u.getId(), u.getUserNiceName(), u.getAvatar())); Log.e("eve", u.getId() + ""); /** * 加入副房间 @@ -718,7 +720,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { } }); LivePushRyViewHolder.btn_close.setVisibility(View.VISIBLE); - LiveRyAnchorActivity.isDRPK=1; + LiveRyAnchorActivity.isDRPK = 1; ScreenDimenUtil util = ScreenDimenUtil.getInstance(); int mScreenWdith = util.getScreenWdith(); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, mScreenWdith * 720 / 960); @@ -772,14 +774,14 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { LivePushRyViewHolder.mPreView1.setLayoutParams(params); LivePushRyViewHolder.mPreView1.setVisibility(View.VISIBLE); LivePushRyViewHolder.btn_close.setVisibility(View.VISIBLE); - LiveRyAnchorActivity.isDRPK=1; + LiveRyAnchorActivity.isDRPK = 1; JSONObject msg1 = new JSONObject(); msg1.put("uid", CommonAppConfig.getInstance().getUid()); msg1.put("pkuid", CommonAppConfig.getInstance().getUid()); msg1.put("pkhead", CommonAppConfig.getInstance().getUserBean().getAvatarThumb()); msg1.put("pkname", CommonAppConfig.getInstance().getUserBean().getUserNiceName()); - EventBus.getDefault().post(new AnchorInfoEvent(false,bean.getId(), bean.getUserNiceName(),bean.getAvatar())); + EventBus.getDefault().post(new AnchorInfoEvent(false, bean.getId(), bean.getUserNiceName(), bean.getAvatar())); if (bean != null && bean.isRandomPk()) { msg1.put("random_pk", bean.isRandomPk() ? 1 : 0); @@ -1069,7 +1071,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { */ public static void leaveDRRoom() { //清理PK上面对方的头像 - EventBus.getDefault().post(new AnchorInfoEvent(true,"", "","")); + EventBus.getDefault().post(new AnchorInfoEvent(true, "", "", "")); Log.e("ry", "退出多人OKKK" + inputStreamList.size()); isDRPK = 0; @@ -2161,7 +2163,6 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { if (mHandler != null) { mHandler.removeCallbacksAndMessages(null); } - mHandler = null; mSocketRyClient = null; if (mLiveLinkMicPkViewHolder != null) { mLiveLinkMicPkViewHolder.release(); From bacf4fd32ff99a172967569151a4ae594ada9b3b Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Mon, 9 Jan 2023 13:26:32 +0800 Subject: [PATCH 061/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E5=99=A83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/common/utils/DialogUitl.java | 1 + .../live/utils/LiveExoPlayerManager.java | 11 +++++++--- .../live/views/LivePlayRyViewHolder.java | 20 +++++++++++++------ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/utils/DialogUitl.java b/common/src/main/java/com/yunbao/common/utils/DialogUitl.java index d75105daf..1ad1b3e7e 100644 --- a/common/src/main/java/com/yunbao/common/utils/DialogUitl.java +++ b/common/src/main/java/com/yunbao/common/utils/DialogUitl.java @@ -78,6 +78,7 @@ public class DialogUitl { if (!TextUtils.isEmpty(content)) { TextView titleView = (TextView) dialog.findViewById(R.id.text); if (titleView != null) { + titleView.setGravity(Gravity.CENTER); titleView.setText(content); } } diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 6601dca54..2e5c0788f 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -5,6 +5,8 @@ import android.os.Handler; import android.os.Looper; import android.util.Log; +import androidx.annotation.NonNull; + import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.ExoPlayer; @@ -15,8 +17,6 @@ import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.StyledPlayerView; import com.google.android.exoplayer2.video.VideoSize; -import androidx.annotation.NonNull; - /** * 直播间播放器管理器 * 通过预加载子播放器来实现无缝切换分辨率功能 @@ -65,7 +65,7 @@ public class LiveExoPlayerManager { } public void setViewResizeMode(boolean isPhone) { - Log.i(TAG, "setViewResizeMode: "+isPhone); + Log.i(TAG, "setViewResizeMode: " + isPhone); mainView.setResizeMode(isPhone ? AspectRatioFrameLayout.RESIZE_MODE_ZOOM : AspectRatioFrameLayout.RESIZE_MODE_FIT); mainView.requestLayout(); } @@ -262,6 +262,7 @@ public class LiveExoPlayerManager { playBufferIndex = 0; isSwitchUrl = true; log_buffer_time = System.currentTimeMillis(); + mainView.setKeepContentOnPlayerReset(true); getNextPlayer().setMediaItem(createMediaItem(url)); getNextPlayer().prepare(); } @@ -305,6 +306,10 @@ public class LiveExoPlayerManager { getNowPlayer().play(); } + public void clearFrame() { + //mainView.setKeepContentOnPlayerReset(false); + } + /** * 释放播放器 */ diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index aac9da7cd..8b4555631 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -30,6 +30,7 @@ import com.lxj.xpopup.core.BasePopupView; import com.lxj.xpopup.interfaces.XPopupCallback; import com.lzf.easyfloat.EasyFloat; import com.lzy.okserver.OkDownload; +import com.yunbao.common.bean.EnterRoomNewModel; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.manager.IMLoginManager; @@ -239,6 +240,12 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } } + @Override + public void setLiveEnterRoomNewModel(EnterRoomNewModel data) { + super.setLiveEnterRoomNewModel(data); + mPlayer.clearFrame(); + } + /** * 暂停播放 */ @@ -390,7 +397,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (videoLandscape == VIDEO_VERTICAL) { height = ViewGroup.LayoutParams.MATCH_PARENT; } else { - height = DpUtil.dp2px(285); + height = ViewGroup.LayoutParams.WRAP_CONTENT; } mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == 2) { @@ -444,7 +451,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void setPkview() { Log.i("收到socket--->", "变成16:9"); String url = srcUrl; - if(PLAY_MODEL!=-1) { + if (PLAY_MODEL != -1) { url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); } mPlayer.setViewResizeMode(false); @@ -477,7 +484,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } else { String url = srcUrl; - if(PLAY_MODEL!=-1) { + if (PLAY_MODEL != -1) { url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); } mPlayer.setViewResizeMode(false); @@ -727,7 +734,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, - IMLoginManager.get(mContext).getInt(PLAY_MODEL_KEY, PLAY_MODEL), + IMLoginManager.get(mContext).getInt(PLAY_MODEL_KEY, PLAY_MODEL_ANCHOR), ban, true); new XPopup.Builder(mContext) @@ -750,7 +757,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void onDismiss(BasePopupView popupView) { int selectClarity = liveClarityCustomPopup.getSelectClarity(); - if (selectClarity == PLAY_MODEL) return; + if (selectClarity == PLAY_MODEL || selectClarity == IMLoginManager.get(mContext).getInt(LiveRoomPlayViewHolder.PLAY_MODEL_KEY, PLAY_MODEL_ANCHOR)) + return; if (selectClarity == PLAY_MODEL_ANCHOR) { switchStream(srcUrl, PLAY_MODEL_DEF); setAudiencePlayModel(selectClarity); @@ -762,7 +770,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } private void showToast() { - DialogUitl.showToast(mContext, " 設置成功\n" + + DialogUitl.showToast(mContext, "設置成功\n" + "正在為你轉換中", 3000); } From ee084d6f33bf1b4cb07daf573c01818be6daf545 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Mon, 9 Jan 2023 13:41:51 +0800 Subject: [PATCH 062/118] =?UTF-8?q?pk=E5=80=92=E8=AE=A1=E6=97=B6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 ++-- .../main/java/com/yunbao/live/views/LiveRoomViewHolder.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.gradle b/config.gradle index 7bd22a5fb..b123cc49e 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 -// serverHost : "https://napi.yaoulive.com", + serverHost : "https://napi.yaoulive.com", // - serverHost : "https://ceshi.yaoulive.com", +// serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index cf87b203e..574dbf439 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -877,7 +877,7 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mChatRecyclerView.setLayoutParams(params1); mChatRecyclerView.setHasFixedSize(true); - LinearLayoutManager layoutManager = new LiveChatRecyclerViewLayoutManager(mContext); + LinearLayoutManager layoutManager = new LinearLayoutManager(mContext); layoutManager.setOrientation(RecyclerView.VERTICAL); // layoutManager.setReverseLayout(true); layoutManager.setStackFromEnd(true); From 70126171c69ea90e13d668964ef4352e37910031 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Mon, 9 Jan 2023 13:52:34 +0800 Subject: [PATCH 063/118] =?UTF-8?q?=E6=96=99=E4=BD=93=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=A8=E7=94=BB=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 ++-- .../main/java/com/yunbao/live/adapter/LiveChatAdapter.java | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/config.gradle b/config.gradle index b123cc49e..7bd22a5fb 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", // -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java index ea7b6c472..12eee954f 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java @@ -16,6 +16,8 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -391,6 +393,8 @@ public class LiveChatAdapter extends RecyclerView.Adapter { new LiveTextRender().render(mContext, mTextView, bean); } + Animation animation = AnimationUtils.loadAnimation(itemView.getContext(),R.anim.live_chat_msg_in); + itemView.startAnimation(animation); } } From 1904eeb3bab560d1d6c0d37ac85ebd6f84ef9118 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Mon, 9 Jan 2023 13:54:05 +0800 Subject: [PATCH 064/118] =?UTF-8?q?=E7=A7=BB=E9=99=A4Toast=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E5=88=86=E8=BE=A8=E7=8E=87=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/views/LivePlayRyViewHolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 8b4555631..ddb682e61 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -1111,7 +1111,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); - ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); + // ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { From 8730a6396ff4aa8a2261d086573333d52b41e7aa Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Mon, 9 Jan 2023 14:38:32 +0800 Subject: [PATCH 065/118] =?UTF-8?q?=E6=96=99=E4=BD=93=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=A8=E7=94=BB=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 ++-- .../com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java | 5 +++-- .../main/java/com/yunbao/live/views/PortraitLiveManager.java | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/config.gradle b/config.gradle index 7bd22a5fb..b123cc49e 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 -// serverHost : "https://napi.yaoulive.com", + serverHost : "https://napi.yaoulive.com", // - serverHost : "https://ceshi.yaoulive.com", +// serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index 84452cf21..7bffad25e 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -305,7 +305,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { int i = 0; private void nextPkTimeCountDown() { - Log.i("vvvs", "mHandler:" + (mHandler != null) ); + Log.i("vvvs", "mHandler:" + (mHandler != null)); if (mHandler != null) { mHandler.sendEmptyMessageAtTime(WHAT_PK_TIME, getNextSecondTime()); } @@ -384,7 +384,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * pk时间倒计时 */ private void changePkTime() { - if (mPkTimeCount<0)return; + if (mPkTimeCount < 0) return; mPkTimeCount--; Log.i("vvvs", "mPkTimeCount:" + mPkTimeCount); if (mPkTimeCount >= 0) {// @@ -2164,6 +2164,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { mHandler.removeCallbacksAndMessages(null); } mSocketRyClient = null; + mHandler = null; if (mLiveLinkMicPkViewHolder != null) { mLiveLinkMicPkViewHolder.release(); } diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 205c5ba47..395524312 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -291,6 +291,9 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveLinkMicPresenter.setLiveSdk(mLiveSDK); mLiveLinkMicAnchorPresenter.setLiveSdk(mLiveSDK); } + if (mLiveRyLinkMicPkPresenter==null){ + mLiveRyLinkMicPkPresenter = new LiveRyLinkMicPkPresenter(mContext, mLivePlayViewHolder, false, null); + } //去除主播离开画面 if (LivePlayKsyViewHolder.leave != null) { LivePlayKsyViewHolder.leave.setVisibility(View.GONE); @@ -681,6 +684,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe if (mLiveRyLinkMicPkPresenter != null) { mLiveRyLinkMicPkPresenter.clearData(); mLiveRyLinkMicPkPresenter.release(); + mLiveRyLinkMicPkPresenter = null; } if (isQuit) { isQuitF = true; From 207811c41d00437ea64859556bc648bd58cbde70 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Mon, 9 Jan 2023 14:47:23 +0800 Subject: [PATCH 066/118] =?UTF-8?q?=E4=BF=AE=E5=BE=A9=E5=9C=A8=E6=89=8B?= =?UTF-8?q?=E6=9C=BA=E7=9B=B4=E6=92=AD=E7=9A=84=E7=9B=B4=E6=92=AD=E9=97=B4?= =?UTF-8?q?PK=E6=97=B6=E5=88=87=E6=8D=A2=E5=88=86=E8=BE=A8=E7=8E=87?= =?UTF-8?q?=E4=BC=9A=E6=8B=89=E5=8D=87=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/activity/LiveAudienceActivity.java | 4 ++++ .../live/views/LivePlayRyViewHolder.java | 22 ++++++++++++++----- .../live/views/LiveRoomPlayViewHolder.java | 3 +++ .../live/views/PortraitLiveManager.java | 6 ++++- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index 037ff8093..a769238ee 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -684,6 +684,10 @@ public class LiveAudienceActivity extends LiveActivity { } } + public boolean isPkStatus() { + return isPk; + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onLiveRoomChangeEvent(LiveRoomChangeEvent e) { if (verticalViewPager.ismEnableScroll()) { diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index ddb682e61..204664df1 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -278,15 +278,15 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void play(String url, int playModel) { srcUrl = url; PLAY_MODEL = playModel; - Log.i(TAG, "play" + " url:" + url + " playModel: " + playModel + " landscape: " + videoLandscape); - if (playModel != PLAY_MODEL_DEF) { + Log.i(TAG, "play" + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape" + videoLandscape); + if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == VIDEO_VERTICAL) { url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); } else if (landscape == VIDEO_HORIZONTAL) { url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } - } else { + } else if(!url.contains(videoFps[0] + ".flv")){ mPlayer.setViewResizeMode(false); } Log.e("purl121", url); @@ -311,14 +311,14 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { srcUrl = url; PLAY_MODEL = playModel; Log.i(TAG, "switchStream: " + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape = " + videoLandscape); - if (playModel != PLAY_MODEL_DEF) { + if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == VIDEO_VERTICAL) { url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); } else if (landscape == VIDEO_HORIZONTAL) { url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } - } else { + } else if(!url.contains(videoFps[0] + ".flv")){ mPlayer.setViewResizeMode(false); } Log.e("purl121", url); @@ -335,6 +335,16 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { purl = url; } + @Override + public void switchStreamPk(boolean isPk) { + super.switchStreamPk(isPk); + if (isPk && !srcUrl.contains(videoFps[0] + ".flv")) { + mPlayer.setViewResizeMode(false); + String url = srcUrl.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + switchStream(url,PLAY_MODEL); + } + } + @Override public void release() { mEnd = true; @@ -1111,7 +1121,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); - // ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); + // ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index 6aab89439..a663763dd 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -94,6 +94,9 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL this.loadingListener = listener; } + public void switchStreamPk(boolean isPk) { + } + public interface OnMicCallback { void onMikUpdate(); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 395524312..aed314f70 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -1302,8 +1302,12 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe * @param isPk */ public void setPkStatus(boolean isPk) { - if (mLiveRoomViewHolder != null) + if (mLiveRoomViewHolder != null) { mLiveRoomViewHolder.hotAddVisibility(isPk); + } + if(mLivePlayViewHolder!=null){ + mLivePlayViewHolder.switchStreamPk(isPk); + } } @Override From 93e2a8af02248cc7beb65fed106a473a5a7e7c2a Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Mon, 9 Jan 2023 15:26:43 +0800 Subject: [PATCH 067/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E6=8B=89=E5=8D=87=E9=97=AE=E9=A2=984?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/views/LivePlayRyViewHolder.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 204664df1..3e00730ff 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -111,6 +111,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { static int vHeight;//视频高 private TextView debugView; private LiveExoPlayerManager mPlayer; + private boolean isPk = false; //0未申请1申请中2连麦中 RCRTCRoom rcrtcRoom; @@ -286,7 +287,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } else if (landscape == VIDEO_HORIZONTAL) { url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } - } else if(!url.contains(videoFps[0] + ".flv")){ + } else if (!url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(false); } Log.e("purl121", url); @@ -318,7 +319,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } else if (landscape == VIDEO_HORIZONTAL) { url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } - } else if(!url.contains(videoFps[0] + ".flv")){ + } else if (!url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(false); } Log.e("purl121", url); @@ -335,13 +336,23 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { purl = url; } + boolean tmpPk = false; + @Override public void switchStreamPk(boolean isPk) { super.switchStreamPk(isPk); - if (isPk && !srcUrl.contains(videoFps[0] + ".flv")) { + if (isPk && !srcUrl.contains(videoFps[0] + ".flv") && !tmpPk) { + tmpPk = true; mPlayer.setViewResizeMode(false); - String url = srcUrl.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); - switchStream(url,PLAY_MODEL); + String url; + if (PLAY_MODEL != -1) { + url = srcUrl.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + } else { + url = srcUrl.replace(".flv", videoRatioHorizontal[1] + videoFps[0] + ".flv"); + } + mPlayer.switchUrl(url); + } else if (!isPk) { + tmpPk = false; } } @@ -464,6 +475,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (PLAY_MODEL != -1) { url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); } + isPk = true; mPlayer.setViewResizeMode(false); mPlayer.switchUrl(url); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); @@ -477,7 +489,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public synchronized void setPkEndview() { Log.i("收收收", landscape + ""); - + isPk = false; + tmpPk = false; if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); String url = srcUrl; From cc4cc2f746ffcdcf6637967f165459f00bc7670b Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Mon, 9 Jan 2023 16:20:54 +0800 Subject: [PATCH 068/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E6=8B=89=E5=8D=87=E9=97=AE=E9=A2=985?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/live/utils/LiveExoPlayerManager.java | 10 ++++++++++ .../com/yunbao/live/views/LivePlayRyViewHolder.java | 11 ++++++++--- .../com/yunbao/live/views/PortraitLiveManager.java | 4 +--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 2e5c0788f..0b557d7c9 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -34,6 +34,7 @@ public class LiveExoPlayerManager { private int playBufferIndex = 0;//卡顿计数器 private final Handler handler; private static double log_buffer_time = 0, log_buffer_max_time; + private String url; public LiveExoPlayerManager(Context mContext) { DefaultLoadControl control = new DefaultLoadControl.Builder() @@ -240,6 +241,7 @@ public class LiveExoPlayerManager { */ public void startUrl(String url) { Log.i(TAG, "startUrl: " + url + " > " + mainView.getResizeMode()); + this.url = url; isSwitchUrl = true; playBufferIndex = 0; log_buffer_time = System.currentTimeMillis(); @@ -259,6 +261,7 @@ public class LiveExoPlayerManager { */ public void switchUrl(String url) { Log.i(TAG, "switchUrl: " + url); + this.url = url; playBufferIndex = 0; isSwitchUrl = true; log_buffer_time = System.currentTimeMillis(); @@ -317,4 +320,11 @@ public class LiveExoPlayerManager { player1.release(); player2.release(); } + + public String getUrl() { + if(url==null){ + url=""; + } + return url; + } } diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 3e00730ff..3e5d2353f 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -314,9 +314,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Log.i(TAG, "switchStream: " + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape = " + videoLandscape); if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); - if (landscape == VIDEO_VERTICAL) { + if (landscape == VIDEO_VERTICAL && !isPk) { url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); - } else if (landscape == VIDEO_HORIZONTAL) { + } else if (landscape == VIDEO_HORIZONTAL || isPk) { url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } } else if (!url.contains(videoFps[0] + ".flv")) { @@ -341,7 +341,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void switchStreamPk(boolean isPk) { super.switchStreamPk(isPk); - if (isPk && !srcUrl.contains(videoFps[0] + ".flv") && !tmpPk) { + if (isPk && !tmpPk) { tmpPk = true; mPlayer.setViewResizeMode(false); String url; @@ -404,6 +404,11 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { params1.topMargin = contexts.getResources().getDimensionPixelOffset(R.dimen.live_top); params1.addRule(RelativeLayout.ALIGN_TOP); ry_view.requestLayout(); + isPk=true; + if (mPlayer.getUrl().contains("848_24.flv") || mPlayer.getUrl().contains("1280_24.flv")) { + tmpPk = false; + switchStreamPk(true); + } } /** diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index aed314f70..5cc3a058d 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -1305,9 +1305,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe if (mLiveRoomViewHolder != null) { mLiveRoomViewHolder.hotAddVisibility(isPk); } - if(mLivePlayViewHolder!=null){ - mLivePlayViewHolder.switchStreamPk(isPk); - } + } @Override From 7070f5c1b49e2eca747d855c50fd00b9017ff6c1 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Mon, 9 Jan 2023 18:30:53 +0800 Subject: [PATCH 069/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E6=8B=89=E5=8D=87=E9=97=AE=E9=A2=985?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 +-- .../live/utils/LiveExoPlayerManager.java | 4 +-- .../live/views/LivePlayRyViewHolder.java | 33 +++++++++++-------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/config.gradle b/config.gradle index b123cc49e..7bd22a5fb 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", // -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 0b557d7c9..2372f156a 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -45,8 +45,8 @@ public class LiveExoPlayerManager { 50, 100) .build(); - player1 = new ExoPlayer.Builder(mContext).build(); - player2 = new ExoPlayer.Builder(mContext).build(); + player1 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); + player2 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); player1.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); player2.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 3e5d2353f..cce26f97f 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -337,6 +337,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } boolean tmpPk = false; + String waitNextUrl = null; @Override public void switchStreamPk(boolean isPk) { @@ -350,9 +351,18 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } else { url = srcUrl.replace(".flv", videoRatioHorizontal[1] + videoFps[0] + ".flv"); } - mPlayer.switchUrl(url); + waitNextUrl = url; + mPlayer.switchUrl(srcUrl); } else if (!isPk) { tmpPk = false; + if (landscape == VIDEO_VERTICAL && PLAY_MODEL != -1) { + waitNextUrl = srcUrl.replace(".flv", videoRatioVertical[PLAY_MODEL] + videoFps[0] + ".flv"); + } else if (landscape == VIDEO_HORIZONTAL && PLAY_MODEL != -1) { + waitNextUrl = srcUrl.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); + } else { + waitNextUrl = null; + } + mPlayer.switchUrl(srcUrl); } } @@ -404,7 +414,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { params1.topMargin = contexts.getResources().getDimensionPixelOffset(R.dimen.live_top); params1.addRule(RelativeLayout.ALIGN_TOP); ry_view.requestLayout(); - isPk=true; + isPk = true; if (mPlayer.getUrl().contains("848_24.flv") || mPlayer.getUrl().contains("1280_24.flv")) { tmpPk = false; switchStreamPk(true); @@ -477,12 +487,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void setPkview() { Log.i("收到socket--->", "变成16:9"); String url = srcUrl; - if (PLAY_MODEL != -1) { - url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); - } - isPk = true; - mPlayer.setViewResizeMode(false); - mPlayer.switchUrl(url); + switchStreamPk(true); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = vHeight; params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); @@ -499,11 +504,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); String url = srcUrl; - if (PLAY_MODEL != -1) { - url = url.replace(".flv", videoRatioVertical[PLAY_MODEL] + videoFps[0] + ".flv"); - } - mPlayer.setViewResizeMode(true); - mPlayer.switchUrl(url); + switchStreamPk(false); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = RelativeLayout.LayoutParams.MATCH_PARENT; @@ -1139,7 +1140,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); - // ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); + ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { @@ -1169,6 +1170,10 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (loadingListener != null) { loadingListener.onPlayer(); } + if (waitNextUrl != null) { + mPlayer.switchUrl(waitNextUrl); + waitNextUrl = null; + } } } } From ee6a4288b07bc7553570b68c2108abcc728d2245 Mon Sep 17 00:00:00 2001 From: Yutousama <583819556@qq.com> Date: Mon, 9 Jan 2023 20:30:34 +0800 Subject: [PATCH 070/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/bean/EnterRoomInfoModel.java | 4 ++ .../yunbao/common/bean/EnterRoomNewModel.java | 16 ++++++++ .../java/com/yunbao/common/bean/LiveBean.java | 40 ++++++++++++++++++- .../live/views/LivePlayRyViewHolder.java | 9 +++-- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/bean/EnterRoomInfoModel.java b/common/src/main/java/com/yunbao/common/bean/EnterRoomInfoModel.java index 87e6e14c4..1a6af9aa9 100644 --- a/common/src/main/java/com/yunbao/common/bean/EnterRoomInfoModel.java +++ b/common/src/main/java/com/yunbao/common/bean/EnterRoomInfoModel.java @@ -1,6 +1,7 @@ package com.yunbao.common.bean; import com.google.gson.annotations.SerializedName; +import com.yunbao.common.utils.StringUtil; import java.util.List; @@ -475,6 +476,9 @@ public class EnterRoomInfoModel extends BaseModel { } public String getIsconnection() { + if(StringUtil.isEmpty(isconnection)){ + isconnection="0"; + } return isconnection; } diff --git a/common/src/main/java/com/yunbao/common/bean/EnterRoomNewModel.java b/common/src/main/java/com/yunbao/common/bean/EnterRoomNewModel.java index 66daf307c..e0228b8d0 100644 --- a/common/src/main/java/com/yunbao/common/bean/EnterRoomNewModel.java +++ b/common/src/main/java/com/yunbao/common/bean/EnterRoomNewModel.java @@ -119,4 +119,20 @@ public class EnterRoomNewModel extends BaseModel { public void setClarityType(int clarityType) { this.clarityType = clarityType; } + + @Override + public String toString() { + return "EnterRoomNewModel{" + + "liveInfo=" + liveInfo + + ", enterRoomInfo=" + enterRoomInfo + + ", rankHour=" + rankHour + + ", newPeopleTask=" + newPeopleTask + + ", wishList=" + wishList + + ", guardUserAvatar=" + guardUserAvatar + + ", activeList=" + activeList + + ", isUseHotCard='" + isUseHotCard + '\'' + + ", liveRoomActivityModels=" + liveRoomActivityModels + + ", clarityType=" + clarityType + + '}'; + } } diff --git a/common/src/main/java/com/yunbao/common/bean/LiveBean.java b/common/src/main/java/com/yunbao/common/bean/LiveBean.java index b5567764b..7dbafa055 100644 --- a/common/src/main/java/com/yunbao/common/bean/LiveBean.java +++ b/common/src/main/java/com/yunbao/common/bean/LiveBean.java @@ -493,6 +493,44 @@ public class LiveBean implements Parcelable { @Override public String toString() { - return "uid: " + uid + " , userNiceName: " + userNiceName + " ,playUrl: " + pull; + return "LiveBean{" + + "uid='" + uid + '\'' + + ", avatar='" + avatar + '\'' + + ", avatarThumb='" + avatarThumb + '\'' + + ", userNiceName='" + userNiceName + '\'' + + ", title='" + title + '\'' + + ", city='" + city + '\'' + + ", stream='" + stream + '\'' + + ", pull='" + pull + '\'' + + ", thumb='" + thumb + '\'' + + ", nums='" + nums + '\'' + + ", sex=" + sex + + ", distance='" + distance + '\'' + + ", levelAnchor=" + levelAnchor + + ", type=" + type + + ", typeVal='" + typeVal + '\'' + + ", goodNum='" + goodNum + '\'' + + ", gameAction=" + gameAction + + ", game='" + game + '\'' + + ", islive='" + islive + '\'' + + ", isTop='" + isTop + '\'' + + ", pk_avatar_thumb='" + pk_avatar_thumb + '\'' + + ", landscape=" + landscape + + ", hot_num='" + hot_num + '\'' + + ", content_pic_size_one='" + content_pic_size_one + '\'' + + ", content_pic_size_two='" + content_pic_size_two + '\'' + + ", content_pic_size_three='" + content_pic_size_three + '\'' + + ", is_week='" + is_week + '\'' + + ", img='" + img + '\'' + + ", url='" + url + '\'' + + ", drpk_status='" + drpk_status + '\'' + + ", is_rong=" + is_rong + + ", isattention='" + isattention + '\'' + + ", recommendCardtype='" + recommendCardtype + '\'' + + ", recommendCardIconSizeTwo='" + recommendCardIconSizeTwo + '\'' + + ", recommendCardIconSizeThree='" + recommendCardIconSizeThree + '\'' + + ", params=" + params + + ", mWeekList=" + mWeekList + + '}'; } } diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index cce26f97f..2e0e1a5b9 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -244,7 +244,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void setLiveEnterRoomNewModel(EnterRoomNewModel data) { super.setLiveEnterRoomNewModel(data); - mPlayer.clearFrame(); + isPk=data.getEnterRoomInfo().getIsconnection().equals("1"); } /** @@ -283,9 +283,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == VIDEO_VERTICAL) { - url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); + waitNextUrl = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); } else if (landscape == VIDEO_HORIZONTAL) { - url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); + waitNextUrl = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } } else if (!url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(false); @@ -311,7 +311,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void switchStream(String url, int playModel) { srcUrl = url; PLAY_MODEL = playModel; - Log.i(TAG, "switchStream: " + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape = " + videoLandscape); + Log.i(TAG, "switchStream: " + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape = " + videoLandscape + " ispk = " + isPk+" bean = "+roomModel.getEnterRoomInfo().getIsconnection()); if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == VIDEO_VERTICAL && !isPk) { @@ -487,6 +487,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void setPkview() { Log.i("收到socket--->", "变成16:9"); String url = srcUrl; + isPk = true; switchStreamPk(true); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = vHeight; From e2761049e5fcb32eaacdc6fd246bb3d7cdf5d6ac Mon Sep 17 00:00:00 2001 From: Yutousama <583819556@qq.com> Date: Mon, 9 Jan 2023 21:29:46 +0800 Subject: [PATCH 071/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BE=8E=E9=A2=9C?= =?UTF-8?q?=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/views/LivePushRyViewHolder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java index b7fc7d1cb..abe5d0ef7 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java @@ -775,7 +775,8 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX videoLayout1.setY(0); //Y 坐标 videoLayout1.setWidth(720); // 视频窗口的宽 videoLayout1.setHeight(1280); // 视频窗口的高 - RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(new IRCRTCVideoOutputFrameListener() { + //不能设置setVideoFrameListener,会影响到美颜 + /* RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(new IRCRTCVideoOutputFrameListener() { @Override public RCRTCVideoFrame processVideoFrame(RCRTCVideoFrame rtcVideoFrame) { // 使用数据进行美颜/录像等处理后,需要把数据再返回给 SDK 做发送。 @@ -784,7 +785,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX Log.e("视频流", "Height---------------------" + rtcVideoFrame.getHeight()); return rtcVideoFrame; } - }); + });*/ //2. 合流画布设置 rcrtcLiveInfo.setMixConfig(config, new IRCRTCResultCallback() { @Override From 2e6efc69e8f17edcf64e1ac69dc515ebfe02a963 Mon Sep 17 00:00:00 2001 From: Yutousama <583819556@qq.com> Date: Mon, 9 Jan 2023 22:36:51 +0800 Subject: [PATCH 072/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/utils/LiveExoPlayerManager.java | 10 ++++---- .../live/views/LivePlayRyViewHolder.java | 24 +++++++------------ 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 2372f156a..24898ddc1 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -39,11 +39,11 @@ public class LiveExoPlayerManager { public LiveExoPlayerManager(Context mContext) { DefaultLoadControl control = new DefaultLoadControl.Builder() .setPrioritizeTimeOverSizeThresholds(false) - .setBackBuffer(15_000, true) - .setBufferDurationsMs(150, - 5_000, - 50, - 100) + .setBackBuffer(120_000, true) + .setBufferDurationsMs(500, + 60_000, + 150, + 200) .build(); player1 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); player2 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 2e0e1a5b9..586dd7575 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -244,7 +244,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void setLiveEnterRoomNewModel(EnterRoomNewModel data) { super.setLiveEnterRoomNewModel(data); - isPk=data.getEnterRoomInfo().getIsconnection().equals("1"); + isPk = data.getEnterRoomInfo().getIsconnection().equals("1"); } /** @@ -282,9 +282,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Log.i(TAG, "play" + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape" + videoLandscape); if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); - if (landscape == VIDEO_VERTICAL) { + if (landscape == VIDEO_VERTICAL && !isPk) { waitNextUrl = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); - } else if (landscape == VIDEO_HORIZONTAL) { + } else if (landscape == VIDEO_HORIZONTAL || isPk) { waitNextUrl = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } } else if (!url.contains(videoFps[0] + ".flv")) { @@ -311,7 +311,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void switchStream(String url, int playModel) { srcUrl = url; PLAY_MODEL = playModel; - Log.i(TAG, "switchStream: " + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape = " + videoLandscape + " ispk = " + isPk+" bean = "+roomModel.getEnterRoomInfo().getIsconnection()); + Log.i(TAG, "switchStream: " + " url:" + url + " playModel: " + playModel + " landscape: " + landscape + " videoLandscape = " + videoLandscape + " ispk = " + isPk + " bean = " + roomModel.getEnterRoomInfo().getIsconnection()); if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == VIDEO_VERTICAL && !isPk) { @@ -342,7 +342,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void switchStreamPk(boolean isPk) { super.switchStreamPk(isPk); - if (isPk && !tmpPk) { + Log.i(TAG, "switchStreamPk: isPk1" + isPk + " tmp = " + !tmpPk + " isPk2" + this.isPk); + if (isPk && !tmpPk || this.isPk) { tmpPk = true; mPlayer.setViewResizeMode(false); String url; @@ -502,24 +503,15 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Log.i("收收收", landscape + ""); isPk = false; tmpPk = false; + switchStreamPk(false); if (landscape == 2) { Log.i("收到socket--->", "还原9:16"); - String url = srcUrl; - switchStreamPk(false); - RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = RelativeLayout.LayoutParams.MATCH_PARENT; params.topMargin = 0; mVideoView.requestLayout(); } else { - String url = srcUrl; - if (PLAY_MODEL != -1) { - url = url.replace(".flv", videoRatioHorizontal[PLAY_MODEL] + videoFps[0] + ".flv"); - } - mPlayer.setViewResizeMode(false); - mPlayer.switchUrl(url); - RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); params.height = vHeight; params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); @@ -1166,7 +1158,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Player.Listener.super.onIsPlayingChanged(isPlaying); if (isPlaying) { hideCover(); - Log.i(TAG, "onIsPlayingChanged: 开始播放"); + Log.i(TAG, "onIsPlayingChanged: 开始播放 | waitNextUrl = "+waitNextUrl); OkDownload.getInstance().startAll(); if (loadingListener != null) { loadingListener.onPlayer(); From d48098648533c7d6780331f43584ea0691931e36 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 10:34:55 +0800 Subject: [PATCH 073/118] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=BB=B6=E8=BF=9F200?= =?UTF-8?q?=E6=AF=AB=E7=A7=92=E9=9A=90=E8=97=8Floading?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/views/PortraitLiveManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 5cc3a058d..f35c9cf34 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -279,7 +279,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLivePlayViewHolder.setLoadViewListener(new LiveRoomPlayViewHolder.LoadingListener() { @Override public void onPlayer() { - loading.setVisibility(View.GONE); + liveHandler.postDelayed(()->loading.setVisibility(View.GONE),200); } }); mLiveRoomViewHolder.subscribeActivityLifeCycle(); From 652e569e2be80690ecf55a498424db5b341a5090 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Tue, 10 Jan 2023 11:02:22 +0800 Subject: [PATCH 074/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BB=E6=92=AD?= =?UTF-8?q?=E7=AB=AF=E5=8F=91=E5=B8=83=E8=BF=9C=E7=AB=AF=E6=B5=81=E5=88=86?= =?UTF-8?q?=E8=BE=A8=E7=8E=87=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/event/LivePushRyEvent.java | 6 +++ .../live/activity/LiveRyAnchorActivity.java | 42 +++++++++---------- .../live/views/LiveNewReadyRyViewHolder.java | 22 +++++----- .../live/views/LivePushRyViewHolder.java | 32 ++++++++------ 4 files changed, 56 insertions(+), 46 deletions(-) create mode 100644 common/src/main/java/com/yunbao/common/event/LivePushRyEvent.java diff --git a/common/src/main/java/com/yunbao/common/event/LivePushRyEvent.java b/common/src/main/java/com/yunbao/common/event/LivePushRyEvent.java new file mode 100644 index 000000000..7ead2123a --- /dev/null +++ b/common/src/main/java/com/yunbao/common/event/LivePushRyEvent.java @@ -0,0 +1,6 @@ +package com.yunbao.common.event; + +import com.yunbao.common.bean.BaseModel; + +public class LivePushRyEvent extends BaseModel { +} diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index 782aa7d2e..1c07161e5 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -212,27 +212,27 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl Bus.getOn(this); Intent intent = getIntent(); initFaceManager(); -// RCRTCEngine.getInstance().registerStatusReportListener(new IRCRTCStatusReportListener() { -// -// @Override -// public void onConnectionStats(StatusReport statusReport) { -// //视频发送信息 -// for (Map.Entry entry : statusReport.statusVideoSends.entrySet()) { -// StatusBean statusBean = entry.getValue(); -// //获取userID -// String userId = statusBean.uid; -// //获取视频 宽x高@帧率 -// String resolution = statusBean.frameWidth + "x" + statusBean.frameHeight + "@" + statusBean.frameRate; -// //获取码率 -// long bitRate = statusBean.bitRate; -// //丢包率 -// long lossRate = statusBean.packetLostRate; -// //带宽 -// String googAvailableSendBandwidth = statusReport.googAvailableSendBandwidth; -// Log.e("网速和内存", "码率:" +bitRate+ " 丢包率:" + lossRate+" 带宽:"+googAvailableSendBandwidth); -// } -// } -// }); + RCRTCEngine.getInstance().registerStatusReportListener(new IRCRTCStatusReportListener() { + + @Override + public void onConnectionStats(StatusReport statusReport) { + //视频发送信息 + for (Map.Entry entry : statusReport.statusVideoSends.entrySet()) { + StatusBean statusBean = entry.getValue(); + //获取userID + String userId = statusBean.uid; + //获取视频 宽x高@帧率 + String resolution = statusBean.frameWidth + "x" + statusBean.frameHeight + "@" + statusBean.frameRate; + //获取码率 + long bitRate = statusBean.bitRate; + //丢包率 + long lossRate = statusBean.packetLostRate; + //带宽 + String googAvailableSendBandwidth = statusReport.googAvailableSendBandwidth; + Log.e("网速和内存", "获取视频:" +resolution+ " 丢包率:" + lossRate+" 带宽:"+googAvailableSendBandwidth); + } + } + }); leave_img = findViewById(R.id.leave_img); mLiveSDK = intent.getIntExtra(Constants.LIVE_SDK, Constants.LIVE_SDK_KSY); mLiveKsyConfigBean = intent.getParcelableExtra(Constants.LIVE_KSY_CONFIG); diff --git a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java index d99df4d6f..9312232bc 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveNewReadyRyViewHolder.java @@ -9,7 +9,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; -import android.text.format.Formatter; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -29,12 +28,13 @@ import com.yunbao.common.Constants; import com.yunbao.common.bean.LiveClassBean; import com.yunbao.common.bean.LiveRoomTypeBean; import com.yunbao.common.bean.UserBean; +import com.yunbao.common.event.LivePushRyEvent; import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.interfaces.CommonCallback; import com.yunbao.common.interfaces.ImageResultCallback; import com.yunbao.common.manager.IMLoginManager; -import com.yunbao.common.utils.DeviceUtils; +import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.L; import com.yunbao.common.utils.ProcessImageUtil; @@ -63,12 +63,8 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.io.File; -import java.util.Map; import cn.rongcloud.rtc.api.RCRTCEngine; -import cn.rongcloud.rtc.api.callback.IRCRTCStatusReportListener; -import cn.rongcloud.rtc.api.report.StatusBean; -import cn.rongcloud.rtc.api.report.StatusReport; import cn.rongcloud.rtc.api.stream.RCRTCCameraOutputStream; import cn.rongcloud.rtc.api.stream.RCRTCVideoStreamConfig; import cn.rongcloud.rtc.base.RCRTCParamsType; @@ -215,8 +211,8 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl // DeviceUtils.getNetSpeed(mContext);//获取当前上传网速 // Log.e("网速和内存", "内存:" + + " 网速:" + DeviceUtils.getNetSpeed(mContext)); - selectClarity = IMLoginManager.get(mContext).getSelectClarity(); - setSelectClarity(selectClarity); + IMLoginManager.get(mContext).setSelectClarity(selectClarity); + setSelectClarity(IMLoginManager.get(mContext).getSelectClarity()); ViewClicksAntiShake .clicksAntiShake( findViewById(R.id.btn_live_clarity), () -> { @@ -327,6 +323,9 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl .setVideoResolution(rcrtcVideoResolution) .build(); RCRTCEngine.getInstance().getDefaultVideoStream().setVideoConfig(config); + Log.e("切换分辨率", "时间戳" + System.currentTimeMillis()); + //重新发布一下流 + Bus.get().post(new LivePushRyEvent()); } public void setManager(FaceManager manager) { @@ -334,7 +333,6 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl } - @Override public void onClick(View v) { if (!canClick()) { @@ -364,7 +362,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl return; } // startLive(); - liveOpenCustomPopup = new LiveOpenCustomPopup(mContext, selectClarity, classBean, liveRoomTypeBean) + liveOpenCustomPopup = new LiveOpenCustomPopup(mContext, IMLoginManager.get(mContext).getSelectClarity(), classBean, liveRoomTypeBean) .setCallBack(new LiveOpenCustomPopup.LiveOpenCallBack() { @Override @@ -384,7 +382,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl LiveClarityCustomPopup liveClarityCustomPopup = new LiveClarityCustomPopup(mContext, IMLoginManager.get(mContext).getSelectClarity(), - IMLoginManager.get(mContext).getClarity() ? 0 : LiveClarityCustomPopup.BAN_1080, false); + IMLoginManager.get(mContext).getClarity() ? 0 : LiveClarityCustomPopup.BAN_1080, false); new XPopup.Builder(mContext) .setPopupCallback(new XPopupCallback() { @Override @@ -821,7 +819,7 @@ public class LiveNewReadyRyViewHolder extends AbsViewHolder implements View.OnCl return; } String title = mEditTitle.getText().toString().trim(); - LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, mAvatarFile, selectClarity + 1, new HttpCallback() { + LiveHttpUtil.newcreateRoom(title, mLiveClassID, mLiveType, mLiveTypeVal, mAvatarFile, IMLoginManager.get(mContext).getSelectClarity() + 1, new HttpCallback() { @Override public void onSuccess(int code, String msg, final String[] info) { if (code == 0 && info.length > 0) { diff --git a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java index abe5d0ef7..e4c2af532 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java @@ -34,6 +34,7 @@ import com.yunbao.common.Constants; import com.yunbao.common.bean.HttpCallbackModel; import com.yunbao.common.bean.UserBean; import com.yunbao.common.event.AnchorInfoEvent; +import com.yunbao.common.event.LivePushRyEvent; import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; @@ -41,6 +42,7 @@ import com.yunbao.common.http.live.LiveNetManager; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.IMRTCManager; import com.yunbao.common.manager.RandomPkManager; +import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DialogUitl; import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.L; @@ -71,14 +73,12 @@ import cn.rongcloud.rtc.api.RCRTCRoomConfig; import cn.rongcloud.rtc.api.callback.IRCRTCResultCallback; import cn.rongcloud.rtc.api.callback.IRCRTCResultDataCallback; import cn.rongcloud.rtc.api.callback.IRCRTCRoomEventsListener; -import cn.rongcloud.rtc.api.callback.IRCRTCVideoOutputFrameListener; import cn.rongcloud.rtc.api.stream.RCRTCInputStream; import cn.rongcloud.rtc.api.stream.RCRTCLiveInfo; import cn.rongcloud.rtc.api.stream.RCRTCVideoStreamConfig; import cn.rongcloud.rtc.api.stream.RCRTCVideoView; import cn.rongcloud.rtc.base.RCRTCParamsType; import cn.rongcloud.rtc.base.RCRTCRoomType; -import cn.rongcloud.rtc.base.RCRTCVideoFrame; import cn.rongcloud.rtc.base.RTCErrorCode; import cn.rongcloud.rtc.core.CameraVideoCapturer; import cn.rongcloud.rtc.core.RendererCommon; @@ -396,6 +396,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX @Override public void init() { super.init(); + Bus.getOn(this); mPreView = (FrameLayout) findViewById(R.id.camera_preview); mPreView1 = (FrameLayout) findViewById(R.id.camera_preview1); dr1_preview = (FrameLayout) findViewById(R.id.dr1_preview); @@ -775,17 +776,6 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX videoLayout1.setY(0); //Y 坐标 videoLayout1.setWidth(720); // 视频窗口的宽 videoLayout1.setHeight(1280); // 视频窗口的高 - //不能设置setVideoFrameListener,会影响到美颜 - /* RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(new IRCRTCVideoOutputFrameListener() { - @Override - public RCRTCVideoFrame processVideoFrame(RCRTCVideoFrame rtcVideoFrame) { - // 使用数据进行美颜/录像等处理后,需要把数据再返回给 SDK 做发送。 -// rtcVideoFrame.setTextureId(tencentTRTCBeautyManager.renderWithTexture(rtcVideoFrame.getTextureId(), rtcVideoFrame.getWidth(), rtcVideoFrame.getHeight(), false)); - Log.e("视频流", "Width---------------------" + rtcVideoFrame.getWidth()); - Log.e("视频流", "Height---------------------" + rtcVideoFrame.getHeight()); - return rtcVideoFrame; - } - });*/ //2. 合流画布设置 rcrtcLiveInfo.setMixConfig(config, new IRCRTCResultCallback() { @Override @@ -858,6 +848,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX @Override public void release() { super.release(); + Bus.getOff(this); LiveHttpUtil.cancel(LiveHttpConsts.LINK_MIC_TX_MIX_STREAM); rtcRoom = null; } @@ -913,4 +904,19 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX return ((LiveActivity) mContext).getTxAppId(); } + @Subscribe(threadMode = ThreadMode.MAIN) + public void setSelectClarity(LivePushRyEvent event) { + if (rtcRoom != null) + rtcRoom.getLocalUser().publishDefaultLiveStreams(new IRCRTCResultDataCallback() { + @Override + public void onSuccess(RCRTCLiveInfo rcrtcLiveInfo1) { + rcrtcLiveInfo = rcrtcLiveInfo1; + } + + @Override + public void onFailed(RTCErrorCode rtcErrorCode) { + Log.e("ry", "rtcErrorCode" + rtcErrorCode); + } + }); + } } From a22dfb6214712ba277a0f8240a2ae92c2e9ba50f Mon Sep 17 00:00:00 2001 From: 18142669586 <1669783059@qq.com> Date: Tue, 10 Jan 2023 13:27:13 +0800 Subject: [PATCH 075/118] =?UTF-8?q?=E5=96=AE=E4=BA=BAPK=E5=8D=A10=E5=88=86?= =?UTF-8?q?=20=E5=84=AA=E5=8C=96=E8=A8=88=E7=AE=97=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presenter/LiveRyLinkMicPkPresenter.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index 7bffad25e..c599c1e39 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -39,6 +39,7 @@ import com.tencent.trtc.TRTCCloud; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.bean.UserBean; import com.yunbao.common.event.AnchorInfoEvent; +import com.yunbao.common.event.FollowEvent; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.http.live.LiveNetManager; @@ -304,18 +305,19 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { */ int i = 0; - private void nextPkTimeCountDown() { - Log.i("vvvs", "mHandler:" + (mHandler != null)); + private void nextPkTimeCountDown(int is) { + if (mHandler != null) { mHandler.sendEmptyMessageAtTime(WHAT_PK_TIME, getNextSecondTime()); } if (mLiveLinkMicPkViewHolder != null) { String s = mIsPkEnd ? mPkTimeString2 : mPkTimeString1; String s1 = StringUtil.getDurationText(mPkTimeCount * 1000); -// if (i == 1 && s1.equals("00:01")) { -// s1 = "00:00"; -// i = 0; -// } + Log.i("tag23333",mPkTimeCount+"mPkTimeCount"+s1+"is"+is); + if (i == 1 && s1.equals("00:01")) { + s1 = "00:00"; + i = 0; + } if (rtcRoom != null) { ScreenDimenUtil util = ScreenDimenUtil.getInstance(); int mScreenWdith = util.getScreenWdith(); @@ -328,8 +330,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { Log.i("tts", s1); mLiveLinkMicPkViewHolder.setTime(s + " " + s1); - if (i == 0 && s1.equals("00:01") && mIsAnchor && !s.contains("懲罰")) { - i = 1; + if ( s1.equals("00:01") && mIsAnchor && !s.contains("懲罰")) { HttpClient.getInstance().get("Livepk.endPK", "Livepk.endPK") .params("uid", CommonAppConfig.getInstance().getUid()) .params("addtime", "00:00") @@ -384,11 +385,11 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * pk时间倒计时 */ private void changePkTime() { - if (mPkTimeCount < 0) return; + if (mPkTimeCount<0)return; mPkTimeCount--; Log.i("vvvs", "mPkTimeCount:" + mPkTimeCount); if (mPkTimeCount >= 0) {// - nextPkTimeCountDown(); + nextPkTimeCountDown(1); if (mContext instanceof LiveAudienceActivity) { ((LiveAudienceActivity) mContext).setPkStatus(true); } @@ -1921,7 +1922,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { mPkTimeCount = pkTime; Log.d("mPkTimeCount1", "" + mPkTimeCount + ";mPkTimeFromServer=" + mPkTimeFromServer); mPkTimeFromServer = pkTime; - nextPkTimeCountDown(); + nextPkTimeCountDown(2); } @@ -1957,7 +1958,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { Log.d("mPkTimeCount1", "" + mPkTimeCount + ";mPkTimeFromServer=" + mPkTimeFromServer); // mPkTimeFromServer=pkTime; //恢复播放画面 - nextPkTimeCountDown(); + nextPkTimeCountDown(3); } @@ -1984,7 +1985,6 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { } mLiveLinkMicPkViewHolder.startAnim(); mLiveLinkMicPkViewHolder.showTime(); - nextPkTimeCountDown(); if (mIsAnchor) { ((LiveRyAnchorActivity) mContext).setPkBtnVisible(false); mPkTimeCount = PK_TIME_MAX; @@ -1993,6 +1993,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { // mPkTimeCount=mPkTimeFromServer; mPkTimeCount = PK_TIME_MAX; } + nextPkTimeCountDown(4); Log.d("mPkTimeCount2", "" + mPkTimeCount + ";mPkTimeFromServer=" + mPkTimeFromServer); } @@ -2036,7 +2037,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { mLiveLinkMicPkViewHolder.end(-1); } mPkTimeCount = PK_TIME_MAX_2;//进入惩罚时间 - nextPkTimeCountDown(); + nextPkTimeCountDown(5); } } @@ -2164,7 +2165,6 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { mHandler.removeCallbacksAndMessages(null); } mSocketRyClient = null; - mHandler = null; if (mLiveLinkMicPkViewHolder != null) { mLiveLinkMicPkViewHolder.release(); } From 749f756d58b282c104fc8d0fa3e4fd0065589220 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 13:32:08 +0800 Subject: [PATCH 076/118] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=B9=B8=E8=BF=90?= =?UTF-8?q?=E7=99=BE=E5=88=86=E7=99=BE=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/src/main/java/com/yunbao/common/Constants.java | 1 + .../java/com/yunbao/live/activity/LiveAudienceActivity.java | 1 + .../main/java/com/yunbao/live/event/LiveAudienceEvent.java | 3 ++- .../src/main/java/com/yunbao/live/socket/SocketRyClient.java | 5 +++++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/yunbao/common/Constants.java b/common/src/main/java/com/yunbao/common/Constants.java index 3063290c0..2e8a5c808 100644 --- a/common/src/main/java/com/yunbao/common/Constants.java +++ b/common/src/main/java/com/yunbao/common/Constants.java @@ -191,6 +191,7 @@ public class Constants { public static final String LOVE_CHECK = "LoveCheck";//热度卡消息 public static final String TRUMPET_NOTIFY = "TrumpetNotify";//全栈喇叭 public static final String LuckyAngel = "LuckyCheck";//幸运天使 + public static final String Lucky100Check = "Lucky100Check";//幸运天使 public static final int SOCKET_WHAT_CONN = 0; public static final int SOCKET_WHAT_DISCONN = 2; diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index a769238ee..4fdde22aa 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -1179,6 +1179,7 @@ public class LiveAudienceActivity extends LiveActivity { break; case LUCKY_ANGEL: + case LUCKY_100_CHECK: manager.luckyAngel(event.getMsgModel()); break; case LINK_MIC: diff --git a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java index 204abebf2..036bf54ea 100644 --- a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java +++ b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java @@ -257,7 +257,8 @@ public class LiveAudienceEvent extends BaseModel { CUSTOM_FULL_SERVICE_NOTIFY(51, "全服通知"), CHANGE_VIEW(52, "更改连胜位置"), UPDATA_ROBOT(53, "更新机器人消息"), - LIVE_VIDEO(54, "画质选择"); + LIVE_VIDEO(54, "画质选择"), + LUCKY_100_CHECK(55,"幸运百分百"); private int type; private String name; diff --git a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java index b2685d167..7d27169eb 100644 --- a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java +++ b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java @@ -551,6 +551,11 @@ public class SocketRyClient { .setType(LiveAudienceEvent.LiveAudienceType.LUCKY_ANGEL) .setMsgModel(GsonUtils.fromJson(map.getJSONObject("ct").toString(), MsgModel.class))); break; + case Constants.Lucky100Check: + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.LUCKY_100_CHECK) + .setMsgModel(GsonUtils.fromJson(map.getJSONObject("ct").toString(), MsgModel.class))); + break; case Constants.PK_RANK_UPDATE: Log.i("PK排位", map.toString()); JSONObject item = map.getJSONObject("ct"); From 872245c9c9a4c3f4a5779eb301fa5d232bdd7639 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 15:34:40 +0800 Subject: [PATCH 077/118] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=B9=B8=E8=BF=90?= =?UTF-8?q?=E7=99=BE=E5=88=86=E7=99=BE=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/src/main/res/values-en/strings.xml | 1 + common/src/main/res/values/strings.xml | 1 + .../live/activity/LiveAudienceActivity.java | 4 +++- .../com/yunbao/live/adapter/LiveChatAdapter.java | 11 ++++++++++- .../java/com/yunbao/live/bean/LiveChatBean.java | 1 + .../com/yunbao/live/utils/LiveTextRender.java | 16 ++++++++++++++++ .../yunbao/live/views/LiveRoomViewHolder.java | 11 +++++++++++ 7 files changed, 43 insertions(+), 2 deletions(-) diff --git a/common/src/main/res/values-en/strings.xml b/common/src/main/res/values-en/strings.xml index fbe44671d..102cc792e 100644 --- a/common/src/main/res/values-en/strings.xml +++ b/common/src/main/res/values-en/strings.xml @@ -939,6 +939,7 @@ Limited ride And limited avatar frame In a batch Chat Congratulations %s have won %s in the Lucky Angel! The next lucky angel will be you! + Congratulations on %s winning %s in Luck 100 %! Go pass on the good luck! Guardian group %s people receive To complete diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 2c5c8b5e2..f3b7113f3 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -959,6 +959,7 @@ 聊聊天 想在其他APP上方也顯示小窗,\n可前往設置進行授權。 恭喜 %s 在幸運天使中抽中 %s!下一個幸運天使就是你哦! + 恭喜 %s 在好運百分百中抽中 %s!快去接力好運吧~ 守護團%s人 領取 去完成 diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index 4fdde22aa..462057ed5 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -1179,9 +1179,11 @@ public class LiveAudienceActivity extends LiveActivity { break; case LUCKY_ANGEL: - case LUCKY_100_CHECK: manager.luckyAngel(event.getMsgModel()); break; + case LUCKY_100_CHECK: + manager.lucky100(event.getMsgModel()); + break; case LINK_MIC: if (!StringUtil.isEmpty(((LinkMicUserBean) event.getObject()).getUid())) { mMicQueueList.put(((LinkMicUserBean) event.getObject()).getUid(), (LinkMicUserBean) event.getObject()); diff --git a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java index 12eee954f..6e5cb5312 100644 --- a/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/LiveChatAdapter.java @@ -1,6 +1,7 @@ package com.yunbao.live.adapter; import static com.yunbao.live.bean.LiveChatBean.AI_AUTOMATIC_SPEECH; +import static com.yunbao.live.bean.LiveChatBean.LUCKY_100_CHECK; import static com.yunbao.live.bean.LiveChatBean.LUCKY_ANGEL; import static com.yunbao.live.bean.LiveChatBean.RECOMMEND_CARD_NOTIFY; import static com.yunbao.live.bean.LiveChatBean.STAR_CHALLENGE_UPGRADE_NOTIFY; @@ -378,7 +379,15 @@ public class LiveChatAdapter extends RecyclerView.Adapter { new LiveTextRender().luckyAngel(mContext, mTextView, bean.getMsgModel()); } - } else { + }else if(bean.getType() == LUCKY_100_CHECK){ + if (!TextUtils.isEmpty(bean.getMsgModel().getSystem_bubble())) { + bean.setId(bean.getMsgModel().getUserId()); + itemView.setTag(bean); + LoadDian9TuUtil.loadDian9Tu(mContext, mBg, bean.getMsgModel().getSystem_bubble(), 1); + new LiveTextRender().lucky100(mContext, mTextView, bean.getMsgModel()); + } + } + else { if (bean.getBubble() != null && !bean.getBubble().equals("")) { //加载.9图聊天气泡 LoadDian9TuUtil.loadDian9Tu(mContext, mBg, bean.getBubble(), 1); diff --git a/live/src/main/java/com/yunbao/live/bean/LiveChatBean.java b/live/src/main/java/com/yunbao/live/bean/LiveChatBean.java index 5a492399f..8d876699b 100644 --- a/live/src/main/java/com/yunbao/live/bean/LiveChatBean.java +++ b/live/src/main/java/com/yunbao/live/bean/LiveChatBean.java @@ -22,6 +22,7 @@ public class LiveChatBean { public static final int AI_AUTOMATIC_SPEECH = 101; public static final int STAR_CHALLENGE_UPGRADE_NOTIFY = 105; public static final int LUCKY_ANGEL = 106;//幸运天使 + public static final int LUCKY_100_CHECK = 107;//幸运天使 diff --git a/live/src/main/java/com/yunbao/live/utils/LiveTextRender.java b/live/src/main/java/com/yunbao/live/utils/LiveTextRender.java index 8699d194f..ba96ab4b9 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveTextRender.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveTextRender.java @@ -157,6 +157,22 @@ public class LiveTextRender { builder.setSpan(new ForegroundColorSpan(Color.parseColor("#FFF86C")), giftIndexOf, giftIndexOf + giftSize, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); mTextView.setText(builder); } + /** + * 幸运100%活动 + */ + public void lucky100(Context mContext, TextView mTextView, MsgModel msgModel){ + String msg = mContext.getString(R.string.lucky_100); + msg = String.format(msg, msgModel.getUserName(), msgModel.getGiftName()); + int unameIndexOf = msg.indexOf(msgModel.getUserName()); + int giftIndexOf = msg.indexOf(msgModel.getGiftName()); + int unameSize = msgModel.getUserName().length(); + int giftSize = msgModel.getGiftName().length(); + SpannableStringBuilder builder = new SpannableStringBuilder(); + builder.append(msg); + builder.setSpan(new ForegroundColorSpan(Color.parseColor("#78FEFF")), unameIndexOf, unameIndexOf + unameSize, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + builder.setSpan(new ForegroundColorSpan(Color.parseColor("#FFF86C")), giftIndexOf, giftIndexOf + giftSize, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + mTextView.setText(builder); + } public void aiAutomaticSpeech(Context activity, TextView textView, AiAutomaticSpeechModel model) { ImgLoader.displayDrawable(activity, model.getIcon(), new ImgLoader.DrawableCallback() { diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 574dbf439..2c630a09f 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -3904,6 +3904,17 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis mLiveChatAdapter.insertItem(bean); } } + /** + * 幸运100%活动 + */ + public void lucky100(MsgModel model){ + if (mLiveChatAdapter != null) { + LiveChatBean bean = new LiveChatBean(); + bean.setType(LiveChatBean.LUCKY_100_CHECK); + bean.setMsgModel(model); + mLiveChatAdapter.insertItem(bean); + } + } @Subscribe(threadMode = ThreadMode.MAIN) public void updateSub(LiveAudienceEvent event) { From 518e57ee44a84b9c39d6f1954efa9f1d7ede6c19 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 15:35:15 +0800 Subject: [PATCH 078/118] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B7=B2=E7=BB=8F?= =?UTF-8?q?=E5=9C=A8=E5=A4=9A=E4=BA=BAPK=E6=97=B6=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E9=BB=98=E8=AE=A4=E6=B5=81=E5=88=86=E8=BE=A8?= =?UTF-8?q?=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/utils/LiveExoPlayerManager.java | 14 ++++++++++---- .../yunbao/live/views/LivePlayRyViewHolder.java | 15 +++++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 24898ddc1..3eb0dea13 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -34,7 +34,7 @@ public class LiveExoPlayerManager { private int playBufferIndex = 0;//卡顿计数器 private final Handler handler; private static double log_buffer_time = 0, log_buffer_max_time; - private String url; + private String url=""; public LiveExoPlayerManager(Context mContext) { DefaultLoadControl control = new DefaultLoadControl.Builder() @@ -71,6 +71,10 @@ public class LiveExoPlayerManager { mainView.requestLayout(); } + public boolean isViewResizeModeToPhone() { + return mainView.getResizeMode() == AspectRatioFrameLayout.RESIZE_MODE_ZOOM; + } + private void setAnalyticsListener() { player1.addAnalyticsListener(new AnalyticsListener() { @Override @@ -240,6 +244,7 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void startUrl(String url) { + if(url.equals(this.url))return; Log.i(TAG, "startUrl: " + url + " > " + mainView.getResizeMode()); this.url = url; isSwitchUrl = true; @@ -260,7 +265,8 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void switchUrl(String url) { - Log.i(TAG, "switchUrl: " + url); + if(url.equals(this.url))return; + Log.i(TAG, "switchUrl: " + url +" src : "+this.url); this.url = url; playBufferIndex = 0; isSwitchUrl = true; @@ -322,8 +328,8 @@ public class LiveExoPlayerManager { } public String getUrl() { - if(url==null){ - url=""; + if (url == null) { + url = ""; } return url; } diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 586dd7575..941b827f2 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -283,9 +283,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (playModel != PLAY_MODEL_DEF && !url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(landscape == VIDEO_VERTICAL); if (landscape == VIDEO_VERTICAL && !isPk) { - waitNextUrl = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); + url = url.replace(".flv", videoRatioVertical[playModel] + videoFps[0] + ".flv"); } else if (landscape == VIDEO_HORIZONTAL || isPk) { - waitNextUrl = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); + url = url.replace(".flv", videoRatioHorizontal[playModel] + videoFps[0] + ".flv"); } } else if (!url.contains(videoFps[0] + ".flv")) { mPlayer.setViewResizeMode(false); @@ -342,9 +342,9 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void switchStreamPk(boolean isPk) { super.switchStreamPk(isPk); - Log.i(TAG, "switchStreamPk: isPk1" + isPk + " tmp = " + !tmpPk + " isPk2" + this.isPk); + Log.i(TAG, "switchStreamPk: isPk1" + isPk + " tmp = " + !tmpPk + " isPk2 = " + this.isPk); + if(this.isPk&&tmpPk)return; if (isPk && !tmpPk || this.isPk) { - tmpPk = true; mPlayer.setViewResizeMode(false); String url; if (PLAY_MODEL != -1) { @@ -352,8 +352,11 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } else { url = srcUrl.replace(".flv", videoRatioHorizontal[1] + videoFps[0] + ".flv"); } - waitNextUrl = url; + if (!tmpPk) { + waitNextUrl = url; + } mPlayer.switchUrl(srcUrl); + tmpPk = true; } else if (!isPk) { tmpPk = false; if (landscape == VIDEO_VERTICAL && PLAY_MODEL != -1) { @@ -1158,7 +1161,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { Player.Listener.super.onIsPlayingChanged(isPlaying); if (isPlaying) { hideCover(); - Log.i(TAG, "onIsPlayingChanged: 开始播放 | waitNextUrl = "+waitNextUrl); + Log.i(TAG, "onIsPlayingChanged: 开始播放 | waitNextUrl = " + waitNextUrl); OkDownload.getInstance().startAll(); if (loadingListener != null) { loadingListener.onPlayer(); From 3606815a410a32a6748a53dff8bce12333b8d34e Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 16:12:17 +0800 Subject: [PATCH 079/118] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E6=8A=9B=E9=94=99=E6=97=B6=E9=87=8D=E6=96=B0=E6=92=AD=E6=94=BE?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E6=BB=91=E5=8A=A8=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E6=97=B6=E5=8F=AF=E8=83=BD=E5=87=BA=E7=8E=B0=E4=B8=8A?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E7=9B=B4=E6=92=AD=E9=97=B4=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/utils/LiveExoPlayerManager.java | 35 +++++++++++++++---- .../live/views/LivePlayRyViewHolder.java | 6 ++++ .../live/views/LiveRoomPlayViewHolder.java | 3 ++ .../live/views/PortraitLiveManager.java | 25 +++++++++++-- 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 3eb0dea13..dc2cd8c05 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -11,6 +11,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; @@ -34,7 +35,7 @@ public class LiveExoPlayerManager { private int playBufferIndex = 0;//卡顿计数器 private final Handler handler; private static double log_buffer_time = 0, log_buffer_max_time; - private String url=""; + private String url = ""; public LiveExoPlayerManager(Context mContext) { DefaultLoadControl control = new DefaultLoadControl.Builder() @@ -123,7 +124,7 @@ public class LiveExoPlayerManager { public void onPlaybackStateChanged(int playbackState) { Player.Listener.super.onPlaybackStateChanged(playbackState); Log.i(TAG, "onPlaybackStateChanged 1: " + playbackState); - if (playbackState == Player.STATE_READY) { + if (playbackState == Player.STATE_READY && !player1.isPlaying()) { player2.stop(); player2.clearVideoSurface(); player1.play(); @@ -177,6 +178,15 @@ public class LiveExoPlayerManager { Player.Listener.super.onIsLoadingChanged(isLoading); Log.i(TAG, "onIsLoadingChanged: 1 " + isLoading); } + + @Override + public void onPlayerError(@NonNull PlaybackException error) { + Player.Listener.super.onPlayerError(error); + error.printStackTrace(); + String url=LiveExoPlayerManager.this.url; + LiveExoPlayerManager.this.url=null; + startUrl(url); + } }); player2.addListener(new Player.Listener() { @@ -184,7 +194,7 @@ public class LiveExoPlayerManager { public void onPlaybackStateChanged(int playbackState) { Player.Listener.super.onPlaybackStateChanged(playbackState); Log.i(TAG, "onPlaybackStateChanged 2: " + playbackState); - if (playbackState == Player.STATE_READY) { + if (playbackState == Player.STATE_READY && !player2.isPlaying()) { player1.stop(); player1.clearVideoSurface(); player2.play(); @@ -235,6 +245,14 @@ public class LiveExoPlayerManager { Player.Listener.super.onIsLoadingChanged(isLoading); Log.i(TAG, "onIsLoadingChanged: 2 " + isLoading); } + @Override + public void onPlayerError(@NonNull PlaybackException error) { + Player.Listener.super.onPlayerError(error); + error.printStackTrace(); + String url=LiveExoPlayerManager.this.url; + LiveExoPlayerManager.this.url=null; + startUrl(url); + } }); } @@ -244,7 +262,7 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void startUrl(String url) { - if(url.equals(this.url))return; + if (url!=null&&url.equals(this.url)) return; Log.i(TAG, "startUrl: " + url + " > " + mainView.getResizeMode()); this.url = url; isSwitchUrl = true; @@ -265,8 +283,8 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void switchUrl(String url) { - if(url.equals(this.url))return; - Log.i(TAG, "switchUrl: " + url +" src : "+this.url); + if (url!=null&&url.equals(this.url)) return; + Log.i(TAG, "switchUrl: " + url + " src : " + this.url); this.url = url; playBufferIndex = 0; isSwitchUrl = true; @@ -316,7 +334,10 @@ public class LiveExoPlayerManager { } public void clearFrame() { - //mainView.setKeepContentOnPlayerReset(false); + mainView.setKeepContentOnPlayerReset(false); + if (mainView.getVideoSurfaceView() != null) { + mainView.setPlayer(null); + } } /** diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 941b827f2..27c684339 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -370,6 +370,12 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } } + @Override + public void clearFrame() { + super.clearFrame(); + mPlayer.clearFrame(); + } + @Override public void release() { mEnd = true; diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index a663763dd..63bc39eea 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -97,6 +97,9 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL public void switchStreamPk(boolean isPk) { } + public void clearFrame() { + } + public interface OnMicCallback { void onMikUpdate(); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index f35c9cf34..f9bf72956 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -244,12 +244,19 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mViewPager.setCanScroll(true); } }; + final Runnable loadRunnableGone = new Runnable() { + @Override + public void run() { + loading.setVisibility(View.GONE); + } + }; @Override public synchronized void onAdd(LiveBean data, int liveType, int liveTypeVal, int liveSdk) { isEnterRoom = false; openParametersModel = new OpenParametersModel(); mContext.runOnUiThread(new Runnable() { + @Override public void run() { Log.e("ImgLoader1", data.getAvatar()); @@ -264,9 +271,11 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe .setmLiveType(mLiveType) .setmLiveTypeVal(mLiveTypeVal))); loading.setVisibility(View.VISIBLE); + loading.setAlpha(0.6f); ImgLoader.displayBlurLive(mContext, mLiveBean.getAvatar(), ivBg); AnimationDrawable frameAnimation = (AnimationDrawable) ivLoading.getBackground(); frameAnimation.start(); + liveHandler.removeCallbacks(loadRunnableGone); if (mLivePlayViewHolder == null) { mLivePlayViewHolder = new LivePlayRyViewHolder(mContext, playContainer, 1); mLiveRoomViewHolder = new LiveRoomViewHolder(false, 1, mContext, mContainer, mSecondPage.findViewById(R.id.gift_gif), mSecondPage.findViewById(R.id.gift_svga), mContainerWrap, mContext.getWindowManager()); @@ -279,7 +288,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLivePlayViewHolder.setLoadViewListener(new LiveRoomPlayViewHolder.LoadingListener() { @Override public void onPlayer() { - liveHandler.postDelayed(()->loading.setVisibility(View.GONE),200); + liveHandler.postDelayed(loadRunnableGone, 350); } }); mLiveRoomViewHolder.subscribeActivityLifeCycle(); @@ -291,7 +300,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveLinkMicPresenter.setLiveSdk(mLiveSDK); mLiveLinkMicAnchorPresenter.setLiveSdk(mLiveSDK); } - if (mLiveRyLinkMicPkPresenter==null){ + if (mLiveRyLinkMicPkPresenter == null) { mLiveRyLinkMicPkPresenter = new LiveRyLinkMicPkPresenter(mContext, mLivePlayViewHolder, false, null); } //去除主播离开画面 @@ -367,6 +376,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe landscape = data.getLiveInfo().getLandscape(); mLivePlayViewHolder.setLiveBeanLandscape(landscape); mLivePlayViewHolder.setLiveEnterRoomNewModel(data); + mLivePlayViewHolder.clearFrame(); int userClarityType = IMLoginManager.get(mContext).getInt(LiveRoomPlayViewHolder.PLAY_MODEL_KEY, -1); int anchorClarityType = data.getClarityType() - 1; if (userClarityType != anchorClarityType) { @@ -596,7 +606,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.showPrizePoolLevel(String.valueOf(giftPrizePoolLevel)); } } - liveHandler.postDelayed(() -> loading.setVisibility(View.GONE), 10_000); + liveHandler.postDelayed(loadRunnableGone, 10_000); } @@ -1794,6 +1804,15 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe } } + /** + * 幸运100%活动 + */ + public void lucky100(MsgModel model){ + if (mLiveRoomViewHolder != null) { + mLiveRoomViewHolder.lucky100(model); + } + } + public void messageBottom() { if (mLiveRoomViewHolder != null) { mLiveRoomViewHolder.chatScrollToBottom(); From 418d306d72a6265994e8d19d3519c191156c4e52 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 16:33:41 +0800 Subject: [PATCH 080/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=82=B9=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E9=80=9A=E7=9F=A5=E6=97=B6=E5=BC=B9=E5=87=BA=E4=BA=86?= =?UTF-8?q?=E7=94=BB=E8=B4=A8=E9=80=89=E9=A1=B9=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/common/views/CustomDrawerPopupView.java | 4 +++- .../com/yunbao/live/activity/LiveAudienceActivity.java | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/yunbao/common/views/CustomDrawerPopupView.java b/common/src/main/java/com/yunbao/common/views/CustomDrawerPopupView.java index c5c23580c..9abff4007 100644 --- a/common/src/main/java/com/yunbao/common/views/CustomDrawerPopupView.java +++ b/common/src/main/java/com/yunbao/common/views/CustomDrawerPopupView.java @@ -129,7 +129,7 @@ public class CustomDrawerPopupView extends DrawerPopupView { public void onViewClicks() { dismiss(); if (callBack != null) { - callBack.systemNotice(); + callBack.changeVideo(); } @@ -198,6 +198,8 @@ public class CustomDrawerPopupView extends DrawerPopupView { void systemNotice(); + void changeVideo(); + void online(); void reportLayout(); diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index 462057ed5..430527077 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -877,6 +877,13 @@ public class LiveAudienceActivity extends LiveActivity { @Override public void systemNotice() { + Bus.get().post(new LiveAudienceEvent() + .setBean(mLiveBean) + .setType(LiveAudienceEvent.LiveAudienceType.NOTICE)); + } + + @Override + public void changeVideo() { Bus.get().post(new LiveAudienceEvent() .setBean(mLiveBean) .setType(LiveAudienceEvent.LiveAudienceType.LIVE_VIDEO)); From 1ad9effe91ad6e42736c530e3b07af64e40af272 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 16:57:25 +0800 Subject: [PATCH 081/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E7=9B=B8=E5=86=8C=E6=9D=83=E9=99=90=E5=90=8E=E6=89=93=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E5=B8=83=E5=8A=A8=E6=80=81=E4=BC=9A=E9=97=AA=E9=80=80?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/main/dialog/MainStartDialogFragment.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main/src/main/java/com/yunbao/main/dialog/MainStartDialogFragment.java b/main/src/main/java/com/yunbao/main/dialog/MainStartDialogFragment.java index e7b0d026a..9c3edaf42 100644 --- a/main/src/main/java/com/yunbao/main/dialog/MainStartDialogFragment.java +++ b/main/src/main/java/com/yunbao/main/dialog/MainStartDialogFragment.java @@ -17,6 +17,7 @@ import android.widget.LinearLayout; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.yunbao.common.CommonAppConfig; +import com.yunbao.common.CommonAppContext; import com.yunbao.common.Constants; import com.yunbao.common.activity.AbsActivity; import com.yunbao.common.dialog.AbsDialogFragment; @@ -228,12 +229,12 @@ public class MainStartDialogFragment extends AbsDialogFragment implements View.O Constants.myIntoIndex = 2; Intent intent = new Intent(mContext, MyWebViewActivity.class); intent.putExtra(Constants.URL, CommonAppConfig.HOST + "/h5/shequ/index.html#/h5/shequ/release" + "?token=" + CommonAppConfig.getInstance().getToken() + "&uid=" + CommonAppConfig.getInstance().getUid() + "&isRelease=1"); - startActivity(intent); + CommonAppContext.getTopActivity().startActivity(intent); } else { Constants.myIntoIndex = 2; Intent intent = new Intent(mContext, MyWebViewActivity.class); intent.putExtra(Constants.URL, CommonAppConfig.HOST + "/h5/shequ/index.html#/h5/shequ/release" + "?token=" + CommonAppConfig.getInstance().getToken() + "&uid=" + CommonAppConfig.getInstance().getUid() + "&isRelease=1"); - startActivity(intent); + CommonAppContext.getTopActivity().startActivity(intent); } } }; From f26fb83feca3734ed199aa68c36b5d12e59a046f Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Tue, 10 Jan 2023 17:04:56 +0800 Subject: [PATCH 082/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E9=80=81?= =?UTF-8?q?=E7=A4=BC=E5=85=A8=E6=9C=8D=E9=80=9A=E7=9F=A5=E5=B1=95=E7=A4=BA?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E7=A4=BC=E7=89=A9=E5=90=8D=E5=AD=97=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/common/glide/ImgLoader.java | 1 + .../java/com/yunbao/live/socket/SocketRyClient.java | 1 + .../java/com/yunbao/live/utils/AllMsgTextRender.java | 11 +++++++---- .../com/yunbao/live/views/PortraitLiveManager.java | 11 ++++++----- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/glide/ImgLoader.java b/common/src/main/java/com/yunbao/common/glide/ImgLoader.java index 15ef5591a..4d7882868 100644 --- a/common/src/main/java/com/yunbao/common/glide/ImgLoader.java +++ b/common/src/main/java/com/yunbao/common/glide/ImgLoader.java @@ -239,6 +239,7 @@ public class ImgLoader { public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { if (callback != null) { callback.onLoadSuccess(resource); + } } diff --git a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java index 7d27169eb..aa8790693 100644 --- a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java +++ b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java @@ -154,6 +154,7 @@ public class SocketRyClient { public void processBroadcast(String socketMsg) { L.e("收到socket--->" + socketMsg); + Log.i("SocketRyClient", "socketMsg" + socketMsg); Log.i("SocketRyClient", "socketMsg" + socketMsg); if (Constants.SOCKET_STOP_PLAY.equals(socketMsg)) { diff --git a/live/src/main/java/com/yunbao/live/utils/AllMsgTextRender.java b/live/src/main/java/com/yunbao/live/utils/AllMsgTextRender.java index 53e515f8b..602dd7cd2 100644 --- a/live/src/main/java/com/yunbao/live/utils/AllMsgTextRender.java +++ b/live/src/main/java/com/yunbao/live/utils/AllMsgTextRender.java @@ -68,10 +68,13 @@ public class AllMsgTextRender { ImgLoader.displayDrawable(context, url, new ImgLoader.DrawableCallback() { @Override public void onLoadSuccess(Drawable drawable) { - builder = createPrefix(drawable, builder); - builder = renderMsg(color2, builder, text); - textView.setText(builder); - giftAnimPresenter.setCountDownTimerEnd(intoIndex); + if (builder!=null&&!builder.toString().contains(text)){ + builder = createPrefix(drawable, builder); + builder = renderMsg(color2, builder, text); + textView.setText(builder); + giftAnimPresenter.setCountDownTimerEnd(intoIndex); + } + } @Override diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index f9bf72956..17a444429 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -696,6 +696,11 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRyLinkMicPkPresenter.release(); mLiveRyLinkMicPkPresenter = null; } + if (mLiveEndViewHolder != null) { + mLiveEndViewHolder.removeFromParent(); + mLiveEndViewHolder.release(); + } + mLiveEndViewHolder = null; if (isQuit) { isQuitF = true; if (mLiveAudienceViewHolder != null) { @@ -714,11 +719,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.clearData(); mLiveRoomViewHolder.countDownTimerTrickery = null; } - if (mLiveEndViewHolder != null) { - mLiveEndViewHolder.removeFromParent(); - mLiveEndViewHolder.release(); - } - mLiveEndViewHolder = null; + mLiveAudienceViewHolder = null; mLivePlayViewHolder = null; mLiveRoomViewHolder = null; From aca98cb7e6678ec06fff5a230a0a5c47b0ea39cf Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Tue, 10 Jan 2023 17:05:21 +0800 Subject: [PATCH 083/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E7=BB=93=E6=9D=9F=E6=BB=9A=E5=8A=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/yunbao/live/views/PortraitLiveManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 17a444429..4c0b4891d 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -673,6 +673,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe //断开socket + if (mSocketRyClient != null) { mSocketRyClient.disConnect(); mSocketRyClient = null; From 420573736d2a76079a124ace869d59fab38a42c9 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Tue, 10 Jan 2023 17:22:15 +0800 Subject: [PATCH 084/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E7=BB=93=E6=9D=9F=E6=BB=9A=E5=8A=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/views/PortraitLiveManager.java | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 4c0b4891d..154369138 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -624,8 +624,12 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe public void removeLiveEnd() { + if (mLiveEndViewHolder != null) { + mLiveEndViewHolder.removeFromParent(); + mLiveEndViewHolder.release(); + } + mLiveEndViewHolder = null; if (mLiveAudienceViewHolder != null) { - mLiveAudienceViewHolder.removeFromParent(); mLiveAudienceViewHolder.removeCallbacks(); mLiveAudienceViewHolder.release(); @@ -641,17 +645,12 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.clearData(); mLiveRoomViewHolder.countDownTimerTrickery = null; } - if (mLiveEndViewHolder != null) { - mLiveEndViewHolder.removeFromParent(); - mLiveEndViewHolder.release(); - } - mLiveEndViewHolder = null; mLiveAudienceViewHolder = null; - mLivePlayViewHolder = null; mLiveRoomViewHolder = null; mLiveLinkMicPresenter = null; mLiveLinkMicAnchorPresenter = null; mLiveRyLinkMicPkPresenter = null; + mLivePlayViewHolder = null; } @Override @@ -670,27 +669,24 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe if (mLiveAudienceViewHolder != null) { mLiveAudienceViewHolder.removeCallbacks(); } - //断开socket - - if (mSocketRyClient != null) { mSocketRyClient.disConnect(); mSocketRyClient = null; } - if (mSocketClient != null) { mSocketClient.disConnect(); mSocketClient = null; } - if (mLiveLinkMicPresenter != null) { mLiveLinkMicPresenter.clearData(); mLiveLinkMicPresenter.release(); + mLiveLinkMicPresenter = null; } if (mLiveLinkMicAnchorPresenter != null) { mLiveLinkMicAnchorPresenter.clearData(); mLiveLinkMicAnchorPresenter.release(); + mLiveLinkMicAnchorPresenter = null; } if (mLiveRyLinkMicPkPresenter != null) { mLiveRyLinkMicPkPresenter.clearData(); @@ -698,10 +694,9 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRyLinkMicPkPresenter = null; } if (mLiveEndViewHolder != null) { - mLiveEndViewHolder.removeFromParent(); - mLiveEndViewHolder.release(); + removeLiveEnd(); } - mLiveEndViewHolder = null; + if (isQuit) { isQuitF = true; if (mLiveAudienceViewHolder != null) { @@ -1809,7 +1804,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe /** * 幸运100%活动 */ - public void lucky100(MsgModel model){ + public void lucky100(MsgModel model) { if (mLiveRoomViewHolder != null) { mLiveRoomViewHolder.lucky100(model); } From 50d01ccd922280514d1c3d04fe15914e36e80eb9 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 17:47:42 +0800 Subject: [PATCH 085/118] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/views/LivePlayRyViewHolder.java | 2 +- .../main/java/com/yunbao/live/views/PortraitLiveManager.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 27c684339..22a847970 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -1142,7 +1142,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void onVideoSizeChanged(VideoSize videoSize) { Player.Listener.super.onVideoSizeChanged(videoSize); Log.i(TAG, "onVideoSizeChanged: width = " + videoSize.width + " height = " + videoSize.height); - ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); + //ToastUtil.show("分辨率: 宽 = " + videoSize.width + " 高 = " + videoSize.height); if (videoSize.height > videoSize.width) { videoLandscape = VIDEO_VERTICAL; } else { diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 154369138..64140fa64 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -271,7 +271,6 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe .setmLiveType(mLiveType) .setmLiveTypeVal(mLiveTypeVal))); loading.setVisibility(View.VISIBLE); - loading.setAlpha(0.6f); ImgLoader.displayBlurLive(mContext, mLiveBean.getAvatar(), ivBg); AnimationDrawable frameAnimation = (AnimationDrawable) ivLoading.getBackground(); frameAnimation.start(); From 7bffdda6b9fcc87b6d16157836c47e6599ce6e50 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Tue, 10 Jan 2023 17:50:03 +0800 Subject: [PATCH 086/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E7=BB=93=E6=9D=9F=E6=BB=9A=E5=8A=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 ++-- .../main/java/com/yunbao/live/views/PortraitLiveManager.java | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/config.gradle b/config.gradle index 7bd22a5fb..b123cc49e 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 -// serverHost : "https://napi.yaoulive.com", + serverHost : "https://napi.yaoulive.com", // - serverHost : "https://ceshi.yaoulive.com", +// serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 64140fa64..76bfa27d3 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -680,12 +680,10 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe if (mLiveLinkMicPresenter != null) { mLiveLinkMicPresenter.clearData(); mLiveLinkMicPresenter.release(); - mLiveLinkMicPresenter = null; } if (mLiveLinkMicAnchorPresenter != null) { mLiveLinkMicAnchorPresenter.clearData(); mLiveLinkMicAnchorPresenter.release(); - mLiveLinkMicAnchorPresenter = null; } if (mLiveRyLinkMicPkPresenter != null) { mLiveRyLinkMicPkPresenter.clearData(); @@ -693,7 +691,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRyLinkMicPkPresenter = null; } if (mLiveEndViewHolder != null) { - removeLiveEnd(); + removeLiveEnd(); } if (isQuit) { From 9f9c02b7e78e734fadbb574bcc828b96fc2c8db2 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 10 Jan 2023 17:59:53 +0800 Subject: [PATCH 087/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E5=88=86=E8=BE=A8=E7=8E=87=E4=BC=9A=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E6=92=AD=E6=94=BE=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/utils/LiveExoPlayerManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index dc2cd8c05..1bd62a09b 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -157,6 +157,9 @@ public class LiveExoPlayerManager { mainView.setPlayer(player1); status = MODEL_PLAY1; isSwitchUrl = false; + if(getNextPlayer().isPlaying()){ + getNextPlayer().stop(); + } if (listener != null) { listener.onIsPlayingChanged(true); } @@ -224,6 +227,9 @@ public class LiveExoPlayerManager { //ToastUtil.show(String.format(Locale.CHINA, "从加载到播放 = %.3f,最大耗时 = %.3f", tmp, log_buffer_max_time)); log_buffer_time = -1; status = MODEL_PLAY2; + if(getNextPlayer().isPlaying()){ + getNextPlayer().stop(); + } isSwitchUrl = false; if (listener != null) { listener.onIsPlayingChanged(true); From eaafcdd444ef3f6d33aae414168664daf6033ac3 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Wed, 11 Jan 2023 11:34:15 +0800 Subject: [PATCH 088/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=BF=9E=E9=BA=A6?= =?UTF-8?q?=E4=B8=8B=E9=BA=A6=E6=97=B6=E4=BC=9A=E7=94=BB=E9=9D=A2=E5=8D=A1?= =?UTF-8?q?=E4=BD=8F=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/utils/LiveExoPlayerManager.java | 5 +++++ .../java/com/yunbao/live/views/LivePlayRyViewHolder.java | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 1bd62a09b..c23774c61 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -338,6 +338,11 @@ public class LiveExoPlayerManager { public void play() { getNowPlayer().play(); } + public void replay(){ + String tmp=url; + url=null; + startUrl(tmp); + } public void clearFrame() { mainView.setKeepContentOnPlayerReset(false); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 22a847970..7459fd7e0 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -263,8 +263,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (!mPlayer.isPlaying()) { new Handler(Looper.getMainLooper()) .postDelayed(() -> { - mPlayer.stop(); - mPlayer.play(); + mPlayer.replay(); // ToastUtil.show("强制播放" + val); }, 100); } @@ -1041,6 +1040,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { "timestampNs:" + videoFrame.getTimestampNs() + "\n" + "分辨率:" + videoFrame.getBuffer().getHeight() + "x" + videoFrame.getBuffer().getWidth() + "\n" + "当前时间:" + new SimpleDateFormat("HH:mm:ss", Locale.CHINA).format(new Date()) + "\n"; + System.out.println("debugText = " + debugText); new Handler(Looper.getMainLooper()).post(() -> { debugView.setText(debugText); From 7226d542774a779995a12879f72aa841105c6f0d Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Wed, 11 Jan 2023 15:02:19 +0800 Subject: [PATCH 089/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=BF=9E=E9=BA=A6?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=AB=AF=E9=BB=98=E8=AE=A4=E7=94=A8=E5=B0=8F?= =?UTF-8?q?=E6=B5=81=E5=AF=BC=E8=87=B4=E7=94=BB=E9=9D=A2=E6=A8=A1=E7=B3=8A?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/utils/LiveExoPlayerManager.java | 24 +++++++++---------- .../live/views/LivePlayRyViewHolder.java | 7 ++++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index c23774c61..59292afa7 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -157,7 +157,7 @@ public class LiveExoPlayerManager { mainView.setPlayer(player1); status = MODEL_PLAY1; isSwitchUrl = false; - if(getNextPlayer().isPlaying()){ + if (getNextPlayer().isPlaying()) { getNextPlayer().stop(); } if (listener != null) { @@ -186,9 +186,7 @@ public class LiveExoPlayerManager { public void onPlayerError(@NonNull PlaybackException error) { Player.Listener.super.onPlayerError(error); error.printStackTrace(); - String url=LiveExoPlayerManager.this.url; - LiveExoPlayerManager.this.url=null; - startUrl(url); + replay(); } }); @@ -227,7 +225,7 @@ public class LiveExoPlayerManager { //ToastUtil.show(String.format(Locale.CHINA, "从加载到播放 = %.3f,最大耗时 = %.3f", tmp, log_buffer_max_time)); log_buffer_time = -1; status = MODEL_PLAY2; - if(getNextPlayer().isPlaying()){ + if (getNextPlayer().isPlaying()) { getNextPlayer().stop(); } isSwitchUrl = false; @@ -251,13 +249,12 @@ public class LiveExoPlayerManager { Player.Listener.super.onIsLoadingChanged(isLoading); Log.i(TAG, "onIsLoadingChanged: 2 " + isLoading); } + @Override public void onPlayerError(@NonNull PlaybackException error) { Player.Listener.super.onPlayerError(error); error.printStackTrace(); - String url=LiveExoPlayerManager.this.url; - LiveExoPlayerManager.this.url=null; - startUrl(url); + replay(); } }); } @@ -268,7 +265,7 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void startUrl(String url) { - if (url!=null&&url.equals(this.url)) return; + if (url != null && url.equals(this.url)) return; Log.i(TAG, "startUrl: " + url + " > " + mainView.getResizeMode()); this.url = url; isSwitchUrl = true; @@ -289,7 +286,7 @@ public class LiveExoPlayerManager { * @param url 地址 */ public void switchUrl(String url) { - if (url!=null&&url.equals(this.url)) return; + if (url != null && url.equals(this.url)) return; Log.i(TAG, "switchUrl: " + url + " src : " + this.url); this.url = url; playBufferIndex = 0; @@ -338,9 +335,10 @@ public class LiveExoPlayerManager { public void play() { getNowPlayer().play(); } - public void replay(){ - String tmp=url; - url=null; + + public void replay() { + String tmp = url; + url = null; startUrl(tmp); } diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 7459fd7e0..eb5c6102c 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -80,7 +80,9 @@ import cn.rongcloud.rtc.base.RCRTCMediaType; import cn.rongcloud.rtc.base.RCRTCParamsType; import cn.rongcloud.rtc.base.RCRTCRemoteVideoFrame; import cn.rongcloud.rtc.base.RCRTCRoomType; +import cn.rongcloud.rtc.base.RCRTCStreamType; import cn.rongcloud.rtc.base.RTCErrorCode; +import cn.rongcloud.rtc.center.stream.RCRTCAudioInputStreamImpl; public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @@ -342,7 +344,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void switchStreamPk(boolean isPk) { super.switchStreamPk(isPk); Log.i(TAG, "switchStreamPk: isPk1" + isPk + " tmp = " + !tmpPk + " isPk2 = " + this.isPk); - if(this.isPk&&tmpPk)return; + if (this.isPk && tmpPk) return; if (isPk && !tmpPk || this.isPk) { mPlayer.setViewResizeMode(false); String url; @@ -1031,6 +1033,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { if (userinputStreamList1.size() == 0) { //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 RCRTCVideoView remoteView = new RCRTCVideoView(contexts); + ((RCRTCVideoInputStream) stream).setStreamType(RCRTCStreamType.NORMAL); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); ((RCRTCVideoInputStream) stream).setVideoFrameListener(new IRCRTCVideoInputFrameListener() { @Override @@ -1040,7 +1043,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { "timestampNs:" + videoFrame.getTimestampNs() + "\n" + "分辨率:" + videoFrame.getBuffer().getHeight() + "x" + videoFrame.getBuffer().getWidth() + "\n" + "当前时间:" + new SimpleDateFormat("HH:mm:ss", Locale.CHINA).format(new Date()) + "\n"; - System.out.println("debugText = " + debugText); + Log.d("ry", "onFrame: " + debugText); new Handler(Looper.getMainLooper()).post(() -> { debugView.setText(debugText); From 1244010c3d13c84e9d59d775171c8c003447f9d3 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Wed, 11 Jan 2023 17:19:37 +0800 Subject: [PATCH 090/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=95=B4=E8=9B=8A?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=87=91=E5=B8=81=E6=80=BB=E6=98=AF=E4=B8=BA?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC1000?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/dialog/LivePrankDialogFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/live/src/main/java/com/yunbao/live/dialog/LivePrankDialogFragment.java b/live/src/main/java/com/yunbao/live/dialog/LivePrankDialogFragment.java index ee39ac0c3..d3e63b0d5 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LivePrankDialogFragment.java +++ b/live/src/main/java/com/yunbao/live/dialog/LivePrankDialogFragment.java @@ -217,6 +217,7 @@ public class LivePrankDialogFragment extends AbsDialogFragment implements View.O @Override public void onSuccess(PrankHttpTurntableBean data) { setDate(data); + mCoinTextView.setText(data.getCoin()+""); } @Override From 5f2dda021a5a21e666837cd18a8b1dec922aede5 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Wed, 11 Jan 2023 18:06:51 +0800 Subject: [PATCH 091/118] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E7=BC=93=E5=86=B2=E8=B6=85=E8=BF=872?= =?UTF-8?q?=E7=A7=92=E5=B0=B1=E5=88=B7=E6=96=B0=E6=92=AD=E6=94=BE=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/live/utils/LiveExoPlayerManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 59292afa7..8abbd82ab 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -46,8 +46,8 @@ public class LiveExoPlayerManager { 150, 200) .build(); - player1 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); - player2 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); + player1 = new ExoPlayer.Builder(mContext).build(); + player2 = new ExoPlayer.Builder(mContext).build(); player1.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); player2.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); @@ -115,6 +115,7 @@ public class LiveExoPlayerManager { public void run() { playBufferIndex = 0; listener.onPlaybackStateChanged(Player.STATE_BUFFERING); + replay(); } }; @@ -134,7 +135,7 @@ public class LiveExoPlayerManager { } else if (playbackState == Player.STATE_BUFFERING && status == MODEL_PLAY1 && !isSwitchUrl) { if (listener != null) { if (playBufferIndex++ == 0) { - handler.postDelayed(buffRunnable, 1000); + handler.postDelayed(buffRunnable, 2000); } } } @@ -205,7 +206,7 @@ public class LiveExoPlayerManager { } else if (playbackState == Player.STATE_BUFFERING && status == MODEL_PLAY2 && !isSwitchUrl) { if (listener != null) { if (playBufferIndex++ == 0) { - handler.postDelayed(buffRunnable, 1000); + handler.postDelayed(buffRunnable, 2000); } } } @@ -337,6 +338,7 @@ public class LiveExoPlayerManager { } public void replay() { + Log.i(TAG, "replay: 重载播放"); String tmp = url; url = null; startUrl(tmp); From 9acbc60db26c5c22918d6bc0fa50c6c7f7baccc2 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 12 Jan 2023 11:05:24 +0800 Subject: [PATCH 092/118] =?UTF-8?q?=E9=9A=8F=E6=9C=BAPK=E6=96=87=E6=A1=88?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E3=80=90120=E5=88=86=E9=92=9F=E3=80=91?= =?UTF-8?q?=E2=86=92=E3=80=9010=E5=88=86=E9=92=9F=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index c599c1e39..7c2a2c88b 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -1170,7 +1170,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { new DialogUitl.Builder(mContext) .setHtmlCode(Html.fromHtml( "有人向您发起PK请求。
" + - "若拒绝PK,将会120分钟内不会再收到任何随机PK请求。" + "若拒绝PK,将会10分钟内不会再收到任何随机PK请求。" )) .setConfrimString("接受") .setCancelString("拒絕") @@ -1214,7 +1214,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { titleVal = "拒絕PK提示"; ((TextView) context).setText(Html.fromHtml( "若拒絕PK,將會關閉你的隨機PK開關。
" + - "並且120分鍾不會收到任何隨機PK請求。
" + "並且10分鍾不會收到任何隨機PK請求。" )); ((TextView) cancelBtn).setText("堅持拒絕"); clickCancel = true; From c21df55c0652cf8174e1c7f9445d7742a27cfbb9 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Thu, 12 Jan 2023 11:15:47 +0800 Subject: [PATCH 093/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E5=85=A8?= =?UTF-8?q?=E6=9C=8D=E7=A4=BC=E7=89=A9=E9=80=9A=E7=9F=A5=EF=BC=8C=E7=82=B9?= =?UTF-8?q?=E5=9B=B4=E8=A7=82=E6=97=A0=E5=8F=8D=E5=BA=94=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 10 +++++----- .../live/presenter/LiveGiftAnimPresenter.java | 13 ++++++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/config.gradle b/config.gradle index b123cc49e..dde86129b 100644 --- a/config.gradle +++ b/config.gradle @@ -4,15 +4,15 @@ ext { buildToolsVersion: "29.0.2", minSdkVersion : 21, targetSdkVersion : 31, - versionCode : 402, - versionName : "6.4.7" + versionCode : 405, + versionName : "6.4.8" ] manifestPlaceholders = [ //正式 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", // -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", @@ -27,6 +27,6 @@ ext { // true表示谷歌支付 false isGooglePlay : true, //是否上报异常日志 - isUploadLog : false + isUploadLog : true ] } \ No newline at end of file diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveGiftAnimPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveGiftAnimPresenter.java index 9033417f5..bcf3c4ddc 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveGiftAnimPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveGiftAnimPresenter.java @@ -47,6 +47,7 @@ import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.GiftCacheUtil; import com.yunbao.common.utils.HtmlTagHandler; import com.yunbao.common.utils.L; +import com.yunbao.common.utils.MicStatusManager; import com.yunbao.common.utils.RouteUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.WordUtil; @@ -55,6 +56,7 @@ import com.yunbao.live.bean.LiveGiftPrizePoolWinBean; import com.yunbao.live.bean.LiveLuckGiftWinBean; import com.yunbao.live.bean.LiveReceiveGiftBean; import com.yunbao.live.custom.FrameImageView; +import com.yunbao.live.event.LiveRoomChangeEvent; import com.yunbao.live.http.LiveHttpUtil; import com.yunbao.live.utils.AllMsgTextRender; import com.yunbao.live.utils.LiveIconUtil; @@ -63,6 +65,8 @@ import com.yunbao.live.views.LiveGiftPrizePoolViewHolder; import com.yunbao.live.views.LiveGiftViewHolder; import com.yunbao.live.views.LiveTitleAnimViewHolder; +import org.greenrobot.eventbus.EventBus; + import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -378,7 +382,14 @@ public class LiveGiftAnimPresenter { new LiveRoomCheckLivePresenter(mContext, liveBean.getUid(), liveBean.getStream(), new LiveRoomCheckLivePresenter.NewActionListener() { @Override public void onLiveRoomChanged(String liveUid, String stream, int liveType, String liveTypeVal, String liveSdk) { - RouteUtil.forwardLiveAudienceActivity(liveBean, liveType, Integer.parseInt(liveSdk), Integer.parseInt(liveTypeVal)); + if (liveBean == null) { + return; + } + if (MicStatusManager.getInstance().isMic(liveUid)) { + MicStatusManager.getInstance().showDownMicDialog(mContext); + return; + } + EventBus.getDefault().post(new LiveRoomChangeEvent(liveBean, liveType, Integer.parseInt(liveTypeVal)).setLiveEnd(true)); } @Override From 731f941298fc1beb72cdc298fa46c1d04e0a2384 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 12 Jan 2023 13:39:18 +0800 Subject: [PATCH 094/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B9=B8=E8=BF=90?= =?UTF-8?q?=E7=99=BE=E5=88=86=E7=99=BE=E6=B4=BB=E5=8A=A8=E5=9C=A8=E8=8B=B1?= =?UTF-8?q?=E6=96=87=E7=B3=BB=E7=BB=9F=E4=B8=8B=E4=BC=9A=E9=97=AA=E9=80=80?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=91=A2=EF=BC=88=E5=AD=97=E7=AC=A6=E4=B8=B2?= =?UTF-8?q?=E8=BD=AC=E4=B9=89=E9=97=AE=E9=A2=98=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/src/main/res/values-en/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/res/values-en/strings.xml b/common/src/main/res/values-en/strings.xml index 102cc792e..2bcde64f0 100644 --- a/common/src/main/res/values-en/strings.xml +++ b/common/src/main/res/values-en/strings.xml @@ -939,7 +939,7 @@ Limited ride And limited avatar frame In a batch Chat Congratulations %s have won %s in the Lucky Angel! The next lucky angel will be you! - Congratulations on %s winning %s in Luck 100 %! Go pass on the good luck! + Congratulations on %s winning %s in Luck 100 %%! Go pass on the good luck! Guardian group %s people receive To complete From 49bd97f646e7447d6b326de96f8488e49ee08510 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Thu, 12 Jan 2023 15:09:48 +0800 Subject: [PATCH 095/118] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E5=88=86=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.gradle b/config.gradle index dde86129b..66e026ffe 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 -// serverHost : "https://napi.yaoulive.com", + serverHost : "https://napi.yaoulive.com", // - serverHost : "https://ceshi.yaoulive.com", +// serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", @@ -25,7 +25,7 @@ ext { baiduAppSecretKey: "nEVSgmuGpU0pjPr6VleEGGAl0hzGW52S", // true表示谷歌支付 false - isGooglePlay : true, + isGooglePlay : false, //是否上报异常日志 isUploadLog : true ] From e932238fc2a8aeb11ef28d367d4bba39943abda4 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Fri, 13 Jan 2023 09:46:06 +0800 Subject: [PATCH 096/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8DGoogleFragment.java?= =?UTF-8?q?=E7=9A=84url=E4=B8=BA=E7=A9=BA=E5=AF=BC=E8=87=B4=E5=9C=A8?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E6=97=A5=E5=BF=97=E6=97=B6=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E7=9A=84=E7=A9=BA=E6=8C=87=E9=92=88=E9=97=AA=E9=80=80=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/main/activity/GoogleFragment.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/main/src/main/java/com/yunbao/main/activity/GoogleFragment.java b/main/src/main/java/com/yunbao/main/activity/GoogleFragment.java index 7ca8599cc..62d937191 100644 --- a/main/src/main/java/com/yunbao/main/activity/GoogleFragment.java +++ b/main/src/main/java/com/yunbao/main/activity/GoogleFragment.java @@ -24,6 +24,7 @@ import com.yunbao.common.CommonAppConfig; import com.yunbao.common.http.CommonHttpUtil; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.utils.GoogleBillingUtilNew; +import com.yunbao.common.utils.StringUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.main.R; import com.yunbao.main.views.TestWebViewClient; @@ -55,6 +56,10 @@ public class GoogleFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //通过参数中的布局填充获取对应布局 view = inflater.inflate(R.layout.activity_recharge, container, false); + if(StringUtil.isEmpty(url)){ + Log.e(TAG, "URL为空" ); + return view; + } rlWebview = (WebView) view.findViewById(R.id.rlWebview); Log.e("ttt", url); rlWebview.loadUrl(url); From 3de9ff57c30650a14b19bf8bbabc32134645445f Mon Sep 17 00:00:00 2001 From: 18142669586 <1669783059@qq.com> Date: Fri, 13 Jan 2023 17:36:06 +0800 Subject: [PATCH 097/118] =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=89=93=E4=B8=8D=E5=BC=80=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/src/main/res/layout/activity_webview.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/res/layout/activity_webview.xml b/common/src/main/res/layout/activity_webview.xml index da9a6f211..0f10ea7e6 100644 --- a/common/src/main/res/layout/activity_webview.xml +++ b/common/src/main/res/layout/activity_webview.xml @@ -67,5 +67,5 @@ + android:layout_height="match_parent" /> \ No newline at end of file From 1bbab7ac9e960537e7a4c35849115076267bfb5f Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sat, 14 Jan 2023 13:19:23 +0800 Subject: [PATCH 098/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=BB=91=E5=8A=A8?= =?UTF-8?q?=E7=9B=B4=E6=92=AD=E9=97=B4=E5=88=B0=E5=90=8C=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E4=B8=BB=E6=92=AD=E6=97=B6=EF=BC=8C=E4=BC=9A=E9=BB=91=E5=B1=8F?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/utils/LiveExoPlayerManager.java | 9 +++++++-- .../java/com/yunbao/live/views/LivePlayRyViewHolder.java | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 8abbd82ab..d074070ee 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -40,9 +40,9 @@ public class LiveExoPlayerManager { public LiveExoPlayerManager(Context mContext) { DefaultLoadControl control = new DefaultLoadControl.Builder() .setPrioritizeTimeOverSizeThresholds(false) - .setBackBuffer(120_000, true) + .setBackBuffer(10_000, true) .setBufferDurationsMs(500, - 60_000, + 5_000, 150, 200) .build(); @@ -328,6 +328,7 @@ public class LiveExoPlayerManager { */ public void stop() { getNowPlayer().stop(); + clearUrl(); } /** @@ -355,9 +356,13 @@ public class LiveExoPlayerManager { * 释放播放器 */ public void release() { + Log.i(TAG, "release: 释放播放器"); player1.release(); player2.release(); } + public void clearUrl(){ + url=""; + } public String getUrl() { if (url == null) { diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index eb5c6102c..271bdc723 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -302,6 +302,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } if (mPlayer.isPlaying()) { mPlayer.stop(); + mPlayer.clearUrl(); } mPlayer.startUrl(url); purl = url; From 5d7cff6707c2adb767528718d381741a3c103da3 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sat, 14 Jan 2023 14:30:34 +0800 Subject: [PATCH 099/118] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E5=99=A8=EF=BC=8C=E6=92=AD=E6=94=BE=E5=90=8E?= =?UTF-8?q?10=E7=A7=92=E6=9C=AA=E6=92=AD=E6=94=BE=E5=B0=B1=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E5=8A=A0=E8=BD=BD=E6=92=AD=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/utils/LiveExoPlayerManager.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index d074070ee..bbcddb532 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -46,8 +46,8 @@ public class LiveExoPlayerManager { 150, 200) .build(); - player1 = new ExoPlayer.Builder(mContext).build(); - player2 = new ExoPlayer.Builder(mContext).build(); + player1 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); + player2 = new ExoPlayer.Builder(mContext).setLoadControl(control).build(); player1.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); player2.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); @@ -158,6 +158,7 @@ public class LiveExoPlayerManager { mainView.setPlayer(player1); status = MODEL_PLAY1; isSwitchUrl = false; + handler.removeCallbacks(buffRunnable); if (getNextPlayer().isPlaying()) { getNextPlayer().stop(); } @@ -229,6 +230,7 @@ public class LiveExoPlayerManager { if (getNextPlayer().isPlaying()) { getNextPlayer().stop(); } + handler.removeCallbacks(buffRunnable); isSwitchUrl = false; if (listener != null) { listener.onIsPlayingChanged(true); @@ -268,6 +270,7 @@ public class LiveExoPlayerManager { public void startUrl(String url) { if (url != null && url.equals(this.url)) return; Log.i(TAG, "startUrl: " + url + " > " + mainView.getResizeMode()); + handler.removeCallbacks(buffRunnable); this.url = url; isSwitchUrl = true; playBufferIndex = 0; @@ -279,6 +282,7 @@ public class LiveExoPlayerManager { getNowPlayer().setMediaItem(createMediaItem(url)); getNowPlayer().prepare(); getNowPlayer().play(); + handler.postDelayed(buffRunnable, 10000); } /** @@ -340,6 +344,8 @@ public class LiveExoPlayerManager { public void replay() { Log.i(TAG, "replay: 重载播放"); + getNowPlayer().stop(); + getNextPlayer().stop(); String tmp = url; url = null; startUrl(tmp); @@ -360,8 +366,9 @@ public class LiveExoPlayerManager { player1.release(); player2.release(); } - public void clearUrl(){ - url=""; + + public void clearUrl() { + url = ""; } public String getUrl() { From 543336af99b5ecafea4c620921f5850055259e55 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sat, 14 Jan 2023 14:51:59 +0800 Subject: [PATCH 100/118] =?UTF-8?q?=E7=9B=B4=E6=92=AD=E9=97=B4loading?= =?UTF-8?q?=E5=8A=A8=E7=94=BB=E4=BB=8E10=E7=A7=92=E6=94=B9=E6=88=9015?= =?UTF-8?q?=E7=A7=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/utils/LiveExoPlayerManager.java | 2 ++ .../main/java/com/yunbao/live/views/PortraitLiveManager.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index bbcddb532..9947f25be 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -365,10 +365,12 @@ public class LiveExoPlayerManager { Log.i(TAG, "release: 释放播放器"); player1.release(); player2.release(); + handler.removeCallbacks(buffRunnable); } public void clearUrl() { url = ""; + handler.removeCallbacks(buffRunnable); } public String getUrl() { diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 76bfa27d3..0bf2b0b5d 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -605,7 +605,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRoomViewHolder.showPrizePoolLevel(String.valueOf(giftPrizePoolLevel)); } } - liveHandler.postDelayed(loadRunnableGone, 10_000); + liveHandler.postDelayed(loadRunnableGone, 15_000); } From 911869ed9f0489404e21d3325017a64c80da1c65 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 15 Jan 2023 09:56:51 +0800 Subject: [PATCH 101/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E3=80=90=E4=B8=BA=E4=BD=A0=E6=8E=A8=E8=8D=90=E3=80=91=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=E8=BF=9B=E5=85=A5=E7=9B=B4=E6=92=AD=E9=97=B4=E4=BC=9A?= =?UTF-8?q?=E6=9C=89=E4=B8=8A=E4=B8=AA=E7=9B=B4=E6=92=AD=E9=97=B4=E6=AE=8B?= =?UTF-8?q?=E7=95=99=E7=94=BB=E9=9D=A2=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/utils/LiveExoPlayerManager.java | 42 +++++++++++++++---- .../live/views/LivePlayRyViewHolder.java | 23 +++++++++- .../live/views/PortraitLiveManager.java | 1 + 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java index 9947f25be..ae558dcdf 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveExoPlayerManager.java @@ -4,6 +4,8 @@ import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; +import android.view.ViewGroup; +import android.widget.RelativeLayout; import androidx.annotation.NonNull; @@ -25,8 +27,8 @@ import com.google.android.exoplayer2.video.VideoSize; public class LiveExoPlayerManager { private final int MODEL_PLAY1 = 0;//当前主播放器 private final int MODEL_PLAY2 = 1;//当前子播放器 - private final ExoPlayer player1; - private final ExoPlayer player2; + private ExoPlayer player1; + private ExoPlayer player2; private StyledPlayerView mainView;//渲染视图 private int status = MODEL_PLAY1; private Player.Listener listener; @@ -324,14 +326,19 @@ public class LiveExoPlayerManager { * 是否正在播放 */ public boolean isPlaying() { - return getNowPlayer().isPlaying(); + if (getNowPlayer() != null) { + return getNowPlayer().isPlaying(); + } + return false; } /** * 停止播放 */ public void stop() { - getNowPlayer().stop(); + if (getNowPlayer() != null) { + getNowPlayer().stop(); + } clearUrl(); } @@ -344,8 +351,12 @@ public class LiveExoPlayerManager { public void replay() { Log.i(TAG, "replay: 重载播放"); - getNowPlayer().stop(); - getNextPlayer().stop(); + if (getNowPlayer() != null) { + getNowPlayer().stop(); + } + if (getNextPlayer() != null) { + getNextPlayer().stop(); + } String tmp = url; url = null; startUrl(tmp); @@ -363,8 +374,23 @@ public class LiveExoPlayerManager { */ public void release() { Log.i(TAG, "release: 释放播放器"); - player1.release(); - player2.release(); + if (player1 != null) { + player1.clearVideoSurface(); + player1.release(); + } + if (player2 != null) { + player2.clearVideoSurface(); + player2.release(); + } + player1 = null; + player2 = null; + mainView.setKeepContentOnPlayerReset(false); + mainView.setPlayer(null); + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mainView.getLayoutParams(); + layoutParams.height = RelativeLayout.LayoutParams.WRAP_CONTENT; + mainView.setLayoutParams(layoutParams); + mainView.removeAllViews(); + mainView.requestLayout(); handler.removeCallbacks(buffRunnable); } diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 271bdc723..802f1cd20 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -103,8 +103,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { private boolean mPausedPlay;//是否被动暂停了播放 public int landscape; //1h 2s - public static Context contexts; - public static FrameLayout ry_view; + public Context contexts; + public FrameLayout ry_view; private static final int VIDEO_VERTICAL = 2; private static final int VIDEO_HORIZONTAL = 1; @@ -138,6 +138,7 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @Override public void init() { + Log.i(TAG, "init: 初始化播放器ViewHolder"); EventBus.getDefault().register(this); Bus.getOn(this); mRoot = (ViewGroup) findViewById(R.id.root); @@ -376,6 +377,24 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { public void clearFrame() { super.clearFrame(); mPlayer.clearFrame(); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mVideoView.getLayoutParams(); + params.height = ViewGroup.LayoutParams.WRAP_CONTENT; + params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params.addRule(RelativeLayout.ALIGN_TOP); + mVideoView.setLayoutParams(params); + mVideoView.requestLayout(); + + RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) ry_view.getLayoutParams(); + params1.height = ViewGroup.LayoutParams.WRAP_CONTENT; + params1.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); + params1.addRule(RelativeLayout.ALIGN_TOP); + ry_view.setLayoutParams(params1); + ry_view.requestLayout(); + RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) mCover.getLayoutParams(); + params2.height = DpUtil.dp2px(270); + params2.topMargin = DpUtil.dp2px(120); + mCover.setLayoutParams(params2); + mCover.requestLayout(); } @Override diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 0bf2b0b5d..a2d2f7704 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -314,6 +314,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe ImgLoader.displayBlurLive(mContext, mLiveBean.getAvatar(), liveBack, 400, 600); mask.setVisibility(View.VISIBLE); + mLivePlayViewHolder.clearFrame(); mLivePlayViewHolder.setLiveBean(mLiveBean); mLivePlayViewHolder.setCover(mLiveBean.getAvatar()); mLivePlayViewHolder.setLiveBeanLandscape(mLiveBean.getLandscape()); From 944d703e36363f86db443c345961f7066b0c1c57 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 29 Jan 2023 09:49:04 +0800 Subject: [PATCH 102/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8DUserBean=E7=9A=84is?= =?UTF-8?q?=5Fbind=E4=B8=BA=E7=A9=BA=E5=AF=BC=E8=87=B4=E3=80=90=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E8=B5=84=E6=96=99=E3=80=91=E6=97=B6=E9=97=AA=E9=80=80?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/src/main/java/com/yunbao/common/bean/UserBean.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/src/main/java/com/yunbao/common/bean/UserBean.java b/common/src/main/java/com/yunbao/common/bean/UserBean.java index 0134c53a5..8294e97ff 100644 --- a/common/src/main/java/com/yunbao/common/bean/UserBean.java +++ b/common/src/main/java/com/yunbao/common/bean/UserBean.java @@ -6,6 +6,7 @@ import android.text.TextUtils; import com.alibaba.fastjson.annotation.JSONField; import com.google.gson.annotations.SerializedName; +import com.yunbao.common.utils.StringUtil; /** * Created by cxf on 2017/8/14. @@ -116,6 +117,9 @@ public class UserBean implements Parcelable { } public String getIs_bind() { + if(StringUtil.isEmpty(is_bind)){ + is_bind="0"; + } return is_bind; } From 80fe5271f6389a09298e35cd67fa6d4d378e03d6 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 29 Jan 2023 09:52:01 +0800 Subject: [PATCH 103/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8DUserBean=E7=9A=84is?= =?UTF-8?q?=5Fbind=E4=B8=BA=E7=A9=BA=E5=AF=BC=E8=87=B4=E3=80=90=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E8=B5=84=E6=96=99=E3=80=91=E6=97=B6=E9=97=AA=E9=80=80?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/main/activity/EditProfileActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/src/main/java/com/yunbao/main/activity/EditProfileActivity.java b/main/src/main/java/com/yunbao/main/activity/EditProfileActivity.java index 144b9b490..bb00765df 100644 --- a/main/src/main/java/com/yunbao/main/activity/EditProfileActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/EditProfileActivity.java @@ -466,7 +466,7 @@ public class EditProfileActivity extends AbsActivity { MainHttpUtil.getBaseInfo(new CommonCallback() { @Override public void callback(UserBean u) { - if ("1".equals(u.getIs_bind())) { + if (u != null &&"1".equals(u.getIs_bind())) { tv_bind_phone.setText(""); isBind = "1"; mobile = u.getMobile(); From b82c87d5d601504526d72ee1c2536fc93805ba22 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 29 Jan 2023 10:12:05 +0800 Subject: [PATCH 104/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=90=8D=E7=89=87=E6=B8=B2=E6=9F=93=E7=94=A8=E6=88=B7=E7=AD=89?= =?UTF-8?q?=E7=BA=A7=E6=97=B6=E6=89=80=E4=BD=BF=E7=94=A8=E7=9A=84Activity?= =?UTF-8?q?=E8=A2=AB=E9=94=80=E6=AF=81=E5=AF=BC=E8=87=B4=E7=9A=84=E9=97=AA?= =?UTF-8?q?=E9=80=80=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/yunbao/live/utils/LiveTextRender.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/live/src/main/java/com/yunbao/live/utils/LiveTextRender.java b/live/src/main/java/com/yunbao/live/utils/LiveTextRender.java index ba96ab4b9..da83aca91 100644 --- a/live/src/main/java/com/yunbao/live/utils/LiveTextRender.java +++ b/live/src/main/java/com/yunbao/live/utils/LiveTextRender.java @@ -1,5 +1,6 @@ package com.yunbao.live.utils; +import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -424,6 +425,11 @@ public class LiveTextRender { */ public void getLevelImage(Context mContext, int userLevel, ImgLoader.DrawableCallback callback) { mCallback = callback; + if(mContext instanceof Activity){ + if(((Activity)mContext).isDestroyed()){ + mContext=CommonAppContext.getTopActivity(); + } + } List models = new NewLevelManager(mContext).getNewLevelModels(); String imgUrl = "https://downs.yaoulive.com/level/user_lv1_bg.png"; for (NewLevelModel newLevelModel : models) { From bc0e698a77790187f783b9471d45013f469adec0 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 29 Jan 2023 10:41:48 +0800 Subject: [PATCH 105/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E3=80=90=E6=88=91?= =?UTF-8?q?=E7=9A=84=E3=80=91UserBean.getSlide=E5=8F=AF=E8=83=BD=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E5=AF=BC=E8=87=B4=E7=9A=84=E9=97=AA=E9=80=80=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/main/views/MainMeViewHolder.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java b/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java index 4d8c38d39..fb8f59241 100644 --- a/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java +++ b/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java @@ -42,6 +42,7 @@ import com.yunbao.common.interfaces.OnItemClickListener; import com.yunbao.common.manager.APKManager; import com.yunbao.common.utils.RouteUtil; import com.yunbao.common.utils.SVGAViewUtils; +import com.yunbao.common.utils.StringUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.views.AbsMainViewHolder; import com.yunbao.common.views.weight.ViewClicksAntiShake; @@ -282,10 +283,8 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi private void showData(UserBean u, List list) { mBannerList.clear(); mBannerListNew.clear(); - if (!u.getSlide().equals("") && u.getSlide() != null) { + if (!StringUtil.isEmpty(u.getSlide())) { mBannerListNew.addAll(JSON.parseArray(u.getSlide(), SlideBean.class)); - } - if (!u.getSlide().equals("") && null != u.getSlide()) { for (SlideBean bean : mBannerListNew) { if (bean.getSlide_status().equals("1")) { mBannerList.add(bean); From e108494bd5652ae61ff6d3e12d628eacd7ebcf05 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 29 Jan 2023 10:43:36 +0800 Subject: [PATCH 106/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=9C=AA=E8=AF=BB=E6=B6=88=E6=81=AF=E6=97=B6?= =?UTF-8?q?userInfo=E4=B8=BA=E7=A9=BA=E5=AF=BC=E8=87=B4=E7=9A=84=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E4=B8=8D=E5=88=B0uid=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E9=97=AA=E9=80=80=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/manager/imrongcloud/MessageIMManager.java | 3 +++ 1 file changed, 3 insertions(+) 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 b95bb4e37..734cae4ce 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 @@ -98,6 +98,9 @@ public class MessageIMManager { public void getSystemMessages() { systemNumber = 0; IMLoginModel userInfo = IMLoginManager.get(mContext).getUserInfo(); + if (userInfo == null) { + return; + } HttpClient.getInstance().get("Message.getLists", "getImUserInfo") .params("uid", userInfo.getId()) .params("token", userInfo.getToken()) From c1aeaa0e1bb1ec76c3522e67885ad8813cff5180 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 29 Jan 2023 10:55:54 +0800 Subject: [PATCH 107/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8DLiveGiftDialogFragmen?= =?UTF-8?q?t=E4=B8=80=E5=A4=84=E7=A9=BA=E6=8C=87=E9=92=88=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/dialog/LiveGiftDialogFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/dialog/LiveGiftDialogFragment.java b/live/src/main/java/com/yunbao/live/dialog/LiveGiftDialogFragment.java index c0d56f7ae..4366e4bd6 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LiveGiftDialogFragment.java +++ b/live/src/main/java/com/yunbao/live/dialog/LiveGiftDialogFragment.java @@ -208,7 +208,7 @@ public class LiveGiftDialogFragment extends AbsDialogFragment implements View.On @Override public void onPageSelected(int position) { - if (mRadioGroup != null) { + if (mRadioGroup != null && mRadioGroup.getChildAt(position)!=null) { ((RadioButton) mRadioGroup.getChildAt(position)).setChecked(true); } } From 344bbcdfc8bacaa1470f6acb1e769ebda683a483 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Sun, 29 Jan 2023 16:48:29 +0800 Subject: [PATCH 108/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=8EPC=E7=AB=AF?= =?UTF-8?q?=E8=BF=9E=E9=BA=A6=E7=94=BB=E9=9D=A2=E4=BC=9A=E6=8B=89=E5=8D=87?= =?UTF-8?q?=E6=94=BE=E5=A4=A7=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/live/views/LivePlayRyViewHolder.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 802f1cd20..91d039452 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -83,6 +83,7 @@ import cn.rongcloud.rtc.base.RCRTCRoomType; import cn.rongcloud.rtc.base.RCRTCStreamType; import cn.rongcloud.rtc.base.RTCErrorCode; import cn.rongcloud.rtc.center.stream.RCRTCAudioInputStreamImpl; +import cn.rongcloud.rtc.core.RendererCommon; public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { @@ -891,7 +892,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { RCRTCVideoView remoteView = new RCRTCVideoView(contexts); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 - remoteView.setScalingType(SCALE_ASPECT_FILL); + remoteView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + remoteView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); ry_view.addView(remoteView); Log.e("ry", stream.getMediaType() + "rcrtcOtherRoom成功 :" + data.getLiveStreams().size()); } @@ -1072,7 +1074,8 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { }); //todo 本demo只演示添加1个远端用户的视图 ry_view.removeAllViews(); - remoteView.setScalingType(SCALE_ASPECT_FILL); + remoteView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + remoteView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); ry_view.addView(remoteView); } userinputStreamList1.add(stream); From 1e595ec52696178d6cdf309a15eea0049093c449 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Thu, 2 Feb 2023 15:27:41 +0800 Subject: [PATCH 109/118] =?UTF-8?q?=E4=B8=BB=E6=92=AD=E5=BC=BA=E5=88=B6?= =?UTF-8?q?=E5=85=B3=E6=92=AD=E5=8A=9F=E8=83=BD=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/activity/LiveRyAnchorActivity.java | 6 ++- .../yunbao/live/event/LiveAudienceEvent.java | 43 ++++++++++++++++++- .../yunbao/live/socket/SocketRyClient.java | 7 +++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index 1c07161e5..f7cc06eb6 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -229,7 +229,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl long lossRate = statusBean.packetLostRate; //带宽 String googAvailableSendBandwidth = statusReport.googAvailableSendBandwidth; - Log.e("网速和内存", "获取视频:" +resolution+ " 丢包率:" + lossRate+" 带宽:"+googAvailableSendBandwidth); + Log.e("网速和内存", "获取视频:" + resolution + " 丢包率:" + lossRate + " 带宽:" + googAvailableSendBandwidth); } } }); @@ -1596,6 +1596,10 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl case UPDATA_ROBOT: getAiRobotStatus(); break; + //主播强制下播 + case LIVE_END: + endLive(); + break; } } diff --git a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java index 036bf54ea..49600b5f1 100644 --- a/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java +++ b/live/src/main/java/com/yunbao/live/event/LiveAudienceEvent.java @@ -31,6 +31,46 @@ public class LiveAudienceEvent extends BaseModel { private int time; private CustomFullServiceNotifyEvent customFullServiceNotifyEvent; private LivePKUserListBean livePKUserListBean; + private String votes; + private String length; + private int nums; + private String uname; + + public String getVotes() { + return votes; + } + + public LiveAudienceEvent setVotes(String votes) { + this.votes = votes; + return this; + } + + public String getLength() { + return length; + } + + public LiveAudienceEvent setLength(String length) { + this.length = length; + return this; + } + + public int getNums() { + return nums; + } + + public LiveAudienceEvent setNums(int nums) { + this.nums = nums; + return this; + } + + public String getUname() { + return uname; + } + + public LiveAudienceEvent setUname(String uname) { + this.uname = uname; + return this; + } public LivePKUserListBean getLivePKUserListBean() { return livePKUserListBean; @@ -258,7 +298,8 @@ public class LiveAudienceEvent extends BaseModel { CHANGE_VIEW(52, "更改连胜位置"), UPDATA_ROBOT(53, "更新机器人消息"), LIVE_VIDEO(54, "画质选择"), - LUCKY_100_CHECK(55,"幸运百分百"); + LUCKY_100_CHECK(55, "幸运百分百"), + LIVE_END(56, "主播下播"); private int type; private String name; diff --git a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java index aa8790693..8e436a47b 100644 --- a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java +++ b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java @@ -364,6 +364,13 @@ public class SocketRyClient { } else if (action == 19) { mListener.onAnchorInvalid(); } + //主播强制下播 + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.LIVE_END) + .setVotes(map.getString("votes")) + .setLength(map.getString("length")) + .setNums(map.getIntValue("nums")) + .setUname(map.getString("uname"))); break; case Constants.SOCKET_CHANGE_LIVE://主播切换计时收费类型 mListener.onChangeTimeCharge(map.getIntValue("type_val")); From 3de716053878159be372f9f7b219fd230a92d527 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 3 Feb 2023 16:22:48 +0800 Subject: [PATCH 110/118] =?UTF-8?q?=E4=B8=BB=E6=92=AD=E7=AB=AF=E5=A4=9A?= =?UTF-8?q?=E4=BA=BAPK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/activity/LiveRyAnchorActivity.java | 24 +- .../presenter/LiveRyLinkMicPkPresenter.java | 771 ++++++++++++++---- .../yunbao/live/socket/SocketRyClient.java | 70 +- .../live/views/AbsRyLivePushViewHolder.java | 5 +- .../live/views/LivePushRyViewHolder.java | 29 +- .../live/views/LiveRyAnchorViewHolder.java | 4 +- .../src/main/res/layout/view_live_push_ry.xml | 132 +-- 7 files changed, 777 insertions(+), 258 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index f7cc06eb6..06dd88fe3 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -5,8 +5,6 @@ import static com.tencent.trtc.TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_DISABLE; import static com.tencent.trtc.TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_ENABLE; import static com.yunbao.common.Constants.SOCKET_LIVE_DRPK; import static com.yunbao.common.Constants.SOCKET_LIVE_DRPK_RANDOM; -import static com.yunbao.live.views.AbsRyLivePushViewHolder.mPreView; -import static com.yunbao.live.views.LivePushRyViewHolder.dr_pk_view; import static com.yunbao.live.views.LiveRyAnchorViewHolder.btn_dr_pk_nub; import static com.yunbao.live.views.LiveRyAnchorViewHolder.btn_start_dr_pk; import static com.yunbao.live.views.LiveRyAnchorViewHolder.btn_start_dr_pk_view; @@ -24,7 +22,6 @@ import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.LinearLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -66,11 +63,9 @@ import com.yunbao.common.utils.BitmapUtil; import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DateFormatUtil; import com.yunbao.common.utils.DialogUitl; -import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.L; import com.yunbao.common.utils.LogUtil; import com.yunbao.common.utils.MicStatusManager; -import com.yunbao.common.utils.ScreenDimenUtil; import com.yunbao.common.utils.StringUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.WordUtil; @@ -406,7 +401,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl if (code == 0) { btn_start_dr_pk.setVisibility(View.VISIBLE); - dr_pk_view.setVisibility(View.VISIBLE); +// dr_pk_view.setVisibility(View.VISIBLE); final SocketSendBean msg1 = new SocketSendBean() .param("_method_", SOCKET_LIVE_DRPK) .param("action", 9) @@ -426,18 +421,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl @Override public void onSuccess(Message message) { isDRPK = 1; - btn_start_dr_pk_view.setVisibility(View.VISIBLE); - dr_pk_view.setVisibility(View.VISIBLE); - - ScreenDimenUtil util = ScreenDimenUtil.getInstance(); - int mScreenWdith = util.getScreenWdith(); - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, mScreenWdith * 720 / 960); - params.weight = 1; - params.topMargin = DpUtil.dp2px(123); - dr_pk_view.setLayoutParams(params); - mPreView.setLayoutParams(params); - } @Override @@ -1577,7 +1561,11 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl mLiveRyLinkMicPkPresenter.leaveDRRoom(); } break; - + case LEAVE_PK_SCORE: + if (mLiveRyLinkMicPkPresenter != null) { + mLiveRyLinkMicPkPresenter.upDataPkScore(event.getPkScores(), event.getUid(), event.getTime()); + } + break; case PK_TIME_COUNT: if (mLiveRoomViewHolder != null) { mLiveRoomViewHolder.endDRGif(); diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index 7c2a2c88b..efa31c2e4 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -4,9 +4,7 @@ import static com.lzy.okgo.utils.HttpUtils.runOnUiThread; import static com.yunbao.common.Constants.SOCKET_LINK_MIC_PK; import static com.yunbao.common.Constants.SOCKET_LIVE_DRPK; import static com.yunbao.live.activity.LiveRyAnchorActivity.isDRPK; -import static com.yunbao.live.views.AbsRyLivePushViewHolder.mPreView; import static com.yunbao.live.views.LivePushRyViewHolder.contexts; -import static com.yunbao.live.views.LivePushRyViewHolder.dr_pk_view; import static com.yunbao.live.views.LivePushRyViewHolder.rcrtcLiveInfo; import static com.yunbao.live.views.LivePushRyViewHolder.rtcRoom; import static cn.rongcloud.rtc.core.RendererCommon.ScalingType.SCALE_ASPECT_FILL; @@ -29,20 +27,24 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupWindow; +import android.widget.RelativeLayout; import android.widget.TextView; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.tencent.trtc.TRTCCloud; import com.yunbao.common.CommonAppConfig; +import com.yunbao.common.bean.LiveInfoModel; import com.yunbao.common.bean.UserBean; import com.yunbao.common.event.AnchorInfoEvent; -import com.yunbao.common.event.FollowEvent; +import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.http.live.LiveNetManager; +import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.manager.IMRTCManager; import com.yunbao.common.manager.RandomPkManager; import com.yunbao.common.utils.Bus; @@ -108,6 +110,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { private static final int WHAT_PK_WAIT_RECEIVE = 0;//收到pk申请等待 what private static final int WHAT_PK_WAIT_SEND = 1;//发送pk申请等待 what private static final int WHAT_PK_TIME = 2;//pk时间变化 what + private static final int WHAT_PK_TIME2 = 22;//pk时间变化 what private static final int LINK_MIC_COUNT_MAX = 10; private static int PK_TIME_MAX = 60 * 15;//pk时间 15分钟 private static final int PK_TIME_MAX_2 = 60;//惩罚时间 1分钟 @@ -141,7 +144,14 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { private String mSelfStream; private int mPkTimeFromServer; public static TRTCCloud mTRTCCloud1; + private View detailsView1, detailsView2, detailsView3, detailsView4; + private LinearLayout detailsLinearLayout1, detailsLinearLayout2, detailsLinearLayout3, detailsLinearLayout4; + private LinearLayout linearGrade1, linearGrade2, linearGrade3, linearGrade4; + private TextView textPkName1, textPkName2, textPkName3, textPkName4; + private TextView textGrade1, textGrade2, textGrade3, textGrade4; + private ImageView imageGrade1, imageGrade2, imageGrade3, imageGrade4; + public LivePushRyViewHolder livePushRyViewHolder; public static List inputStreamList = new ArrayList<>(); public static List inputStreamList1 = new ArrayList<>(); @@ -224,6 +234,50 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { case WHAT_PK_TIME: changePkTime(); break; + + } + } + }; + + } + + public LiveRyLinkMicPkPresenter(Context context, LivePushRyViewHolder linkMicViewHolder, boolean isAnchor, View root) { + mContext = context; + mIsAnchor = isAnchor; + mRoot = root; + mPkContainer = linkMicViewHolder.getPkContainer(); + livePushRyViewHolder = linkMicViewHolder; + mPkTimeString1 = ""; + mPkTimeString2 = WordUtil.getString(R.string.live_pk_time_2); + //从本地取数据 + String pkTime = CommonAppConfig.getInstance().getAnchorPkTime(); + if (!pkTime.isEmpty()) { + try { + int time = Integer.parseInt(pkTime) * 60; + if (time > 0) { + PK_TIME_MAX = time; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + Log.d("PK_TIME_MAX", "" + PK_TIME_MAX); + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case WHAT_PK_WAIT_RECEIVE: + onApplyPkWait(); + break; + case WHAT_PK_WAIT_SEND: + onSendPkWait(); + break; + case WHAT_PK_TIME2: + pkCountdownTimer(); + break; + case WHAT_PK_TIME: + changePkTime(); + break; } } }; @@ -313,7 +367,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { if (mLiveLinkMicPkViewHolder != null) { String s = mIsPkEnd ? mPkTimeString2 : mPkTimeString1; String s1 = StringUtil.getDurationText(mPkTimeCount * 1000); - Log.i("tag23333",mPkTimeCount+"mPkTimeCount"+s1+"is"+is); + Log.i("tag23333", mPkTimeCount + "mPkTimeCount" + s1 + "is" + is); if (i == 1 && s1.equals("00:01")) { s1 = "00:00"; i = 0; @@ -324,13 +378,13 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, mScreenWdith * 720 / 960); params.weight = 1; params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); - LivePushRyViewHolder.mPreView.setLayoutParams(params); - LivePushRyViewHolder.mPreView1.setLayoutParams(params); + livePushRyViewHolder.camera.setLayoutParams(params); + livePushRyViewHolder.mPreView1.setLayoutParams(params); } Log.i("tts", s1); mLiveLinkMicPkViewHolder.setTime(s + " " + s1); - if ( s1.equals("00:01") && mIsAnchor && !s.contains("懲罰")) { + if (s1.equals("00:01") && mIsAnchor && !s.contains("懲罰")) { HttpClient.getInstance().get("Livepk.endPK", "Livepk.endPK") .params("uid", CommonAppConfig.getInstance().getUid()) .params("addtime", "00:00") @@ -385,7 +439,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * pk时间倒计时 */ private void changePkTime() { - if (mPkTimeCount<0)return; + if (mPkTimeCount < 0) return; mPkTimeCount--; Log.i("vvvs", "mPkTimeCount:" + mPkTimeCount); if (mPkTimeCount >= 0) {// @@ -490,35 +544,36 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 RCRTCVideoView remoteView = new RCRTCVideoView(mContext); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); + livePushRyViewHolder.mPreView1.setVisibility(View.VISIBLE); //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr1_preview.removeAllViews(); + livePushRyViewHolder.mPreView1.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr1_preview.addView(remoteView); + livePushRyViewHolder.mPreView1.addView(remoteView); } else if (i == 2) { //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 - RCRTCVideoView remoteView = new RCRTCVideoView(mContext); - ((RCRTCVideoInputStream) stream).setVideoView(remoteView); - //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr2_preview.removeAllViews(); - remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr2_preview.addView(remoteView); +// RCRTCVideoView remoteView = new RCRTCVideoView(mContext); +// ((RCRTCVideoInputStream) stream).setVideoView(remoteView); +// //todo 本demo只演示添加1个远端用户的视图 +// LivePushRyViewHolder.dr2_preview.removeAllViews(); +// remoteView.setScalingType(SCALE_ASPECT_FILL); +// LivePushRyViewHolder.dr2_preview.addView(remoteView); } else if (i == 3) { //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 - RCRTCVideoView remoteView = new RCRTCVideoView(mContext); - ((RCRTCVideoInputStream) stream).setVideoView(remoteView); - //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr3_preview.removeAllViews(); - remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr3_preview.addView(remoteView); +// RCRTCVideoView remoteView = new RCRTCVideoView(mContext); +// ((RCRTCVideoInputStream) stream).setVideoView(remoteView); +// //todo 本demo只演示添加1个远端用户的视图 +// LivePushRyViewHolder.dr3_preview.removeAllViews(); +// remoteView.setScalingType(SCALE_ASPECT_FILL); +// LivePushRyViewHolder.dr3_preview.addView(remoteView); } else if (i == 4) { //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 - RCRTCVideoView remoteView = new RCRTCVideoView(mContext); - ((RCRTCVideoInputStream) stream).setVideoView(remoteView); - //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr4_preview.removeAllViews(); - remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr4_preview.addView(remoteView); +// RCRTCVideoView remoteView = new RCRTCVideoView(mContext); +// ((RCRTCVideoInputStream) stream).setVideoView(remoteView); +// //todo 本demo只演示添加1个远端用户的视图 +// LivePushRyViewHolder.dr4_preview.removeAllViews(); +// remoteView.setScalingType(SCALE_ASPECT_FILL); +// LivePushRyViewHolder.dr4_preview.addView(remoteView); } //如果要订阅所有远端用户的流。保存所有流信息,方便后面统一订阅 inputStreamList.add(stream); @@ -647,9 +702,9 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { RCRTCVideoView remoteView = new RCRTCVideoView(contexts); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 -// LivePushRyViewHolder.mPreView1.removeAllViews(); + livePushRyViewHolder.mPreView1.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.mPreView1.addView(remoteView); + livePushRyViewHolder.mPreView1.addView(remoteView); } //如果要订阅所有远端用户的流。保存所有流信息,方便后面统一订阅 inputStreamList.add(stream); @@ -727,9 +782,9 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, mScreenWdith * 720 / 960); params.weight = 1; params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); - LivePushRyViewHolder.mPreView.setLayoutParams(params); - LivePushRyViewHolder.mPreView1.setLayoutParams(params); - LivePushRyViewHolder.mPreView1.setVisibility(View.VISIBLE); + livePushRyViewHolder.camera.setLayoutParams(params); + livePushRyViewHolder.mPreView1.setLayoutParams(params); + livePushRyViewHolder.mPreView1.setVisibility(View.VISIBLE); final SocketSendBean msg1 = new SocketSendBean() .param("_method_", SOCKET_LINK_MIC_PK) @@ -771,9 +826,9 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, mScreenWdith * 720 / 960); params.weight = 1; params.topMargin = mContext.getResources().getDimensionPixelOffset(R.dimen.live_top); - LivePushRyViewHolder.mPreView.setLayoutParams(params); - LivePushRyViewHolder.mPreView1.setLayoutParams(params); - LivePushRyViewHolder.mPreView1.setVisibility(View.VISIBLE); + livePushRyViewHolder.camera.setLayoutParams(params); + livePushRyViewHolder.mPreView1.setLayoutParams(params); + livePushRyViewHolder.mPreView1.setVisibility(View.VISIBLE); LivePushRyViewHolder.btn_close.setVisibility(View.VISIBLE); LiveRyAnchorActivity.isDRPK = 1; @@ -807,9 +862,9 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { RCRTCVideoView remoteView = new RCRTCVideoView(contexts); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 -// LivePushRyViewHolder.mPreView1.removeAllViews(); + livePushRyViewHolder.mPreView1.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.mPreView1.addView(remoteView); + livePushRyViewHolder.mPreView1.addView(remoteView); } //如果要订阅所有远端用户的流。保存所有流信息,方便后面统一订阅 inputStreamList.add(stream); @@ -1070,7 +1125,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { /** * 退出多人PK */ - public static void leaveDRRoom() { + public void leaveDRRoom() { //清理PK上面对方的头像 EventBus.getDefault().post(new AnchorInfoEvent(true, "", "", "")); @@ -1143,26 +1198,32 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { } } - new Handler(Looper.getMainLooper()).post(new Runnable() { - public void run() { - //恢复全屏画面 - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - params.topMargin = 0; - mPreView.setLayoutParams(params); - dr_pk_view.setVisibility(View.GONE); - inputStreamList.clear(); - inputStreamList1.clear(); - //删除之前其他主播的画面 - LivePushRyViewHolder.dr1_preview.removeAllViews(); - LivePushRyViewHolder.dr2_preview.removeAllViews(); - LivePushRyViewHolder.dr3_preview.removeAllViews(); - LivePushRyViewHolder.dr4_preview.removeAllViews(); - } - }); - + leaveHandler.post(leaveRunnable); } + private Handler leaveHandler = new Handler(Looper.getMainLooper()); + private Runnable leaveRunnable = new Runnable() { + @Override + public void run() { + //恢复全屏画面 + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + params.topMargin = 0; + livePushRyViewHolder.camera.setLayoutParams(params); + livePushRyViewHolder.dr_pk_view.setVisibility(View.GONE); + inputStreamList.clear(); + inputStreamList1.clear(); + //删除之前其他主播的画面 + livePushRyViewHolder.dr1_preview.removeAllViews(); + livePushRyViewHolder.dr3_preview.removeAllViews(); + livePushRyViewHolder.cameraPreview3.removeAllViews(); + leaveHandler.removeCallbacks(leaveRunnable); + livePushRyViewHolder.timeTitle.setVisibility(View.GONE); + livePushRyViewHolder.mPreView.removeView(detailsView1); + livePushRyViewHolder.cameraPreview3.setVisibility(View.GONE); + } + }; + /** * 随机PK拒绝对话框 */ @@ -1556,15 +1617,28 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { //把多人PK的View显示出来 - if (dr_pk_view.getVisibility() == View.GONE) { + if (livePushRyViewHolder.dr_pk_view.getVisibility() == View.GONE) { ScreenDimenUtil util = ScreenDimenUtil.getInstance(); int mScreenWdith = util.getScreenWdith(); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, mScreenWdith * 720 / 960); params.weight = 1; params.topMargin = DpUtil.dp2px(123); - dr_pk_view.setLayoutParams(params); - mPreView.setLayoutParams(params); - dr_pk_view.setVisibility(View.VISIBLE); + livePushRyViewHolder.dr_pk_view.setLayoutParams(params); + livePushRyViewHolder.camera.setLayoutParams(params); + livePushRyViewHolder.dr_pk_view.setVisibility(View.VISIBLE); + livePushRyViewHolder.dr1_preview.setVisibility(View.GONE); + livePushRyViewHolder.dr2_preview.setVisibility(View.GONE); + livePushRyViewHolder.dr3_preview.setVisibility(View.GONE); + livePushRyViewHolder.dr4_preview.setVisibility(View.GONE); + detailsView1 = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + detailsLinearLayout1 = detailsView1.findViewById(R.id.lin_pk1); + linearGrade1 = detailsView1.findViewById(R.id.linear_grade1); + imageGrade1 = detailsView1.findViewById(R.id.image_grade1); + textGrade1 = detailsView1.findViewById(R.id.text_grade1); + imageGrade1.setTag(String.valueOf(IMLoginManager.get(mContext).getUserInfo().getId())); + livePushRyViewHolder.mPreView.addView(detailsView1); + detailsLinearLayout1.setVisibility(View.VISIBLE); + linearGrade1.setVisibility(View.GONE); } Log.e("ry", "多人接受成功" + mApplyUid); @@ -1577,37 +1651,99 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { Log.e("ry", i + "收到" + stream.getMediaType() + "实打实打算" + rcrtcOtherRoom.getRemoteUsers().get(i).getUserId()); if (stream.getMediaType() == RCRTCMediaType.VIDEO) { if (inputStreamList.size() == 0) { + livePushRyViewHolder.dr1_preview.setVisibility(View.VISIBLE); //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 - RCRTCVideoView remoteView = new RCRTCVideoView(contexts); + RCRTCVideoView remoteView = new RCRTCVideoView(mContext); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr1_preview.removeAllViews(); + livePushRyViewHolder.dr1_preview.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr1_preview.addView(remoteView); + livePushRyViewHolder.dr1_preview.addView(remoteView); + + + LiveNetManager.get(mContext).getLiveInfo(uid, new com.yunbao.common.http.base.HttpCallback() { + @Override + public void onSuccess(LiveInfoModel data) { + detailsView2 = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + detailsLinearLayout2 = detailsView2.findViewById(R.id.lin_pk2); + linearGrade2 = detailsView2.findViewById(R.id.linear_grade2); + textPkName2 = detailsView2.findViewById(R.id.text_pk_name2); + imageGrade2 = detailsView2.findViewById(R.id.image_grade2); + textGrade2 = detailsView2.findViewById(R.id.text_grade2); + imageGrade2.setTag(String.valueOf(uid)); + textPkName2.setText(data.getUserNicename()); + livePushRyViewHolder.dr1_preview.addView(detailsView2); + detailsLinearLayout2.setVisibility(View.VISIBLE); + linearGrade2.setVisibility(View.GONE); + } + + @Override + public void onError(String error) { + + } + }); + } else if (inputStreamList.size() == 1) { + livePushRyViewHolder.dr3_preview.setVisibility(View.VISIBLE); //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 - RCRTCVideoView remoteView = new RCRTCVideoView(contexts); + RCRTCVideoView remoteView = new RCRTCVideoView(mContext); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr2_preview.removeAllViews(); + livePushRyViewHolder.dr3_preview.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr2_preview.addView(remoteView); + livePushRyViewHolder.dr3_preview.addView(remoteView); + LiveNetManager.get(mContext).getLiveInfo(uid, new com.yunbao.common.http.base.HttpCallback() { + @Override + public void onSuccess(LiveInfoModel data) { + detailsView4 = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + detailsLinearLayout4 = detailsView4.findViewById(R.id.lin_pk4); + linearGrade4 = detailsView4.findViewById(R.id.linear_grade4); + textPkName4 = detailsView4.findViewById(R.id.text_pk_name4); + imageGrade4 = detailsView4.findViewById(R.id.image_grade4); + textGrade4 = detailsView4.findViewById(R.id.text_grade4); + imageGrade4.setTag(uid); + textPkName4.setText(data.getUserNicename()); + livePushRyViewHolder.dr3_preview.addView(detailsView4); + detailsLinearLayout4.setVisibility(View.VISIBLE); + linearGrade4.setVisibility(View.GONE); + } + + @Override + public void onError(String error) { + + } + }); } else if (inputStreamList.size() == 2) { + livePushRyViewHolder.cameraPreview3.setVisibility(View.VISIBLE); //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 - RCRTCVideoView remoteView = new RCRTCVideoView(contexts); + RCRTCVideoView remoteView = new RCRTCVideoView(mContext); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr3_preview.removeAllViews(); + livePushRyViewHolder.cameraPreview3.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr3_preview.addView(remoteView); - } else if (inputStreamList.size() == 3) { - //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 - RCRTCVideoView remoteView = new RCRTCVideoView(contexts); - ((RCRTCVideoInputStream) stream).setVideoView(remoteView); - //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr4_preview.removeAllViews(); - remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr4_preview.addView(remoteView); + livePushRyViewHolder.cameraPreview3.addView(remoteView); + + LiveNetManager.get(mContext).getLiveInfo(uid, new com.yunbao.common.http.base.HttpCallback() { + @Override + public void onSuccess(LiveInfoModel data) { + detailsView3 = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + detailsLinearLayout3 = detailsView3.findViewById(R.id.lin_pk3); + linearGrade3 = detailsView3.findViewById(R.id.linear_grade3); + textPkName3 = detailsView3.findViewById(R.id.text_pk_name3); + imageGrade3 = detailsView3.findViewById(R.id.image_grade3); + textGrade3 = detailsView3.findViewById(R.id.text_grade3); + imageGrade3.setTag(uid); + textPkName3.setText(data.getUserNicename()); + livePushRyViewHolder.cameraPreview3.addView(detailsView3); + detailsLinearLayout3.setVisibility(View.VISIBLE); + linearGrade3.setVisibility(View.GONE); + } + + @Override + public void onError(String error) { + + } + }); } inputStreamList.add(stream); } @@ -1673,6 +1809,31 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { rcrtcOtherRoom.registerOtherRoomEventsListener(otherRoomEventsListener); new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { + + if (livePushRyViewHolder.dr_pk_view.getVisibility() == View.GONE) { + ScreenDimenUtil util = ScreenDimenUtil.getInstance(); + int mScreenWdith = util.getScreenWdith(); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, mScreenWdith * 720 / 960); + params.weight = 1; + params.topMargin = DpUtil.dp2px(123); + livePushRyViewHolder.dr_pk_view.setLayoutParams(params); + livePushRyViewHolder.camera.setLayoutParams(params); + livePushRyViewHolder.dr_pk_view.setVisibility(View.VISIBLE); + livePushRyViewHolder.dr1_preview.setVisibility(View.GONE); + livePushRyViewHolder.dr2_preview.setVisibility(View.GONE); + livePushRyViewHolder.dr3_preview.setVisibility(View.GONE); + livePushRyViewHolder.dr4_preview.setVisibility(View.GONE); + detailsView1 = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + detailsLinearLayout1 = detailsView1.findViewById(R.id.lin_pk1); + linearGrade1 = detailsView1.findViewById(R.id.linear_grade1); + imageGrade1 = detailsView1.findViewById(R.id.image_grade1); + textGrade1 = detailsView1.findViewById(R.id.text_grade1); + imageGrade1.setTag(String.valueOf(IMLoginManager.get(mContext).getUserInfo().getId())); + livePushRyViewHolder.mPreView.addView(detailsView1); + detailsLinearLayout1.setVisibility(View.VISIBLE); + linearGrade1.setVisibility(View.GONE); + } + //遍历远端用户列表 for (int i = 0; i < rcrtcOtherRoom.getRemoteUsers().size(); i++) { //遍历远端用户发布的资源列表 @@ -1680,37 +1841,96 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { Log.e("ry111", stream.getMediaType() + ""); if (stream.getMediaType() == RCRTCMediaType.VIDEO) { if (inputStreamList.size() == 0) { + livePushRyViewHolder.dr1_preview.setVisibility(View.VISIBLE); //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 RCRTCVideoView remoteView = new RCRTCVideoView(contexts); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr1_preview.removeAllViews(); + livePushRyViewHolder.dr1_preview.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr1_preview.addView(remoteView); + livePushRyViewHolder.dr1_preview.addView(remoteView); + LiveNetManager.get(mContext).getLiveInfo(u, new com.yunbao.common.http.base.HttpCallback() { + @Override + public void onSuccess(LiveInfoModel data) { + detailsView2 = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + detailsLinearLayout2 = detailsView2.findViewById(R.id.lin_pk2); + linearGrade2 = detailsView2.findViewById(R.id.linear_grade2); + textPkName2 = detailsView2.findViewById(R.id.text_pk_name2); + imageGrade2 = detailsView2.findViewById(R.id.image_grade2); + textGrade2 = detailsView2.findViewById(R.id.text_grade2); + imageGrade2.setTag(String.valueOf(u)); + textPkName2.setText(data.getUserNicename()); + livePushRyViewHolder.dr1_preview.addView(detailsView2); + detailsLinearLayout2.setVisibility(View.VISIBLE); + linearGrade2.setVisibility(View.GONE); + } + + @Override + public void onError(String error) { + + } + }); } else if (inputStreamList.size() == 1) { + livePushRyViewHolder.dr3_preview.setVisibility(View.VISIBLE); //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 RCRTCVideoView remoteView = new RCRTCVideoView(contexts); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr2_preview.removeAllViews(); + livePushRyViewHolder.dr3_preview.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr2_preview.addView(remoteView); + livePushRyViewHolder.dr3_preview.addView(remoteView); + LiveNetManager.get(mContext).getLiveInfo(u, new com.yunbao.common.http.base.HttpCallback() { + @Override + public void onSuccess(LiveInfoModel data) { + detailsView4 = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + detailsLinearLayout4 = detailsView4.findViewById(R.id.lin_pk4); + linearGrade4 = detailsView4.findViewById(R.id.linear_grade4); + textPkName4 = detailsView4.findViewById(R.id.text_pk_name4); + imageGrade4 = detailsView4.findViewById(R.id.image_grade4); + textGrade4 = detailsView4.findViewById(R.id.text_grade4); + imageGrade4.setTag(u); + textPkName4.setText(data.getUserNicename()); + livePushRyViewHolder.dr3_preview.addView(detailsView4); + detailsLinearLayout4.setVisibility(View.VISIBLE); + linearGrade4.setVisibility(View.GONE); + } + + @Override + public void onError(String error) { + + } + }); } else if (inputStreamList.size() == 2) { + livePushRyViewHolder.cameraPreview3.setVisibility(View.VISIBLE); //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 RCRTCVideoView remoteView = new RCRTCVideoView(contexts); ((RCRTCVideoInputStream) stream).setVideoView(remoteView); //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr3_preview.removeAllViews(); + livePushRyViewHolder.cameraPreview3.removeAllViews(); remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr3_preview.addView(remoteView); - } else if (inputStreamList.size() == 3) { - //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示 - RCRTCVideoView remoteView = new RCRTCVideoView(contexts); - ((RCRTCVideoInputStream) stream).setVideoView(remoteView); - //todo 本demo只演示添加1个远端用户的视图 - LivePushRyViewHolder.dr4_preview.removeAllViews(); - remoteView.setScalingType(SCALE_ASPECT_FILL); - LivePushRyViewHolder.dr4_preview.addView(remoteView); + livePushRyViewHolder.cameraPreview3.addView(remoteView); + + LiveNetManager.get(mContext).getLiveInfo(u, new com.yunbao.common.http.base.HttpCallback() { + @Override + public void onSuccess(LiveInfoModel data) { + detailsView3 = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + detailsLinearLayout3 = detailsView3.findViewById(R.id.lin_pk3); + linearGrade3 = detailsView3.findViewById(R.id.linear_grade3); + textPkName3 = detailsView3.findViewById(R.id.text_pk_name3); + imageGrade3 = detailsView3.findViewById(R.id.image_grade3); + textGrade3 = detailsView3.findViewById(R.id.text_grade3); + imageGrade3.setTag(u); + textPkName3.setText(data.getUserNicename()); + livePushRyViewHolder.cameraPreview3.addView(detailsView3); + detailsLinearLayout3.setVisibility(View.VISIBLE); + linearGrade3.setVisibility(View.GONE); + } + + @Override + public void onError(String error) { + + } + }); } inputStreamList.add(stream); @@ -1770,7 +1990,9 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * @param streams 必须为视频流列表 * @return */ - public static RCRTCMixConfig create_Custom_MixConfig(boolean isCrop, List streams) { + private RCRTCMixConfig create_Custom_MixConfig(boolean isCrop, List streams) { + Log.e("视频合流", streams.toString()); + Log.e("视频合流", "视频长度:" + streams.size()); RCRTCMixConfig config = new RCRTCMixConfig(); //1. 设置自定义合流布局模式 config.setLayoutMode(RCRTCMixConfig.MixLayoutMode.CUSTOM); @@ -1798,62 +2020,92 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { //(请参照画布和声音配置示例代码) //3. 假设以画布设置的宽高为 300 * 300为例(应以真实设置的宽高为准),设置每个视频流小窗口的坐标及宽高 ArrayList list = new ArrayList<>(); - config.setCustomLayouts(list); - //user1的视频流 - RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout1 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); - list.add(videoLayout1); - videoLayout1.setVideoStream(RCRTCEngine.getInstance().getDefaultVideoStream()); // RCRTCStream#MediaType 必须是Video - videoLayout1.setX(0); //X 坐标 - videoLayout1.setY(0); //Y 坐标 - videoLayout1.setWidth(480); // 视频窗口的宽 - videoLayout1.setHeight(720); // 视频窗口的高 - for (int i = 0; i < streams.size(); i++) { - Log.e("tttts,", "a" + i + "cccc" + streams.size()); - Log.e("tttts", streams.get(i).getUserId() + ""); - if (i == 0) { - //user2的视频流 - RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout2 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); - list.add(videoLayout2); - videoLayout2.setVideoStream(streams.get(i)); // RCRTCStream#MediaType 必须是Video - videoLayout2.setX(480); //X 坐标 - videoLayout2.setY(0); //Y 坐标 - videoLayout2.setWidth(240); // 视频窗口的宽 - videoLayout2.setHeight(360); // 视频窗口的高 - Log.e("ttt1112", "0" + "VS" + streams.get(i).getUserId()); - } else if (i == 1) { - //user3的视频流 - RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout3 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); - list.add(videoLayout3); - videoLayout3.setVideoStream(streams.get(i)); // RCRTCStream#MediaType 必须是Video - videoLayout3.setX(720); //X 坐标 - videoLayout3.setY(0); //Y 坐标 - videoLayout3.setWidth(240); // 视频窗口的宽 - videoLayout3.setHeight(360); // 视频窗口的高 - Log.e("ttt1112", "1" + "VS" + streams.get(i).getUserId()); + if (streams.size() == 1) { + //user1的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout1 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + videoLayout1.setVideoStream(RCRTCEngine.getInstance().getDefaultVideoStream()); // RCRTCStream#MediaType 必须是Video + videoLayout1.setX(0); //X 坐标 + videoLayout1.setY(0); //Y 坐标 + videoLayout1.setWidth(480); // 视频窗口的宽 + videoLayout1.setHeight(720); // 视频窗口的高 + list.add(videoLayout1); - } else if (i == 2) { - //user3的视频流 - RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout4 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); - list.add(videoLayout4); - videoLayout4.setVideoStream(streams.get(i)); // RCRTCStream#MediaType 必须是Video - videoLayout4.setX(480); //X 坐标 - videoLayout4.setY(360); //Y 坐标 - videoLayout4.setWidth(240); // 视频窗口的宽 - videoLayout4.setHeight(360); // 视频窗口的高 - Log.e("ttt1112", "2" + "VS" + streams.get(i).getUserId()); - } else if (i == 3) { - //user3的视频流 - RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout4 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); - list.add(videoLayout4); - videoLayout4.setVideoStream(streams.get(i)); // RCRTCStream#MediaType 必须是Video - videoLayout4.setX(720); //X 坐标 - videoLayout4.setY(360); //Y 坐标 - videoLayout4.setWidth(240); // 视频窗口的宽 - videoLayout4.setHeight(360); // 视频窗口的高 - Log.e("ttt1112", "3" + "VS" + streams.get(i).getUserId()); - } + //user2的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout2 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + videoLayout2.setVideoStream(streams.get(0)); // RCRTCStream#MediaType 必须是Video + videoLayout2.setX(480); //X 坐标 + videoLayout2.setY(0); //Y 坐标 + videoLayout2.setWidth(480); // 视频窗口的宽 + videoLayout2.setHeight(720); // 视频窗口的高 + list.add(videoLayout2); + + } else if (streams.size() == 2) { + //user1的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout1 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + list.add(videoLayout1); + videoLayout1.setVideoStream(RCRTCEngine.getInstance().getDefaultVideoStream()); // RCRTCStream#MediaType 必须是Video + videoLayout1.setX(0); //X 坐标 + videoLayout1.setY(0); //Y 坐标 + videoLayout1.setWidth(480); // 视频窗口的宽 + videoLayout1.setHeight(720); // 视频窗口的高 + + //user2的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout2 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + videoLayout2.setVideoStream(streams.get(0)); // RCRTCStream#MediaType 必须是Video + videoLayout2.setX(480); //X 坐标 + videoLayout2.setY(0); //Y 坐标 + videoLayout2.setWidth(480); // 视频窗口的宽 + videoLayout2.setHeight(360); // 视频窗口的高 + list.add(videoLayout2); + + //user3的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout3 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + videoLayout3.setVideoStream(streams.get(1)); // RCRTCStream#MediaType 必须是Video + videoLayout3.setX(480); //X 坐标 + videoLayout3.setY(360); //Y 坐标 + videoLayout3.setWidth(480); // 视频窗口的宽 + videoLayout3.setHeight(360); // 视频窗口的高 + list.add(videoLayout3); + + } else if (streams.size() == 3) { + //user1的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout1 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + videoLayout1.setVideoStream(RCRTCEngine.getInstance().getDefaultVideoStream()); // RCRTCStream#MediaType 必须是Video + videoLayout1.setX(0); //X 坐标 + videoLayout1.setY(0); //Y 坐标 + videoLayout1.setWidth(480); // 视频窗口的宽 + videoLayout1.setHeight(720); // 视频窗口的高 + list.add(videoLayout1); + + //user2的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout2 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + videoLayout2.setVideoStream(streams.get(0)); // RCRTCStream#MediaType 必须是Video + videoLayout2.setX(480); //X 坐标 + videoLayout2.setY(0); //Y 坐标 + videoLayout2.setWidth(480); // 视频窗口的宽 + videoLayout2.setHeight(360); // 视频窗口的高 + list.add(videoLayout2); + + //user3的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout3 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + videoLayout3.setVideoStream(streams.get(1)); // RCRTCStream#MediaType 必须是Video + videoLayout3.setX(480); //X 坐标 + videoLayout3.setY(360); //Y 坐标 + videoLayout3.setWidth(480); // 视频窗口的宽 + videoLayout3.setHeight(360); // 视频窗口的高 + list.add(videoLayout3); + + //user3的视频流 + RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout4 = new RCRTCMixConfig.CustomLayoutList.CustomLayout(); + videoLayout4.setVideoStream(streams.get(2)); // RCRTCStream#MediaType 必须是Video + videoLayout4.setX(0); //X 坐标 + videoLayout4.setY(360); //Y 坐标 + videoLayout4.setWidth(480); // 视频窗口的宽 + videoLayout4.setHeight(360); // 视频窗口的高 + list.add(videoLayout4); } + config.setCustomLayouts(list); return config; } @@ -1886,7 +2138,6 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { if (mPkPopWindow != null) { mPkPopWindow.dismiss(); } - } /** @@ -1978,13 +2229,15 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { mLiveLinkMicPkViewHolder = new LiveLinkMicPkViewHolder(mContext, mPkContainer); mLiveLinkMicPkViewHolder.addToParent(); mLiveLinkMicPkViewHolder.setIsAnchor(mIsAnchor); - if (LiveAudienceActivity.getmLivePlayViewHolder() != null) { - LiveAudienceActivity.getmLivePlayViewHolder().setPkview(); + if (mContext instanceof LiveAudienceActivity) { + ((LiveAudienceActivity) mContext).getmLivePlayViewHolder().setPkview(); } } mLiveLinkMicPkViewHolder.startAnim(); + EventBus.getDefault().post(new LiveAudienceEvent().setType(LiveAudienceEvent.LiveAudienceType.PK_TWO_START).setObject(pkUid)); mLiveLinkMicPkViewHolder.showTime(); + nextPkTimeCountDown(2); if (mIsAnchor) { ((LiveRyAnchorActivity) mContext).setPkBtnVisible(false); mPkTimeCount = PK_TIME_MAX; @@ -1993,7 +2246,6 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { // mPkTimeCount=mPkTimeFromServer; mPkTimeCount = PK_TIME_MAX; } - nextPkTimeCountDown(4); Log.d("mPkTimeCount2", "" + mPkTimeCount + ";mPkTimeFromServer=" + mPkTimeFromServer); } @@ -2164,6 +2416,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { if (mHandler != null) { mHandler.removeCallbacksAndMessages(null); } + mHandler = null; mSocketRyClient = null; if (mLiveLinkMicPkViewHolder != null) { mLiveLinkMicPkViewHolder.release(); @@ -2199,4 +2452,224 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { public void setSelfStream(String selfStream) { mSelfStream = selfStream; } + + /** + * 更新Pk分数 + */ + public void upDataPkScore(JSONArray pkScores, String uid, int time) { + String userID1 = (String) imageGrade1.getTag(); + String userID2 = (String) imageGrade2.getTag(); + String userID4 = (String) imageGrade4.getTag(); + if (livePushRyViewHolder.timeTitle.getVisibility() == View.GONE) { + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) livePushRyViewHolder.timeTitle.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(123); + livePushRyViewHolder.timeTitle.setLayoutParams(layoutParams); + livePushRyViewHolder.timeTitle.setVisibility(View.VISIBLE); + String pkTime = StringUtil.getDurationText(time * 1000); + livePushRyViewHolder.textTime.setText(String.format(mContext.getString(R.string.pk_time), pkTime)); + mPkTimeCount = time; + pkCountdownTimer(); + } + int pkScoreSize = pkScores.size(); + if (pkScoreSize == 3) { + linearGrade1.setVisibility(View.VISIBLE); + linearGrade2.setVisibility(View.VISIBLE); + linearGrade4.setVisibility(View.VISIBLE); + //拿到原始数据 + for (int i = 0; i < pkScores.size(); i++) { + JSONObject score = pkScores.getJSONObject(i); + String userID = score.getString("id"); + long userScore = score.getLong("score"); + if (TextUtils.equals(userID, userID1)) { + textGrade1.setText(String.valueOf(userScore)); + if (!score.containsKey("paiming")) { + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade1); + } else { + int ranking = score.getIntValue("paiming"); + switch (ranking) { + case 1: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade1); + break; + case 2: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no2, imageGrade1); + break; + case 3: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no3, imageGrade1); + break; + case 4: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no4, imageGrade1); + break; + } + } + } else if (TextUtils.equals(userID, userID2)) { + textGrade2.setText(String.valueOf(userScore)); + if (!score.containsKey("paiming")) { + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade2); + } else { + int ranking = score.getIntValue("paiming"); + switch (ranking) { + case 1: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade2); + break; + case 2: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no2, imageGrade2); + break; + case 3: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no3, imageGrade2); + break; + case 4: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no4, imageGrade2); + break; + } + } + } else if (TextUtils.equals(userID, userID4)) { + textGrade4.setText(String.valueOf(userScore)); + if (!score.containsKey("paiming")) { + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade4); + } else { + int ranking = score.getIntValue("paiming"); + switch (ranking) { + case 1: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade4); + break; + case 2: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no2, imageGrade4); + break; + case 3: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no3, imageGrade4); + break; + case 4: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no4, imageGrade4); + break; + } + } + } + } + } else { + String userID3 = (String) imageGrade3.getTag(); + linearGrade1.setVisibility(View.VISIBLE); + linearGrade2.setVisibility(View.VISIBLE); + linearGrade3.setVisibility(View.VISIBLE); + linearGrade4.setVisibility(View.VISIBLE); + //拿到原始数据 + for (int i = 0; i < pkScores.size(); i++) { + JSONObject score = pkScores.getJSONObject(i); + String userID = score.getString("id"); + long userScore = score.getLong("score"); + if (TextUtils.equals(userID, userID1)) { + textGrade1.setText(String.valueOf(userScore)); + if (!score.containsKey("paiming")) { + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade1); + } else { + int ranking = score.getIntValue("paiming"); + switch (ranking) { + case 1: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade1); + break; + case 2: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no2, imageGrade1); + break; + case 3: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no3, imageGrade1); + break; + case 4: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no4, imageGrade1); + break; + } + } + } else if (TextUtils.equals(userID, userID2)) { + textGrade2.setText(String.valueOf(userScore)); + if (!score.containsKey("paiming")) { + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade2); + } else { + int ranking = score.getIntValue("paiming"); + switch (ranking) { + case 1: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade2); + break; + case 2: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no2, imageGrade2); + break; + case 3: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no3, imageGrade2); + break; + case 4: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no4, imageGrade2); + break; + } + } + } else if (TextUtils.equals(userID, userID4)) { + textGrade4.setText(String.valueOf(userScore)); + if (!score.containsKey("paiming")) { + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade4); + } else { + int ranking = score.getIntValue("paiming"); + switch (ranking) { + case 1: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade4); + break; + case 2: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no2, imageGrade4); + break; + case 3: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no3, imageGrade4); + break; + case 4: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no4, imageGrade4); + break; + } + } + } else if (TextUtils.equals(userID, userID3)) { + textGrade3.setText(String.valueOf(userScore)); + if (!score.containsKey("paiming")) { + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade3); + } else { + int ranking = score.getIntValue("paiming"); + switch (ranking) { + case 1: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no1, imageGrade3); + break; + case 2: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no2, imageGrade3); + break; + case 3: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no3, imageGrade3); + break; + case 4: + ImgLoader.display(mContext, R.mipmap.icon_livepk_no4, imageGrade3); + break; + } + } + } + + } + } + + } + + + /** + * PK倒计时 + */ + private void pkCountdownTimer() { + + mPkTimeCount--; + if (mPkTimeCount > 0) {// + if (mHandler != null) { + String s1 = StringUtil.getDurationText(mPkTimeCount * 1000); + livePushRyViewHolder.textTime.setText(String.format(mContext.getString(R.string.pk_time), s1)); + mHandler.sendEmptyMessageAtTime(WHAT_PK_TIME2, getNextSecondTime()); + } + } else { + livePushRyViewHolder.timeTitle.setVisibility(View.GONE); + if (mHandler != null) { + mHandler.removeCallbacksAndMessages(null); + } + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.PK_TIME_COUNT)); +// endDRGif(); + } + } + + } diff --git a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java index 8e436a47b..e22306814 100644 --- a/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java +++ b/live/src/main/java/com/yunbao/live/socket/SocketRyClient.java @@ -3,8 +3,6 @@ package com.yunbao.live.socket; import static com.blankj.utilcode.util.SnackbarUtils.dismiss; import static com.blankj.utilcode.util.ViewUtils.runOnUiThread; import static com.yunbao.live.activity.LiveRyAnchorActivity.isDRPK; -import static com.yunbao.live.presenter.LiveRyLinkMicPkPresenter.leaveDRRoom; -import static com.yunbao.live.views.LivePushRyViewHolder.dr_pk_view; import static com.yunbao.live.views.LivePushRyViewHolder.rtcRoom; import static com.yunbao.live.views.LiveRoomViewHolder.getIsHot; @@ -154,7 +152,6 @@ public class SocketRyClient { public void processBroadcast(String socketMsg) { L.e("收到socket--->" + socketMsg); - Log.i("SocketRyClient", "socketMsg" + socketMsg); Log.i("SocketRyClient", "socketMsg" + socketMsg); if (Constants.SOCKET_STOP_PLAY.equals(socketMsg)) { @@ -282,42 +279,58 @@ public class SocketRyClient { } //收到对方同意多人PK邀请 else if (action3 == 2) { - UserBean u = new UserBean(); -// u.setUserNiceName(map.getString("uname")); - u.setId(map.getString("uid")); - mListener.onLinkDRMicPkApplyOk(u); - } else if (action3 == 6) { +// UserBean u = new UserBean(); +//// u.setUserNiceName(map.getString("uname")); +// u.setId(map.getString("uid")); +// mListener.onLinkDRMicPkApplyOk(u); + } else if (action3 == 6) {//开始Pk if (LiveRoomViewHolder.mHandler != null) { LiveRoomViewHolder.mHandler.removeCallbacksAndMessages(null); } - LiveRoomViewHolder.UpPkBar(map.getJSONArray("userlist"), mLiveUid, map.getIntValue("drpk_time")); +// LiveRoomViewHolder.UpPkBar(map.getJSONArray("userlist"), mLiveUid, map.getIntValue("drpk_time")); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.LEAVE_PK_SCORE) + .setPkScores(map.getJSONArray("userlist")) + .setUid(mLiveUid) + .setTime(map.getIntValue("drpk_time"))); if (livePushRyViewHolder == null) { - LiveAudienceActivity.getmLivePlayViewHolder().setPkview(); + // LiveAudienceActivity.getmLivePlayViewHolder().setPkview(); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.SOCKET_LIVE_DRPK_SET_PK_VIEW) + ); } } else if (action3 == 5) { -// EventBus.getDefault().post(new LiveAudienceEvent() -// .setType(LiveAudienceEvent.LiveAudienceType.PK_TIME_COUNT)); +// endDRGif(); LiveRoomViewHolder.d_pk_view.setVisibility(View.GONE); if (LiveRyAnchorActivity.mLiveAnchorViewHolder != null) { - dr_pk_view.setVisibility(View.GONE); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); params.topMargin = 0; - LivePushRyViewHolder.mPreView.setLayoutParams(params); - leaveDRRoom(); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.LEAVE_DR_ROOM)); isDRPK = 0; } else { - LiveAudienceActivity.getmLivePlayViewHolder().setPkEndview(); + // LiveAudienceActivity.getmLivePlayViewHolder().setPkEndview(); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.SOCKET_LIVE_DRPK_SET_PK_END_VIEW) + ); + } //創建了多人房間 } else if (action3 == 3) { - if (LiveAudienceActivity.getmLivePlayViewHolder() != null) { + /* if (LiveAudienceActivity.getmLivePlayViewHolder() != null) { LiveAudienceActivity.getmLivePlayViewHolder().setPkview(); - } + }*/ + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.SOCKET_LIVE_DRPK_SET_PK_VIEW) + ); isDRPK = 1; } else if (action3 == 10) { if (!map.getString("uid").equals(CommonAppConfig.getInstance().getUid())) { - LiveAudienceActivity.getmLivePlayViewHolder().setPkview(); + // LiveAudienceActivity.getmLivePlayViewHolder().setPkview(); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.SOCKET_LIVE_DRPK_SET_PK_VIEW) + ); } } @@ -925,7 +938,12 @@ public class SocketRyClient { mListener.onSendGift(receiveGiftBean); } if (map.getIntValue("drpk_status") == 1) { - LiveRoomViewHolder.UpPkBar(map.getJSONArray("userlist"), mLiveUid, 0); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.LEAVE_PK_SCORE) + .setPkScores(map.getJSONArray("userlist")) + .setUid(mLiveUid) + .setTime(0)); +// LiveRoomViewHolder.UpPkBar(map.getJSONArray("userlist"), mLiveUid, 0); } } @@ -1075,16 +1093,8 @@ public class SocketRyClient { break; case 5://PK时候断开连麦的回调 if (rtcRoom != null) { - if (LivePushRyViewHolder.mPreView1 != null) { - LivePushRyViewHolder.mPreView1.removeAllViews(); - LivePushRyViewHolder.mPreView1.setVisibility(View.GONE); - isDRPK = 0; - leaveDRRoom(); - } - LivePushRyViewHolder.btn_close.setVisibility(View.GONE); - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); - params.topMargin = 0; - LivePushRyViewHolder.mPreView.setLayoutParams(params); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.DISCONNEXT_PK_TIME)); //断开连麦 HttpClient.getInstance().post("livepk.setliveuserout", "livepk.setliveuserout") .execute(new HttpCallback() { diff --git a/live/src/main/java/com/yunbao/live/views/AbsRyLivePushViewHolder.java b/live/src/main/java/com/yunbao/live/views/AbsRyLivePushViewHolder.java index cd95be954..2b1c7e4f2 100644 --- a/live/src/main/java/com/yunbao/live/views/AbsRyLivePushViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/AbsRyLivePushViewHolder.java @@ -32,9 +32,10 @@ public class AbsRyLivePushViewHolder extends AbsViewHolder implements ILivePushV protected ViewGroup mLeftContainer; protected ViewGroup mRightContainer; protected ViewGroup mPkContainer; - public static FrameLayout mPreView,mPreView1,dr1_preview,dr2_preview,dr3_preview,dr4_preview; - public static ImageView leave; + public FrameLayout mPreView, mPreView1, cameraPreview3, dr1_preview, dr2_preview, dr3_preview, dr4_preview; + public ImageView leave; protected boolean mOpenCamera;//是否选择了相机 + public LinearLayout camera; //倒计时 protected TextView mCountDownText; diff --git a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java index e4c2af532..488a16729 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java @@ -102,11 +102,13 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX public TencentTRTCBeautyManager tencentTRTCBeautyManager; public static Context contexts; public static TextView btn_close; - public static LinearLayout dr_pk_view; + public LinearLayout dr_pk_view; public static RCRTCRoom rtcRoom; public static RCRTCLiveInfo rcrtcLiveInfo; private ViewGroup liveActivityContainer; + public FrameLayout timeTitle; + public TextView textTime; private TextView tv_avatarOther_name; private ImageView avatarOther; private LinearLayout goto_room_view; @@ -341,6 +343,8 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX userBean1.setUserNiceName("null"); userBean1.setAvatar("null"); } + mLiveRyLinkMicPkPresenter.onLinkMicToPk(userBean1); + mLiveRyLinkMicPkPresenter.onLinkMicPkStart(inviteeRoomId, 3); //单人PK,减掉次数 if (!RandomPkManager.getInstance().isRandomModel()) { LiveNetManager.get(mContext).setFreePkNum(new com.yunbao.common.http.base.HttpCallback() { @@ -398,14 +402,19 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX super.init(); Bus.getOn(this); mPreView = (FrameLayout) findViewById(R.id.camera_preview); + camera = (LinearLayout) findViewById(R.id.camera); mPreView1 = (FrameLayout) findViewById(R.id.camera_preview1); + cameraPreview3 = (FrameLayout) findViewById(R.id.camera_preview3); dr1_preview = (FrameLayout) findViewById(R.id.dr1_preview); dr2_preview = (FrameLayout) findViewById(R.id.dr2_preview); dr3_preview = (FrameLayout) findViewById(R.id.dr3_preview); dr4_preview = (FrameLayout) findViewById(R.id.dr4_preview); leave = (ImageView) findViewById(R.id.leave); dr_pk_view = (LinearLayout) findViewById(R.id.dr_pk_view); + timeTitle = (FrameLayout) findViewById(R.id.time_title); + textTime = (TextView) findViewById(R.id.text_time); dr_pk_view.setVisibility(View.GONE); + cameraPreview3.setVisibility(View.GONE); btn_close = (TextView) findViewById(R.id.btn_close); tv_avatarOther_name = (TextView) findViewById(R.id.tv_avatarOther_name); avatarOther = (ImageView) findViewById(R.id.avatarOther); @@ -450,6 +459,7 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX mPreView1.setVisibility(View.GONE); inputStreamList.clear(); inputStreamList1.clear(); + changeToBig(); } }); } @@ -668,19 +678,28 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX params.width = mPreView.getWidth() / 2; params.height = DpUtil.dp2px(250); params.topMargin = DpUtil.dp2px(130); - mPreView.setLayoutParams(params); + camera.setLayoutParams(params); } } @Override public void changeToBig() { - if (mPreView != null) { - FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mPreView.getLayoutParams(); + if (camera != null) { + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) camera.getLayoutParams(); params.width = ViewGroup.LayoutParams.MATCH_PARENT; params.height = ViewGroup.LayoutParams.MATCH_PARENT; params.topMargin = 0; - mPreView.setLayoutParams(params); + camera.setLayoutParams(params); } + if (mPreView1.getVisibility()==View.VISIBLE){ + mPreView1.removeAllViews(); + mPreView1.setVisibility(View.GONE); + inputStreamList.clear(); + inputStreamList1.clear(); + } + } + public void closeButtonGone(){ + btn_close.setVisibility(View.GONE); } @Override diff --git a/live/src/main/java/com/yunbao/live/views/LiveRyAnchorViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRyAnchorViewHolder.java index 19f774b6a..5a48591af 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRyAnchorViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRyAnchorViewHolder.java @@ -5,7 +5,6 @@ import static com.yunbao.live.activity.LiveRyAnchorActivity.PKing; import static com.yunbao.live.activity.LiveRyAnchorActivity.pk_nub; import static com.yunbao.live.event.LiveAudienceEvent.LiveAudienceType.START_MESSAGE; import static com.yunbao.live.event.LiveAudienceEvent.LiveAudienceType.WISH_LIST_UPDATE; -import static com.yunbao.live.presenter.LiveRyLinkMicPkPresenter.leaveDRRoom; import android.content.Context; import android.graphics.drawable.Drawable; @@ -149,7 +148,8 @@ public class LiveRyAnchorViewHolder extends AbsLiveViewHolder { .execute(new HttpCallback() { @Override public void onSuccess(int code, String msg, String[] info) { - leaveDRRoom(); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.LEAVE_DR_ROOM)); PKing = false; } diff --git a/live/src/main/res/layout/view_live_push_ry.xml b/live/src/main/res/layout/view_live_push_ry.xml index 550226de5..5a0ecee77 100644 --- a/live/src/main/res/layout/view_live_push_ry.xml +++ b/live/src/main/res/layout/view_live_push_ry.xml @@ -1,33 +1,49 @@ - + android:layout_height="match_parent"> + - + android:layout_height="match_parent" + android:orientation="vertical"> + + + + + + + + android:visibility="gone" /> - + android:orientation="vertical" + android:visibility="gone"> + android:layout_weight="1" + android:background="@mipmap/live_icon_vacancy" /> + android:layout_weight="1" + android:background="@mipmap/live_icon_vacancy" /> @@ -59,24 +75,23 @@ + android:background="@mipmap/live_icon_vacancy" /> + android:background="@mipmap/live_icon_vacancy" /> - - - - + android:orientation="vertical" + android:visibility="gone"> + android:layout_height="match_parent" /> + android:gravity="center" + android:visibility="gone"> + + android:layout_marginTop="130dp"> + android:layout_marginBottom="20dp" /> + android:layout_marginBottom="20dp" /> - + android:textSize="13sp" + android:visibility="gone" /> - + app:mfl3_ratio="0.25" /> + android:visibility="gone" /> + + + + + + From ffcb0e8790b53ddab7b89536b8903c77c7d67769 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 3 Feb 2023 16:23:31 +0800 Subject: [PATCH 111/118] =?UTF-8?q?=E4=B8=BB=E6=92=AD=E7=AB=AF=E5=A4=9A?= =?UTF-8?q?=E4=BA=BAPK=20=E4=BB=A3=E7=A0=81=E8=A1=A5=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/mipmap-xxxhdpi/icon_livepk_no1.png | Bin 0 -> 1420 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 live/src/main/res/mipmap-xxxhdpi/icon_livepk_no1.png diff --git a/live/src/main/res/mipmap-xxxhdpi/icon_livepk_no1.png b/live/src/main/res/mipmap-xxxhdpi/icon_livepk_no1.png new file mode 100644 index 0000000000000000000000000000000000000000..03984ca3bf9528a4d339d6e90028e557089762e0 GIT binary patch literal 1420 zcmV;71#|j|P)Px)MoC0LR9Hu)muqZPMHI*XXYSqY?$)i9QeH&_sijyEs}zaB7%4_RC;`oy7{CV< zu)IXf-P=Zk~XaK1^B_RTph+?UgK6dv$W{$acOS_MD z_imhTn>~-;{O8;`X9yk^bEClT@jD@m5|CaAjUEA0Ily-S#DMAmX&1qK0?^x_cXpt3 zTQ3nfS9r>0z}MG}gOu|iXf{C8!8~$EAA$tqDnQ4;>L7Z>0jhkzJ6nz+0r-5QAH_Wj zpzsa|V*nK7f=&A0*?BL(m!QyqyEh*ta+Jzkg97l?hS3oEdJvWZ@a2(sFw;(@xJd+K zJ88tWo^*o@0KWQ0HHbDdFzbINPIk8l*aeo2H2#A>lmAEo;A^j!v7)_T%mk3LKJo;V zM7$F{##*WxP@+ExUtbnd@z4$;T97TUvJA**CyZ_z(uljJny&zXk}&kb;_OV!juLAz zVawLrHQ@pxgI*7$Q9ivx3#t4x^(D2vk8Us)WDn8HiA+YihM$fNX0*sH`ft zD1=V3F^?*mk2uCIfO%;8uIalCdrr@v#U@s)H674$=bvY5jKQjk7Q=tVH3s z>f8YCj?pS);0fmwB|f>#r^10I5WkfYH7S(Ua}%~!gTg6m0Ll;uF2K3G0D2jy*D5~T zO?+|H7{xdM!ox%1+tE&#T!ldSO8^ms9)t+qm8yUPFm|dZ1)K|kfZal>da};1n5hZ+ zju``*riEc;BYyJ=jDP-c_0vbqN70OpE{uDGjsj;^cm{Bt2$uz9Em`O4Hxki$Pv`(- z>=q0;5#gG~G=O@9%DgGimrH6yv&cSMe+b~&o&n-rFl0Hx)6)P>*CRA$iq|l%9YefH z_UYx<0F3qODIEa5FB9OG*AN<=9{?CT$!=X11vuyxz&5&Iq5|RRO({nZZ(WYUQ4e?x zldvOdA?wtVIM{oqlMaBW%mg^K6rqv%0^oD9PQ2O`NXCL{c4ngTyBMQFtR zUc)46fcayxj=ypoK#f;V+vtX+I{+I}kKklo-T(lL8n`*j+U<0Z`=*aZ(FJR?}V?EA>Iap5aCN*sYS%cB0ElH`cRVhGi2hHu!!oM+6^z^%h|2>Rk6 zZK!dQt|%K%25a}UB?gl75x>>0ZD+>f!7{|-G598}f?hPv1AvL>$wmYN1nN7oG$)G` zFZb7evddMoU&bSmQqvL#fy}lnr3uTnz`5TUZaBZtq4@@mC>el3+Y35m1HG`{OaX9y zn1`OPW}&r!F+S&3^EO~665slST1Zds|Es?kQ|R_ZG_x3UnXm=GJ$dKI>cB^(R1Jl5 zT23XKWxfmcMKr5KPE}HT1ct{UFH2^IV!~e5Xc3HX`_pZcC| zY0dUZ_OvVB7YWA0)<{7#l^IVl(=-s56H^$@EhNwh#;-*5qayi@68u|e*r;}zw!_L* aNB;o>5HDn)%1c-P0000 Date: Fri, 3 Feb 2023 16:40:41 +0800 Subject: [PATCH 112/118] =?UTF-8?q?=E4=B8=BB=E6=92=AD=E7=AB=AF=E5=A4=9A?= =?UTF-8?q?=E4=BA=BAPK=20=E4=BB=A3=E7=A0=81=E8=A1=A5=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/background_pk_time.xml | 5 + .../main/res/layout/view_live_pk_details.xml | 252 ++++++++++++++++++ .../res/mipmap-xxxhdpi/icon_livepk_no2.png | Bin 0 -> 1595 bytes .../res/mipmap-xxxhdpi/icon_livepk_no3.png | Bin 0 -> 1746 bytes .../res/mipmap-xxxhdpi/icon_livepk_no4.png | Bin 0 -> 1526 bytes 5 files changed, 257 insertions(+) create mode 100644 live/src/main/res/drawable/background_pk_time.xml create mode 100644 live/src/main/res/layout/view_live_pk_details.xml create mode 100644 live/src/main/res/mipmap-xxxhdpi/icon_livepk_no2.png create mode 100644 live/src/main/res/mipmap-xxxhdpi/icon_livepk_no3.png create mode 100644 live/src/main/res/mipmap-xxxhdpi/icon_livepk_no4.png diff --git a/live/src/main/res/drawable/background_pk_time.xml b/live/src/main/res/drawable/background_pk_time.xml new file mode 100644 index 000000000..b76d2f6c9 --- /dev/null +++ b/live/src/main/res/drawable/background_pk_time.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/live/src/main/res/layout/view_live_pk_details.xml b/live/src/main/res/layout/view_live_pk_details.xml new file mode 100644 index 000000000..3b856255d --- /dev/null +++ b/live/src/main/res/layout/view_live_pk_details.xml @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/live/src/main/res/mipmap-xxxhdpi/icon_livepk_no2.png b/live/src/main/res/mipmap-xxxhdpi/icon_livepk_no2.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0becb0fec06d67f60e4c31a4ec0e0e9ad2e524 GIT binary patch literal 1595 zcmV-B2E_S^P)Px)^+`lQR9Hu)muqZP*A<1oeeOIw;~7k9Ok%sTO@soni;TgfrE-cwh!h1u6D0a4 zjVkq_D&Y@Rlu|01hPJ8tQYs{>NL5j)Ds3tnqE@7lNvK0Zz-gdB+CW<)-hqP0kFm!y zp7EV~b~R(L2ix;VbN-&a*Isv@wb!{vsAN5>rfJjV8ta%^V`VAES!vP50ucmN7!;L% zBYMmSm&VjL7;CLdBBJHsrCdP6>1$0s%Oi-a1HBixvuKWphjJ0&sG!}+;nDpAT}uqA#GtXXXt^02w?rj9_ zId!EmOWRfx>?pvCeB%msbPu|#u$aA8z zAxvU|E}!A?rYOr7gs7?VO;s7sTFwt=c;)g4`w}kcn$lWTkzvv7BWG7MyqyEd6Igt# zzrz?_0~%)X_u^?b_+dw9J+-0f!ZYJ?M7H%_qub{o!Qyc@^G-^&tohHVH6MqZ4kdH9`c*t?>o6qNhw zq*Z;QuXEu`vgAapL9)7EkQH;Co}I|D&RDj8Y5`%N;ki>WddEEm6qY;i?Y3Il>q1kh zUpaV@BjFInUrL-gQOQe^)FhQH80Vo8_Uf$9FsGsJ`ij zubqpttuIL+8ms#hcrSuJ@*?Me{eqR`qo0N)|{y;u`aCkRjwv@}Up2v7P$@f~LJlql` zc(c&ukql418{>wAaeQShc)E-#R?J5E%p0Q{5&dJS>o@o1ZYIf3mqmD>rDh7``q%{D zcyEBdv>(5J(wuT@(wWQs?a2-Cv`g+i5MSho`3taUt}a;X5%H32SrXy%ch?m95O05& z;K0=}yn@7>$(|WC4A?5f6h97uKbw$!Tvi{|kc=jFiO5&c*|bMeah~spa(~l2d<8C; zpZl!E@0i<2Wv%ke-}>o^2l1IAMgpbQ2(`ZhxnpJ*2FC{Iez2aV zGWYzgyjuj`8VcfbifKYFSnJ$>bbaVjozPRa^LG(XKbr)d`h_QLEI)kC{ zji5hQrTL@bmyQDZS*;sv|Fml$g=1Ekg+C}A8K*z@>p=uF%Sqj`fdvFC;w!?C}2id*go{|8FXR>mXrQPltd002ovPDHLkV1f+i9RL6T literal 0 HcmV?d00001 diff --git a/live/src/main/res/mipmap-xxxhdpi/icon_livepk_no3.png b/live/src/main/res/mipmap-xxxhdpi/icon_livepk_no3.png new file mode 100644 index 0000000000000000000000000000000000000000..b9a148addde5dbf3d5d8a4f169e32703e50d7757 GIT binary patch literal 1746 zcmV;@1}*uCP)Px*j7da6R9Hu)mwSv<^%ciI=g!>Oncdl!%Pj5+2o_r?X()oUG+=qGshUD4N+qSV z39U31f!z`zHWED#CQe?TJ|(}v=Us#K~=uz>ie)(0y!uZgP{4;OFqD6YxxKx<)4d4oeGmth7Kkpf}_e;z`LmXY9eLsTOIjR zcP<-)5{POvP}Ut=i0Y#PwLnomvRC%S^IYk1(a#M->Q{s}9ukoOqcI?XP3`qHj_F%t zpbr3Mp@s*-DRM!T$3tmr*V5{3vA&po1fIO`y9q9`5!IRhkKtajLRwXyF&&LIL^iiv zyVr}rx^oRTnIg}jI#rQDk0)(A#H=)apFuceB7;M-wgh!hc3GNS8NDVFStHRiON#ww zc!$8kzMiWp$)rsx<|El{QmU1VEFMnGj?)}Jg%L~jABTH0gOI-{top2asSMpGHA$a?LlLt9Tf$2(5&X7}q9S2~!v zNQhi;9Og!ApM2Z1lOgcv>17iP!}m8-yln5a;)xWsUE_FQ+%G9HiwE`2RhRe99;NZ? zM!qq;Drfo#ay(@Ef9RE{Ecw?Gv${I`IEJo5=@-AAM2cIi@3466FDUkhNZ3hE_q5QN z>Y_4G&aiMT0bd|%aP>Qn;of+jU{Q|Z5qi|o2cH7tWTx19O4_c66*N>=orrw{Yzww(;ED$7?yyMwXhgR=U|!Xx&Yn{*QdAkh^!p1@=V4xw#UIos3Y~OT!s5rJ{Rw!QdeS`{Yx{uBpFU05ka7&8 zUq9Uc&wmeU`B%D{9 zqI+cF(G^F4+w-FP0BqYPl}b`W6`Q8~A=`|SPKx@&Yv?LUzKBQk&5uFd-Q8+kwV1-@LlprE*OWM0#XIU@Y!%3K(T zh|fy#-Qrt0-2D*}EW+nEGuiJEvwAw&Ie9&`r8i~?Y&fxxW6Z0b&Z05*bGrKsFEsDtWc&gRx~|E zn_(f6BN0XR+fHhc%zw8bWI65@&|jmMi~6!URfnNYfTyOerNk`B{F`)=w8hVncGCom z07FY6n8ww?v;X7)wl+VHFK`Jz;1ZIe^2o$#m0L1hRe4sbEqO>4Z3rnY13Z)u{_O(RB*MkJ&Sm*2cL>#1ivTiGkw zw6~W<%rvi}{l~J`>2Pf-i~!|+lOn^1FZ1e9lIjw3Y&z@&uHnzN<{aVQUe!@m|H4nB zsa^!UA9oyBHbGQg0v&n1eW3unck_GGFzufooU!ff6@0Io@BF>hZSU*a=Ly9t#6v6<37k)bX!wn!V|CU(BF){|PTI ziv-}0C_e$b`I`3~*+;p9(2CEzr8maC@DEV({Od3tIR~WrEjn3 z=aKh7MNa^)`BYy#JbUZ$T(9JUyqdDNA!LV!Z07*qoM6N<$g7*w)GXMYp literal 0 HcmV?d00001 diff --git a/live/src/main/res/mipmap-xxxhdpi/icon_livepk_no4.png b/live/src/main/res/mipmap-xxxhdpi/icon_livepk_no4.png new file mode 100644 index 0000000000000000000000000000000000000000..a9879e4f93c8a803fba4baccc29e518abb0fff90 GIT binary patch literal 1526 zcmVPx)ut`KgR9Hu?mwRkebri?H=l0%P+V0V{-Ed$~3^AyGkRg(o49Et8K%77zJ`fW@ zLJ&!qfCMvR5m^XK0iBTH25NxGLL@^E7+*8BrudM(vx5s!h{rwm;tH>(|KZXT84bZ zAJ*zK7vu#9U^Dk*rqJ?5%^*!vroe)6V2lLN-@rx(<1!I`WEKZCQuk%f$@Lq>=n;Uc zs#JfYdnS|gE`R|5tY)ws?}-@90e~(@phYQjMxUbCe@P@MKwa6vY=z_^iKMvE5Z>=Mb?76=B_H;0DR>&IV7kA%=!N_aHoV&gc(~Es9wjs(KkE$O#ryF>BvBZ zqLmEf0x+$QJ_70hDl}bP+&L2+L2i`ov)iKbW+Ix|8^__syNJrsggTeV0;@FzlHB92 zMF?VX+Wd*7?KKexU}kFEcwiZrR{+sj!LiW;^Av@C&bp7Z4f`8X3IQkoPYHY_%G<*NhEM+7?lw^Qobv zDp!)|I5V5BK5)AhX)ojz znS~YzLVq9)+4H7%sQOO)0{f6bunufZc`O4>Umblo<_^DUqKnEaJ@P?5nx+2>=}ve*^_S~>?YsJ@(_cPpLEP~3ai})l8k2>G4G{@6=ih*Jjo~{Aq~=qq3}$*S0d3y zKO(-SxVoe&@eUwGjz8;xmUw4`E?tLq;tW)aF@Rv+PQLdx{>;Er$pEyF26@bIxF?S4 z-JZ5-1^&2%=Bh(bO)f+Xd_Z@KN=u2bpeFz&Z^VBB@b9dK%EADgK_nGWUD5giiD^%= zvf&oo)^$CXZY^0mSWzrT z01Qrs8-oz-Be#n})a8VG_SA$TY}~R3{rV}8V&mE1MnO#9OR&x&F8s*Wpz;PVzuwnN zNZ6SU_nc{o02RAox2c9TLqM1r%UzD<4ROZ$rE8uAcn5&qjj%TN;S5)Ifbwr(x3zYK zf&3#0OJ2r@ORltDNW4{Qec<9I2%c?b+4;Se=0xiA`H*8LBY@!f%LsjU1Xi`@y(drv z#Pi%G?`&-yhHc_sSezM_#X*2gkL7k7oh;C8c5vIkp-2QuC-`*yz-|T}?n@?mrORMQI4WfEO4eHMt#+FPR-Q4#QlI@;0U)gdaqH~8PeM$m zgoH(z>%C_>yX=;%7{r}{PYfenF9##%KExLws)VdB^Q>ESy{o?-ckAZD<(Z0*R|8@y z0B7tD)i)T{0lEz#N;O^GFkrJcn9SbLDSN$YLv1u4;Au>p59UXDF)MT?I!8b?1G_w* z7N0fxO77LFt`!#AQd+G2bqfy@LVAY4BbYFR1X7ux6W{~$pG4A60ysn#{h~*^TSuEW cN6fPJFAFVAekm6>FaQ7m07*qoM6N<$f=@TWcK`qY literal 0 HcmV?d00001 From 11e809a978c765647e08edb8dd63437fad40b8ef Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 3 Feb 2023 17:42:19 +0800 Subject: [PATCH 113/118] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=AB=AF=E5=A4=9A?= =?UTF-8?q?=E4=BA=BAPK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live/activity/LiveAudienceActivity.java | 6 +- .../live/views/LivePlayRyViewHolder.java | 133 +++++++++++++++++- .../live/views/LiveRoomPlayViewHolder.java | 2 + .../live/views/PortraitLiveManager.java | 32 ++++- 4 files changed, 168 insertions(+), 5 deletions(-) diff --git a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java index 430527077..aa96bdef8 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveAudienceActivity.java @@ -1258,7 +1258,11 @@ public class LiveAudienceActivity extends LiveActivity { } break; - + case LEAVE_PK_SCORE: + if (manager != null) { + manager.upDataPkScore(event.getPkScores(), event.getTime()); + } + break; case PK_TIME_COUNT: if (manager != null) { manager.endDRGif(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 91d039452..7b77f93f0 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -10,17 +10,22 @@ import android.graphics.Color; import android.media.AudioManager; import android.os.Handler; import android.os.Looper; +import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.view.Gravity; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.ui.StyledPlayerView; @@ -31,6 +36,7 @@ import com.lxj.xpopup.interfaces.XPopupCallback; import com.lzf.easyfloat.EasyFloat; import com.lzy.okserver.OkDownload; import com.yunbao.common.bean.EnterRoomNewModel; +import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.http.HttpCallback; import com.yunbao.common.http.HttpClient; import com.yunbao.common.manager.IMLoginManager; @@ -40,6 +46,7 @@ import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.L; import com.yunbao.common.utils.MicStatusManager; import com.yunbao.common.utils.ScreenDimenUtil; +import com.yunbao.common.utils.StringUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.WordUtil; import com.yunbao.common.views.LiveClarityCustomPopup; @@ -646,7 +653,6 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { params.height = RelativeLayout.LayoutParams.MATCH_PARENT; params.topMargin = 0; params.addRule(RelativeLayout.ALIGN_TOP); - // mPlayer.setRenderRotation(V2TXLiveDef.V2TXLiveRotation.V2TXLiveRotation270); mVideoView.requestLayout(); } @@ -1204,5 +1210,130 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { } } } + } + private int mPkTimeCount = 0; + private Handler countdownHandler = new Handler(); + private View detailsView = null; + private FrameLayout timeTitle; + private TextView textTime; + private TextView textPkName1, textPkName2, textPkName3, textPkName4; + private TextView textGrade1, textGrade2, textGrade3, textGrade4; + private ImageView imageGrade1, imageGrade2, imageGrade3, imageGrade4; + private LinearLayout linearGrade1, linearGrade2, linearGrade3, linearGrade4; + + /** + * PK倒计时 + */ + public void upDataPkScore(JSONArray pkScores, int time) { + + if (detailsView == null) { + detailsView = LayoutInflater.from(mContext).inflate(R.layout.view_live_pk_details, null); + timeTitle = detailsView.findViewById(R.id.time_title); + textTime = detailsView.findViewById(R.id.text_time); + linearGrade1 = detailsView.findViewById(R.id.lin_pk1); + linearGrade2 = detailsView.findViewById(R.id.lin_pk2); + linearGrade3 = detailsView.findViewById(R.id.lin_pk3); + linearGrade4 = detailsView.findViewById(R.id.lin_pk4); + textPkName1 = detailsView.findViewById(R.id.text_pk_name1); + textPkName2 = detailsView.findViewById(R.id.text_pk_name2); + textPkName3 = detailsView.findViewById(R.id.text_pk_name3); + textPkName4 = detailsView.findViewById(R.id.text_pk_name4); + textGrade1 = detailsView.findViewById(R.id.text_grade1); + textGrade2 = detailsView.findViewById(R.id.text_grade2); + textGrade3 = detailsView.findViewById(R.id.text_grade3); + textGrade4 = detailsView.findViewById(R.id.text_grade4); + imageGrade1 = detailsView.findViewById(R.id.image_grade1); + imageGrade2 = detailsView.findViewById(R.id.image_grade2); + imageGrade3 = detailsView.findViewById(R.id.image_grade3); + imageGrade4 = detailsView.findViewById(R.id.image_grade4); + linearGrade1.setVisibility(View.GONE); + linearGrade2.setVisibility(View.GONE); + linearGrade3.setVisibility(View.GONE); + linearGrade4.setVisibility(View.GONE); + mVideoView.addView(detailsView); + + } + + for (int i = 0; i < pkScores.size(); i++) { + JSONObject score = pkScores.getJSONObject(i); + String userNiceName = score.getString("user_nicename"); + long userScore = score.getLong("score"); + int resScore = R.mipmap.icon_livepk_no1; + if (userScore == 0 && !score.containsKey("paiming")) { + resScore = R.mipmap.icon_livepk_no1; + } else { + if (score.containsKey("paiming")) { + int ranking = score.getIntValue("paiming"); + switch (ranking) { + case 1: + resScore = R.mipmap.icon_livepk_no1; + break; + case 2: + resScore = R.mipmap.icon_livepk_no2; + break; + case 3: + resScore = R.mipmap.icon_livepk_no3; + break; + case 4: + resScore = R.mipmap.icon_livepk_no4; + break; + } + } + } + if (i == 0) { + linearGrade1.setVisibility(View.VISIBLE); + textPkName1.setText(userNiceName); + ImgLoader.display(mContext, resScore, imageGrade1); + textGrade1.setText(String.valueOf(userScore)); + } else if (i == 1) { + linearGrade2.setVisibility(View.VISIBLE); + textPkName2.setText(userNiceName); + ImgLoader.display(mContext, resScore, imageGrade2); + textGrade2.setText(String.valueOf(userScore)); + } else if (i == 2) { + linearGrade4.setVisibility(View.VISIBLE); + textPkName4.setText(userNiceName); + ImgLoader.display(mContext, resScore, imageGrade4); + textGrade4.setText(String.valueOf(userScore)); + } else if (i == 3) { + linearGrade3.setVisibility(View.VISIBLE); + textPkName3.setText(userNiceName); + ImgLoader.display(mContext, resScore, imageGrade3); + textGrade3.setText(String.valueOf(userScore)); + + } + } + + if (time > 0) { + mPkTimeCount = time; + timeTitle.setVisibility(View.VISIBLE); + countdownHandler.postAtTime(countdownRunnable, getNextSecondTime()); + } + + } + + private Runnable countdownRunnable = new Runnable() { + @Override + public void run() { + mPkTimeCount--; + if (mPkTimeCount > 0) {// + String s1 = StringUtil.getDurationText(mPkTimeCount * 1000); + textTime.setText(String.format(mContext.getString(R.string.pk_time), s1)); + countdownHandler.postAtTime(countdownRunnable, getNextSecondTime()); + } else { + timeTitle.setVisibility(View.GONE); + countdownHandler.removeCallbacks(countdownRunnable); + Bus.get().post(new LiveAudienceEvent() + .setType(LiveAudienceEvent.LiveAudienceType.PK_TIME_COUNT)); + } + } + }; + + /** + * 获取下一秒钟的时间 + */ + private long getNextSecondTime() { + long now = SystemClock.uptimeMillis(); + return now + (1000 - now % 1000); } } diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java index 63bc39eea..440030882 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomPlayViewHolder.java @@ -3,6 +3,7 @@ package com.yunbao.live.views; import android.content.Context; import android.view.ViewGroup; +import com.alibaba.fastjson.JSONArray; import com.yunbao.common.bean.EnterRoomNewModel; import com.yunbao.common.bean.LiveBean; import com.yunbao.common.utils.ToastUtil; @@ -101,6 +102,7 @@ public abstract class LiveRoomPlayViewHolder extends AbsViewHolder implements IL } + public interface OnMicCallback { void onMikUpdate(); diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index a2d2f7704..637b0f48c 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -22,6 +22,7 @@ import androidx.drawerlayout.widget.DrawerLayout; import androidx.viewpager.widget.PagerAdapter; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.blankj.utilcode.util.GsonUtils; import com.lzf.easyfloat.EasyFloat; @@ -129,7 +130,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe //侧滑布局 // private DrawerLayout drawerLayout; //直播间拆分布局 - private LiveRoomPlayViewHolder mLivePlayViewHolder; + private LivePlayRyViewHolder mLivePlayViewHolder; //头部布局 public LiveRoomViewHolder mLiveRoomViewHolder; //底部布局 @@ -574,7 +575,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLivePlayViewHolder.setViewUP(4); } - mLiveRoomViewHolder.UpPkBar(pkInfo.getJSONArray("userlist"), mLiveBean.getUid(), pkInfo.getIntValue("drpk_time")); + upDataPkScore(pkInfo.getJSONArray("userlist"), pkInfo.getIntValue("drpk_time")); } //守护相关 mLiveGuardInfo = new LiveGuardInfo(); @@ -692,7 +693,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mLiveRyLinkMicPkPresenter = null; } if (mLiveEndViewHolder != null) { - removeLiveEnd(); + removeLiveEnd(); } if (isQuit) { @@ -1818,6 +1819,31 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mViewPager.setCanScroll(enableScroll); } + /** + * 用户端多人Pk + * + * @param pkScores + * @param time + */ + public void upDataPkScore(JSONArray pkScores, int time) { + if (mLivePlayViewHolder != null) { + String liveId = mLiveBean.getUid(); + JSONObject liveModel = null; + //调整数据 + int index = 0; + for (int i = 0; i < pkScores.size(); i++) { + JSONObject score = pkScores.getJSONObject(i); + if (TextUtils.equals(score.getString("id"), liveId)) { + liveModel = score; + index = i; + } + } + pkScores.remove(index); + pkScores.add(0, liveModel); + mLivePlayViewHolder.upDataPkScore(pkScores, time); + + } + } public void endDRGif() { if (mLiveRoomViewHolder != null) { From 8f58c485c875eb18dd66ce288f5797b2a1f6bc93 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Sat, 4 Feb 2023 16:53:29 +0800 Subject: [PATCH 114/118] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=AB=AF=E5=A4=9A?= =?UTF-8?q?=E4=BA=BAPK=20=E4=BF=AE=E6=94=B9=E7=BB=93=E6=9D=9F=E5=90=8EPK?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=B8=8D=E7=BB=93=E6=9D=9F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yunbao/live/views/LivePlayRyViewHolder.java | 10 ++++++++++ .../com/yunbao/live/views/PortraitLiveManager.java | 1 + 2 files changed, 11 insertions(+) diff --git a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java index 7b77f93f0..e4dedb4c0 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePlayRyViewHolder.java @@ -556,8 +556,18 @@ public class LivePlayRyViewHolder extends LiveRoomPlayViewHolder { params.addRule(RelativeLayout.ALIGN_TOP); mVideoView.requestLayout(); } + if (detailsView != null) { + mVideoView.removeView(detailsView); + detailsView = null; + } } + public void removeDetailView(){ + if (detailsView != null) { + mVideoView.removeView(detailsView); + detailsView = null; + } + } @Override public ViewGroup getSmallContainer() { diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 637b0f48c..9e47a6884 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -317,6 +317,7 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe mask.setVisibility(View.VISIBLE); mLivePlayViewHolder.clearFrame(); mLivePlayViewHolder.setLiveBean(mLiveBean); + mLivePlayViewHolder.removeDetailView(); mLivePlayViewHolder.setCover(mLiveBean.getAvatar()); mLivePlayViewHolder.setLiveBeanLandscape(mLiveBean.getLandscape()); //mLivePlayViewHolder.play(mLiveBean.getPull(), LiveRoomPlayViewHolder.PLAY_MODEL_DEF); From 5dd5b2e0eabfcc1b875d14cc267bdf3d0d01c4ae Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Mon, 6 Feb 2023 16:28:39 +0800 Subject: [PATCH 115/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4PK=E6=97=B6=E9=80=9A=E8=BF=87=E5=8F=B3=E4=B8=8A?= =?UTF-8?q?=E8=A7=92=E8=A7=92=E6=A0=87-=E5=AF=B9=E6=96=B9=E9=A6=96?= =?UTF-8?q?=E9=A1=B5(web)-=E8=B7=B3=E8=BD=AC=E7=9B=B4=E6=92=AD=E9=97=B4?= =?UTF-8?q?=EF=BC=8C=E4=BC=9A=E6=AE=8B=E7=95=99pk=E6=9D=A1=E8=A7=82?= =?UTF-8?q?=E4=BC=97=E5=A4=B4=E5=83=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/main/activity/MyWebViewActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/src/main/java/com/yunbao/main/activity/MyWebViewActivity.java b/main/src/main/java/com/yunbao/main/activity/MyWebViewActivity.java index 8c8297b59..ce9cc40c5 100644 --- a/main/src/main/java/com/yunbao/main/activity/MyWebViewActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/MyWebViewActivity.java @@ -264,7 +264,7 @@ public class MyWebViewActivity extends AbsActivity { MicStatusManager.getInstance().showDownMicDialog(mContext); return; } - EventBus.getDefault().post(new LiveRoomChangeEvent(liveBean, liveType, Integer.parseInt(liveTypeVal))); + EventBus.getDefault().post(new LiveRoomChangeEvent(liveBean, liveType, Integer.parseInt(liveTypeVal)).setLiveEnd(true)); } else { RouteUtil.forwardLiveAudienceActivity(liveBean, liveType, Integer.parseInt(liveTypeVal), Integer.parseInt(liveSdk)); } From 894e264fb35f55ebe0f24b46ffdca18b2d19cb27 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Mon, 6 Feb 2023 18:12:16 +0800 Subject: [PATCH 116/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=9A=E4=BA=BAPK?= =?UTF-8?q?=E7=BB=93=E6=9D=9FPK=E9=80=81=E7=A4=BC=E4=BB=8D=E7=84=B6?= =?UTF-8?q?=E5=B1=95=E7=A4=BAPK=E7=BB=93=E6=9D=9F=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.gradle | 4 ++-- .../yunbao/live/presenter/LiveRyLinkMicPkPresenter.java | 1 + .../java/com/yunbao/live/views/LivePushRyViewHolder.java | 8 ++++++-- .../java/com/yunbao/live/views/LiveRoomViewHolder.java | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/config.gradle b/config.gradle index 66e026ffe..5628c118a 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", // -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index efa31c2e4..ef1b75824 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -2457,6 +2457,7 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * 更新Pk分数 */ public void upDataPkScore(JSONArray pkScores, String uid, int time) { + if (time <= 0) return; String userID1 = (String) imageGrade1.getTag(); String userID2 = (String) imageGrade2.getTag(); String userID4 = (String) imageGrade4.getTag(); diff --git a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java index 488a16729..ed02b4b79 100644 --- a/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LivePushRyViewHolder.java @@ -460,6 +460,9 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX inputStreamList.clear(); inputStreamList1.clear(); changeToBig(); + //清理PK上面对方的头像 + EventBus.getDefault().post(new AnchorInfoEvent(true, "", "", "")); + closeButtonGone(); } }); } @@ -691,14 +694,15 @@ public class LivePushRyViewHolder extends AbsRyLivePushViewHolder implements ITX params.topMargin = 0; camera.setLayoutParams(params); } - if (mPreView1.getVisibility()==View.VISIBLE){ + if (mPreView1.getVisibility() == View.VISIBLE) { mPreView1.removeAllViews(); mPreView1.setVisibility(View.GONE); inputStreamList.clear(); inputStreamList1.clear(); } } - public void closeButtonGone(){ + + public void closeButtonGone() { btn_close.setVisibility(View.GONE); } diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index 2c630a09f..d144f8573 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -3937,7 +3937,7 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis customFullServiceNotify(event.getCustomFullServiceNotifyEvent()); break; case PK_TIME_COUNT: - endDRGif(); +// endDRGif(); break; case UP_PK_TWO: pkUid = (String) event.getObject(); From cd0067d77bd87e3c5c71105a5ff1c338a9c14786 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Tue, 7 Feb 2023 14:19:10 +0800 Subject: [PATCH 117/118] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=9A=E4=BA=BAPK?= =?UTF-8?q?=E7=BB=93=E6=9D=9FPK=E9=80=81=E7=A4=BC=E4=BB=8D=E7=84=B6?= =?UTF-8?q?=E5=B1=95=E7=A4=BAPK=E7=BB=93=E6=9D=9F=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/common/http/PDLiveApi.java | 5 +++++ .../com/yunbao/common/http/live/LiveNetManager.java | 12 ++++++++++++ .../yunbao/live/activity/LiveRyAnchorActivity.java | 2 ++ .../live/presenter/LiveRyLinkMicPkPresenter.java | 10 +++++++++- 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/yunbao/common/http/PDLiveApi.java b/common/src/main/java/com/yunbao/common/http/PDLiveApi.java index 50fd3d6a0..dee1a5e78 100644 --- a/common/src/main/java/com/yunbao/common/http/PDLiveApi.java +++ b/common/src/main/java/com/yunbao/common/http/PDLiveApi.java @@ -537,4 +537,9 @@ public interface PDLiveApi { Observable> getLiveStetUpStatus( @Query("liveuid") String liveUid ); + + @GET("/api/public/?service=live.jieshuDRPK") + Observable> jieshuDRPK( + @Query("roomid") String roomId, + @Query("uid") String uid); } diff --git a/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java b/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java index fee7cbbc5..a1aa6c25d 100644 --- a/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java +++ b/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java @@ -1063,6 +1063,18 @@ public class LiveNetManager { }).isDisposed(); } + public void jieshuDRPK(String uID) { + API.get().pdLiveApi(mContext) + .jieshuDRPK(uID, uID) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(baseModelResponseModel -> { + + }, throwable -> { + + }).isDisposed(); + } + /** * 直播间取消网络请求 */ diff --git a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java index 06dd88fe3..a673b8630 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveRyAnchorActivity.java @@ -163,6 +163,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl public static int backIndex = 0;//0=未判断,1=已判断 private FaceManager manager; private ImageView leave_img; + private final RandomPkManager.OnRandomPkTimer onRandomPkTimer = new RandomPkManager.OnRandomPkTimer() { @Override public void onTimer(String time) { @@ -422,6 +423,7 @@ public class LiveRyAnchorActivity extends LiveActivity implements LiveFunctionCl public void onSuccess(Message message) { isDRPK = 1; btn_start_dr_pk_view.setVisibility(View.VISIBLE); + mLiveRyLinkMicPkPresenter.setDRInitiator(true); } @Override diff --git a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java index ef1b75824..26205c2d8 100644 --- a/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java +++ b/live/src/main/java/com/yunbao/live/presenter/LiveRyLinkMicPkPresenter.java @@ -155,6 +155,12 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { public static List inputStreamList = new ArrayList<>(); public static List inputStreamList1 = new ArrayList<>(); + private boolean DRInitiator = false;//是否是duorenPK发起人 + + public LiveRyLinkMicPkPresenter setDRInitiator(boolean DRInitiator) { + this.DRInitiator = DRInitiator; + return this; + } private IRCRTCOtherRoomEventsListener otherRoomEventsListener = new IRCRTCOtherRoomEventsListener() { @@ -2457,7 +2463,6 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { * 更新Pk分数 */ public void upDataPkScore(JSONArray pkScores, String uid, int time) { - if (time <= 0) return; String userID1 = (String) imageGrade1.getTag(); String userID2 = (String) imageGrade2.getTag(); String userID4 = (String) imageGrade4.getTag(); @@ -2669,6 +2674,9 @@ public class LiveRyLinkMicPkPresenter implements View.OnClickListener { Bus.get().post(new LiveAudienceEvent() .setType(LiveAudienceEvent.LiveAudienceType.PK_TIME_COUNT)); // endDRGif(); + if (DRInitiator) { + LiveNetManager.get(mContext).jieshuDRPK("" + IMLoginManager.get(mContext).getUserInfo().getId()); + } } } From a808cd13c0cd7fb42de59509aa3ece63738c2b97 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Tue, 7 Feb 2023 17:04:51 +0800 Subject: [PATCH 118/118] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4PK=E6=97=B6=E6=BB=91=E5=8A=A8=E5=88=B0=E4=B8=8B?= =?UTF-8?q?=E4=B8=80=E4=B8=AAPK=E7=9B=B4=E6=92=AD=E9=97=B4=EF=BC=8C?= =?UTF-8?q?=E4=BC=9A=E6=AE=8B=E7=95=99pk=E6=9D=A1=E8=A7=82=E4=BC=97?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yunbao/live/views/PortraitLiveManager.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java index 9e47a6884..6f1dbd1c9 100644 --- a/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java +++ b/live/src/main/java/com/yunbao/live/views/PortraitLiveManager.java @@ -256,6 +256,9 @@ public class PortraitLiveManager implements LivePlayListener, SocketMessageListe public synchronized void onAdd(LiveBean data, int liveType, int liveTypeVal, int liveSdk) { isEnterRoom = false; openParametersModel = new OpenParametersModel(); + if(mLiveRoomViewHolder!=null){ + mLiveRoomViewHolder.UpPkTwo(); + } mContext.runOnUiThread(new Runnable() { @Override