From ae4dea2ab0af96b913e688d7c3c351e441922026 Mon Sep 17 00:00:00 2001 From: max Date: Sun, 28 Apr 2024 17:34:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=81=A2=E5=A4=8D=E6=B8=B8=E6=88=8F?= =?UTF-8?q?=E6=88=BF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 + app/src/main/AndroidManifest.xml | 4 + .../app/avroom/fragment/GameRoomFragment.kt | 181 +++++ .../avroom/fragment/HomePartyFragment.java | 113 ++- .../com/chwl/app/avroom/game/AppConfig.java | 16 + .../com/chwl/app/avroom/game/GameDelegate.kt | 695 ++++++++++++++++++ .../avroom/game/OnGameStatusChangeListener.kt | 13 + .../chwl/app/avroom/game/SudMGPAPPState.java | 61 ++ .../chwl/app/avroom/game/SudMGPMGState.java | 125 ++++ .../java/com/chwl/app/home/HomeViewModel.kt | 62 +- .../chwl/app/home/fragment/HomeFragment.kt | 47 ++ .../ui/webview/room_game/RoomGameJSBridge.kt | 48 ++ .../room_game/RoomGameWebDialogActivity.kt | 123 ++++ .../layout/fragment_chatroom_game_main.xml | 95 ++- .../main/res/layout/fragment_game_room.xml | 144 ++++ app/src/main/res/layout/fragment_home.xml | 39 +- .../main/res/layout/room_game_activity.xml | 10 + app/src/main/res/values-ar/strings.xml | 2 + app/src/main/res/values-zh-rTW/strings.xml | 3 + app/src/main/res/values/strings.xml | 3 + .../com/chwl/core/home/model/HomeModel.kt | 27 + 21 files changed, 1764 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/com/chwl/app/avroom/fragment/GameRoomFragment.kt create mode 100644 app/src/main/java/com/chwl/app/avroom/game/AppConfig.java create mode 100644 app/src/main/java/com/chwl/app/avroom/game/GameDelegate.kt create mode 100644 app/src/main/java/com/chwl/app/avroom/game/OnGameStatusChangeListener.kt create mode 100644 app/src/main/java/com/chwl/app/avroom/game/SudMGPAPPState.java create mode 100644 app/src/main/java/com/chwl/app/avroom/game/SudMGPMGState.java create mode 100644 app/src/main/java/com/chwl/app/ui/webview/room_game/RoomGameJSBridge.kt create mode 100644 app/src/main/java/com/chwl/app/ui/webview/room_game/RoomGameWebDialogActivity.kt create mode 100644 app/src/main/res/layout/fragment_game_room.xml create mode 100644 app/src/main/res/layout/room_game_activity.xml diff --git a/app/build.gradle b/app/build.gradle index 42346f6da..da7ff6fe9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -272,6 +272,8 @@ dependencies { if (!isolationMode && file("../modules/module_google/build.gradle").exists()) { implementation project(':modules:module_google') } + + implementation 'tech.sud.mgp:SudMGP-static:1.3.3.1158' } channel { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 10dc00f19..6cd6bf123 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -667,6 +667,10 @@ android:name=".ui.webview.DialogWebViewActivity" android:theme="@style/dialog_web_view_activity" android:windowSoftInputMode="adjustPan" /> + (), + View.OnClickListener, OnGiftDialogBtnClickListener, IGameRoomView, OnMicroItemClickListener, + OnGameStatusChangeListener { + + companion object { + @JvmStatic + fun newInstance(): GameRoomFragment { + val roomFragment = GameRoomFragment() + val bundle = Bundle() + roomFragment.arguments = bundle + return roomFragment + } + } + + private lateinit var gameBinding: FragmentGameRoomBinding + private lateinit var gameDelegate: GameDelegate + private var isShowMiniMic = false + + override fun getRootLayoutId(): Int { + return R.layout.fragment_game_room + } + + override fun onFindViews() { + super.onFindViews() + gameBinding = DataBindingUtil.bind(mView)!! + gameBinding.lifecycleOwner = this + gameBinding.click = this + gameBinding.ktvModel = false + gameDelegate = GameDelegate( + requireActivity(), + gameBinding.flGameContainer, + AvRoomDataManager.get().mCurrentRoomInfo?.mgId + ) + gameDelegate.setOnGameStatusChangeListener(this) + } + + @SuppressLint("CheckResult") + override fun initiate() { + gameBinding.microView.bindAdapter(GameMicroViewAdapter(context)) + super.initiate() + //游戏模式暂时不需要这个 + PlayerModel.get().stop() + gameBinding.roomInfo = AvRoomDataManager.get().mCurrentRoomInfo + gameBinding.tvShowMiniMic.setOnClickListener { showMiniMic() } + gameBinding.ivShowMic.setOnClickListener { showMic() } + } + + private fun showMiniMic() { + if (isShowMiniMic) return + isShowMiniMic = true + gameBinding.microView.bindAdapter(GameMiniMicroViewAdapter(context).apply { + setOnClick { showMic() } + }) + gameBinding.tvShowMiniMic.isVisible = false + gameBinding.microView.postDelayed({ + gameBinding.ivShowMic.isVisible = true + gameBinding.llMicView.setBackgroundResource(R.drawable.bg_mini_mic_entrance) + }, 100) + } + + private fun showMic() { + if (!isShowMiniMic) return + isShowMiniMic = false + gameBinding.microView.bindAdapter(GameMicroViewAdapter(context)) + gameBinding.tvShowMiniMic.isVisible = true + gameBinding.llMicView.background = null + gameBinding.ivShowMic.isVisible = false + } + + override fun onSetListener() { + super.onSetListener() + bottomView.setBottomViewListener(BaseRoomBottomViewWrapper()) + } + + override fun updateView() { + super.updateView() + gameDelegate.updateGame(AvRoomDataManager.get().mCurrentRoomInfo?.mgId) + gameBinding.roomInfo = AvRoomDataManager.get().mCurrentRoomInfo + if (isSixMic()) { + gameBinding.tvShowMiniMic.isVisible = !isShowMiniMic + gameBinding.ivShowMic.isVisible = isShowMiniMic + } else { + showMic() + gameBinding.tvShowMiniMic.isInvisible = true + gameBinding.ivShowMic.isVisible = false + } + gameBinding.microView.adapter.notifyDataSetChanged() + } + + override fun onGameStart() { + if (isSixMic()) { + showMiniMic() + } + } + + override fun onGameEnd() { + if (isSixMic()) { + showMic() + } + } + + private fun isSixMic(): Boolean { + return AvRoomDataManager.get().mgMicNum == AvRoomDataManager.GAME_DEF_MIC_COUNT + } + + override fun onSendMsgSuccess(msg: String?) { + super.onSendMsgSuccess(msg) + msg?.let { + if (AvRoomDataManager.get().isSelfGamePlaying) { + gameDelegate.hitTheMark(msg) + } + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onFinishAvRoomEvent(event: FinishAvRoomEvent) { + gameDelegate.exitGame() + } + + override fun onStart() { + super.onStart() + gameDelegate.onStart() + } + + override fun onResume() { + super.onResume() + gameDelegate.onResume() + } + + + override fun onPause() { + super.onPause() + gameDelegate.onPause() + } + + override fun onStop() { + super.onStop() + gameDelegate.onStop() + } + + override fun onDestroy() { + gameDelegate.onDestroy() + super.onDestroy() + } + + override fun initWidget() { + super.initWidget() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/chwl/app/avroom/fragment/HomePartyFragment.java b/app/src/main/java/com/chwl/app/avroom/fragment/HomePartyFragment.java index 8bdae69ac..db4b5a0dd 100644 --- a/app/src/main/java/com/chwl/app/avroom/fragment/HomePartyFragment.java +++ b/app/src/main/java/com/chwl/app/avroom/fragment/HomePartyFragment.java @@ -16,9 +16,15 @@ import android.widget.TextView; import androidx.annotation.Nullable; import androidx.databinding.DataBindingUtil; import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import com.chwl.app.avroom.adapter.SelectGameAdapter; +import com.chwl.app.home.helper.OpenRoomHelper; import com.chwl.app.ui.widget.GiftDialog; import com.chwl.app.ui.widget.UserInfoDialog; +import com.chwl.core.room.bean.RoomModeType; +import com.chwl.core.room.game.GameModel; +import com.chwl.core.room.game.bean.GameInfo; import com.chwl.library.utils.JavaUtil; import com.example.lib_utils.UiUtils; import com.netease.nim.uikit.common.util.string.StringUtil; @@ -64,6 +70,7 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.lang.reflect.Field; +import java.util.Objects; import io.reactivex.SingleObserver; import io.reactivex.disposables.Disposable; @@ -98,6 +105,7 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe //收藏房间 private String FOLLOW_ROOM_TYPE = ""; + private SelectGameAdapter gameAdapter; public static HomePartyFragment newInstance() { HomePartyFragment homePartyFragment = new HomePartyFragment(); @@ -216,6 +224,72 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe } } + private void initRvGame() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null || gameAdapter != null) return; + gameMainBinding.rvGame.setLayoutManager(new LinearLayoutManager(mContext)); + gameMainBinding.rvGame.setAdapter(gameAdapter = new SelectGameAdapter()); + gameMainBinding.llSelectGame.setOnClickListener(v -> { + if (gameMainBinding.rvGame.getVisibility() == View.VISIBLE) { + gameMainBinding.rvGame.setVisibility(View.GONE); + gameMainBinding.ivChangeGameArrow.setImageResource(R.drawable.ic_room_arrow_type_below); + } else { + if (!isShowChangeGame()) { + SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_fragment_homepartyfragment_01)); + return; + } + if (AvRoomDataManager.get().isGamePlaying()) { + SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_fragment_homepartyfragment_02)); + } else { + gameMainBinding.rvGame.setVisibility(View.VISIBLE); + gameMainBinding.ivChangeGameArrow.setImageResource(R.drawable.ic_room_arrow_type); + } + } + }); + + gameAdapter.setOnItemClickListener((adapter, view, position) -> { + if (AvRoomDataManager.get().isGamePlaying()) { + SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_fragment_homepartyfragment_03)); + } + if (!isShowChangeGame()) { + SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_fragment_homepartyfragment_04)); + return; + } + + GameInfo gameInfo = gameAdapter.getItem(position); + if (gameInfo != null) { + int type; + long mgId = 0; + if (Objects.equals(ResUtil.getString(R.string.avroom_fragment_homepartyfragment_05), gameInfo.getName())) { + type = RoomInfo.ROOMTYPE_HOME_PARTY; + } else { + type = RoomInfo.ROOMTYPE_GAME; + mgId = JavaUtil.str2long(gameInfo.getMgId()); + } + gameMainBinding.rvGame.setVisibility(View.GONE); + gameMainBinding.ivChangeGameArrow.setImageResource(R.drawable.ic_room_arrow_type_below); + OpenRoomHelper.updateRoomInfo( + getBaseActivity(), + AvRoomDataManager.get().mCurrentRoomInfo, + type, + mgId, + false); + } + }); + } + + //这里的2和4是服务端定义的错误状态 关闭排麦模式和关闭PK模式! + private boolean isShowChangeGame() { + RoomInfo currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + return currentRoomInfo != null && + AvRoomDataManager.get().isRoomOwner() && + currentRoomInfo.getIsPermitRoom() != 1 && + currentRoomInfo.getType() != RoomInfo.ROOM_TYPE_SINGLE && + (currentRoomInfo.getRoomModeType() == RoomModeType.NORMAL_MODE || + currentRoomInfo.getRoomModeType() == 2 || + currentRoomInfo.getRoomModeType() == 4); + } + public void setRoomBg(RoomInfo roomInfo) { if (svgaRoomBg == null) return; updateView(roomInfo); @@ -351,11 +425,11 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe Fragment tempFragment = roomFragment; switch (currentRoomInfo.getType()) { -// case RoomInfo.ROOMTYPE_GAME: -// if (!(tempFragment instanceof GameRoomFragment)) { -// tempFragment = GameRoomFragment.newInstance(); -// } -// break; + case RoomInfo.ROOMTYPE_GAME: + if (!(tempFragment instanceof GameRoomFragment)) { + tempFragment = GameRoomFragment.newInstance(); + } + break; case RoomInfo.ROOM_TYPE_SINGLE: if (!(tempFragment instanceof SingleRoomFragment)) { tempFragment = SingleRoomFragment.newInstance(); @@ -391,6 +465,35 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe ivFollowRoom.setImageResource(AvRoomDataManager.get().isRoomFans ? R.drawable.room_ic_collect_yes : R.drawable.room_ic_collect_no); setIdOnlineData(); + + if (isShowChangeGame()) { + initRvGame(); + gameMainBinding.llChangeGame.setVisibility(View.VISIBLE); + if (AvRoomDataManager.get().isOpenGame()) { + gameMainBinding.tvCurrGame.setText(currentRoomInfo.getMgName()); + } else { + gameMainBinding.tvCurrGame.setText(ResUtil.getString(R.string.avroom_fragment_homepartyfragment_08)); + } + GameModel.INSTANCE.getGameList() + .compose(bindToLifecycle()) + .subscribe(gameInfos -> { + if (AvRoomDataManager.get().isOpenGame()) { + for (int i = 0; i < gameInfos.size(); i++) { + GameInfo gameInfo = gameInfos.get(i); + if (JavaUtil.str2long(gameInfo.getMgId()) == currentRoomInfo.getMgId()) { + gameInfos.remove(i); + break; + } + } + GameInfo gameInfo = new GameInfo(); + gameInfo.setName(ResUtil.getString(R.string.avroom_fragment_homepartyfragment_09)); + gameInfos.add(gameInfo); + } + gameAdapter.setNewData(gameInfos); + }); + } else { + gameMainBinding.llChangeGame.setVisibility(View.GONE); + } } } diff --git a/app/src/main/java/com/chwl/app/avroom/game/AppConfig.java b/app/src/main/java/com/chwl/app/avroom/game/AppConfig.java new file mode 100644 index 000000000..3d4941b1f --- /dev/null +++ b/app/src/main/java/com/chwl/app/avroom/game/AppConfig.java @@ -0,0 +1,16 @@ +/* + Copyright © Sud.Tech + https://sud.tech + */ +package com.chwl.app.avroom.game; + + +import com.chwl.app.BuildConfig; + +public class AppConfig { + + protected static final String APP_ID = "1578948593831571457"; + protected static final String APP_KEY = "J9lHOXvFWkAZiTfl4SK7IGt0wDnW3fWd"; + protected static boolean isTestEnv = BuildConfig.DEBUG; + +} diff --git a/app/src/main/java/com/chwl/app/avroom/game/GameDelegate.kt b/app/src/main/java/com/chwl/app/avroom/game/GameDelegate.kt new file mode 100644 index 000000000..575a25a8a --- /dev/null +++ b/app/src/main/java/com/chwl/app/avroom/game/GameDelegate.kt @@ -0,0 +1,695 @@ +package com.chwl.app.avroom.game + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.text.TextUtils +import android.util.Log +import android.view.View +import android.view.ViewTreeObserver.OnGlobalLayoutListener +import android.widget.FrameLayout +import com.google.gson.Gson +import com.chwl.app.R +import com.chwl.core.auth.AuthModel +import com.chwl.core.manager.AvRoomDataManager +import com.chwl.core.room.game.bean.GameCfg +import com.chwl.core.room.game.GameModel +import com.chwl.core.room.game.GameStatus +import com.chwl.core.room.model.HomePartyModel +import com.chwl.core.user.UserModel +import com.chwl.core.utils.LogUtils +import com.chwl.core.utils.net.RxHelper +import com.chwl.library.language.LanguageHelper +import com.chwl.library.net.rxnet.callback.CallBack +import com.chwl.library.utils.SingleToastUtil +import okhttp3.* +import org.json.JSONException +import org.json.JSONObject +import tech.sud.mgp.core.* +import java.util.* + +class GameDelegate(val activity: Activity, val container: FrameLayout, var mgId: Long?) { + + private val TAG = "GameDelegate" + private var APP_CODE = "" + + private val mRoomID :String get() = AvRoomDataManager.get().roomUid.toString() + private var mLanguage = "zh-TW" //語言 + + //調用遊戲SDK的接口,成功加載遊戲後可用: + private var iSudFSTAPP: ISudFSTAPP? = null + + private val gson = Gson() + + //小遊戲ID + private var mMGID = 0L + + //通用狀態-遊戲,關鍵詞 + private var mKeyWord: String? = null + private val mUid = AuthModel.get().currentUid.toString() + + private val homePartyModel = HomePartyModel() + + private var onGameStatusChangeListener: OnGameStatusChangeListener? = null + + fun setOnGameStatusChangeListener(onGameStatusChangeListener: OnGameStatusChangeListener) { + this.onGameStatusChangeListener = onGameStatusChangeListener + } + + private val loginCallback: AppLoginListener = + object : AppLoginListener { + override fun onLoginFailure(err: String?) { + SingleToastUtil.showToast(err) + } + + override fun onLoginSuccess(new_code: String, expire_Date: Long) { + APP_CODE = new_code + Handler(Looper.getMainLooper()).post { + //初始化遊戲SDK + initGameSDK( + activity, + AppConfig.APP_ID, + AppConfig.APP_KEY, + AppConfig.isTestEnv + ) + } + } + + } + + init { + mMGID = mgId ?: 0L + mLanguage = getGameLanguage() + login(loginCallback) + } + + fun updateGame(mgId: Long?) { + if (mgId == null || mgId == 0L) return + if (mgId == mMGID && iSudFSTAPP != null) { + return + } + mMGID = mgId + updateMyMicQueue(GameStatus.STATUS_NOT_JOIN) + loadMG(activity, mUid, mRoomID, APP_CODE, mMGID, mLanguage) + } + + fun exitGame() { + UserModel.get().cacheLoginUserInfo?.gameStatus = GameStatus.STATUS_NOT_JOIN + notifySelfPlayingState(false) + notifySelfInState(false) + } + + /** + * 例如"你畫我猜"遊戲的文字命中 + */ + fun hitTheMark(msg: String) { + mKeyWord?.let { + if (msg.contains(it)) { + notifySelfTextHit(it, msg) + } + } + } + + /** + * "接入方客戶端"登陸接口, 從"接入方服務端"獲得Code + * "接入方服務端"是通過"服務端接入SDK"獲得Code來返回給"接入方客戶端"的 + * @param listener + */ + @SuppressLint("CheckResult") + private fun login(listener: AppLoginListener) { + GameModel.getGameCode() + .compose(RxHelper.bindContext(activity)) + .subscribe({ + listener.onLoginSuccess(it.code, it.expireDate) + }, { + listener.onLoginFailure(it.message) + }) + + } + + /** + * 1,初始化遊戲SDK + * + * @param context 上下文 + * @param appID appID + * @param appKey appKey + * @param isTestEnv 是否是測試環境,true:測試環境,false:正式環境 + */ + private fun initGameSDK(context: Context, appID: String, appKey: String, isTestEnv: Boolean) { + SudMGP.initSDK(context, appID, appKey, isTestEnv, object : ISudListenerInitSDK { + override fun onSuccess() { + loadMG(activity, mUid, mRoomID, APP_CODE, mMGID, mLanguage) + } + + override fun onFailure(code: Int, errInfo: String) { + val msg = context.getString(R.string.game_failed_tips).format("$code-${errInfo}") + showToast(msg) + } + }) + + } + + /** + * 2,加載遊戲 + * + * @param activity 上下文Activity + * @param userID 用戶ID,業務系統保證每個用戶擁有唯一ID + * @param roomID 房間ID,進入同一房間內的 + * @param code 令牌 + * @param mgID 小遊戲ID + * @param language 遊戲語言 現支持,簡體:zh-CN 繁體:zh-TW 英語:en-US 馬來語:ms-MY + */ + private fun loadMG( + activity: Activity, + userID: String, + roomID: String, + code: String, + mgID: Long, + language: String + ) { + iSudFSTAPP?.destroyMG() + iSudFSTAPP = SudMGP.loadMG(activity, userID, roomID, code, mgID, language, mISudFSMMG) + iSudFSTAPP?.apply { + addGameView(gameView) + } + } + + /** + * 3,將遊戲view添加到我們的布局當中 + * + * @param gameView + */ + private fun addGameView(gameView: View) { + container.removeAllViews() + container.addView(gameView) + } + + private fun showToast(content: String?) { + SingleToastUtil.showToast(content) + } + + + /** + * 通知"文字命中狀態"到遊戲端 + * + * @param iSudFSTAPP + * @param keyWord + */ + private fun notifySelfTextHit(keyWord: String?, msg: String) { + LogUtils.d("notifySelfTextHit") + try { + //狀態名稱 + val state: String = SudMGPAPPState.APP_COMMON_SELF_TEXT_HIT + + //狀態數據 + val jsonObject = JSONObject() + jsonObject.put("isHit", true) // true 命中,false 未命中 + jsonObject.put("keyWord", keyWord) // true 命中,false 未命中 + jsonObject.put("text", msg) // 聊天原始內容,這裏的值只是一個示例,意指內容當中包含關鍵詞則命中,具體按業務規則定。 + val dataJson = jsonObject.toString() + //調用接口 + iSudFSTAPP?.notifyStateChange(state, dataJson, null) + } catch (e: Exception) { + e.printStackTrace() + } + } + + /** + * 設置當前關鍵詞 + * + * @param keyWord + */ + private fun setKeyWord(keyWord: String?) { + mKeyWord = keyWord + } + + private fun getGameLanguage(): String { + return when (LanguageHelper.getCurrentLanguageType()) { + LanguageHelper.ZH -> { + "zh-TW" + } + + LanguageHelper.AR -> { + "ar-SA" + } + + else -> { + "en-US" + } + } + } + + /** + * 遊戲SDK調用app的接口 + */ + private val mISudFSMMG: ISudFSMMG = object : ISudFSMMG { + + override fun onGameLog(p0: String?) { + LogUtils.d(p0) + } + + override fun onGameLoadingProgress(p0: Int, p1: Int, p2: Int) { + + } + + override fun onGameStarted() { + } + + override fun onGameDestroyed() { + } + + /** + * 回調此方法,表示令牌過期,此時需要刷新令牌並使用ISudFSMStateHandle回調 + * @param handle + * @param dataJson + */ + override fun onExpireCode(handle: ISudFSMStateHandle, dataJson: String) { + login(object : AppLoginListener { + override fun onLoginFailure(err: String?) { + + } + + override fun onLoginSuccess(new_code: String, expire_Date: Long) { + APP_CODE = new_code + try { + val jsonObject = JSONObject() + jsonObject.put("ret_code", 0) + jsonObject.put("ret_msg", "success") + handle.success(jsonObject.toString()) + } catch (e: JSONException) { + e.printStackTrace() + } + iSudFSTAPP?.updateCode(APP_CODE, null) + } + + }) + } + + /** + * 處理獲取遊戲視圖信息 + * @param handle + * @param dataJson + */ + override fun onGetGameViewInfo(handle: ISudFSMStateHandle, dataJson: String) { + //拿到遊戲View的寬高 + val gameViewWidth = container.measuredWidth + val gameViewHeight = container.measuredHeight + if (gameViewWidth > 0 && gameViewHeight > 0) { + notifyGameViewInfo(handle, gameViewWidth, gameViewHeight) + return + } + + //如果遊戲View未加載完成,則監聽加載完成時回調 + container.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener { + override fun onGlobalLayout() { + container.viewTreeObserver.removeOnGlobalLayoutListener(this) + val width = container.measuredWidth + val height = container.measuredHeight + notifyGameViewInfo(handle, width, height) + } + }) + } + + override fun onGetGameCfg(handle: ISudFSMStateHandle?, p1: String?) { + handle?.success(gson.toJson(GameCfg())) + } + + /** + * 通知遊戲,遊戲視圖信息 + * @param handle + * @param gameViewWidth + * @param gameViewHeight + */ + private fun notifyGameViewInfo( + handle: ISudFSMStateHandle, + gameViewWidth: Int, + gameViewHeight: Int + ) { + try { + val jsonObject = JSONObject() + jsonObject.put("ret_code", 0) + jsonObject.put("ret_msg", "success") + + //遊戲View大小 + val viewSize = JSONObject() + viewSize.put("width", gameViewWidth) + viewSize.put("height", gameViewHeight) + jsonObject.put("view_size", viewSize) + + //遊戲安全操作區域 + val viewGameRect = JSONObject() + viewGameRect.put("left", 0) + viewGameRect.put("top", container.context.resources.getDimensionPixelOffset(R.dimen.dp_180)) + viewGameRect.put("right", 0) + viewGameRect.put("bottom", container.context.resources.getDimensionPixelOffset(R.dimen.dp_150)) + jsonObject.put("view_game_rect", viewGameRect) + + //通知遊戲 + val json = jsonObject.toString() + Log.d(TAG, "notifyGameViewInfo:$json") + handle.success(json) + } catch (e: JSONException) { + e.printStackTrace() + } + } + + /** + * 遊戲狀態變化 + * @param handle + * @param state 狀態名 + * @param dataJson 狀態數據,json字符串 + */ + override fun onGameStateChange( + handle: ISudFSMStateHandle, + state: String, + dataJson: String + ) { + Log.d(TAG, "onGameStateChange state:$state--dataJson:$dataJson") + when (state) { + //SudMGPMGState.MG_COMMON_PUBLIC_MESSAGE -> showToast("遊戲:公屏消息") + SudMGPMGState.MG_COMMON_KEY_WORD_TO_HIT -> { + if (TextUtils.isEmpty(dataJson)) { + setKeyWord(null) + } else { + try { + val jsonObject = JSONObject(dataJson) + if (jsonObject.isNull("word")) { + setKeyWord(null) + } else { + val keyWord = jsonObject.getString("word") + setKeyWord(keyWord) + } + } catch (e: Exception) { + e.printStackTrace() + } + } + } + SudMGPMGState.APP_COMMON_SELF_CLICK_JOIN_BTN -> { + + try { + val jsonObject = JSONObject(dataJson) + val seatIndex = jsonObject.optInt("seatIndex", -1) + updateMyMicQueue(GameStatus.STATUS_NOT_READY, true, seatIndex) + } catch (e: Exception) { + e.printStackTrace() + } + + } + SudMGPMGState.APP_COMMON_SELF_CLICK_START_BTN -> { + notifySelfPlayingState(true) + } + SudMGPMGState.MG_COMMON_GAME_STATE -> handleGameState(dataJson) + } + } + + /** + * 玩家狀態變化 + * @param handle + * @param userId 玩家用戶ID + * @param state 狀態名 + * @param dataJson 狀態數據,json字符串。參考文檔 + */ + override fun onPlayerStateChange( + handle: ISudFSMStateHandle, + userId: String, + state: String, + dataJson: String + ) { + Log.d(TAG, "onPlayerStateChange userId:$userId--state:$state--dataJson:$dataJson") + when (state) { + SudMGPMGState.MG_COMMON_PLAYER_IN -> handlePlayerIn(userId, dataJson) + SudMGPMGState.MG_COMMON_PLAYER_READY -> handlePlayerReady(userId, dataJson) + SudMGPMGState.MG_COMMON_PLAYER_CAPTAIN -> handlePlayerCaptain(dataJson) + SudMGPMGState.MG_COMMON_PLAYER_PLAYING -> handlePlayerPlaying(userId, dataJson) + } + } + } + + private fun handlePlayerIn(userId: String, dataJson: String) { + if (userId != mUid) return + try { + val jsonObject = JSONObject(dataJson) + val retCode = jsonObject.getInt("retCode") + val isIn = jsonObject.getBoolean("isIn") + if (retCode != 0) { + return + } + if (isIn) { // 已加入 + if (AvRoomDataManager.get().isRoomOwner) { + notifySelfCaptainState(mUid) + } + } else { // 未加入 + var reason = 0 + if (jsonObject.has("reason")) { + reason = jsonObject.getInt("reason") + } + if (reason == 0) { + updateMyMicQueue(GameStatus.STATUS_NOT_JOIN) + } else if (reason == 1) { + updateMyMicQueue(GameStatus.STATUS_NOT_JOIN) + } + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun updateMyMicQueue(gameStatus: Int, isJoin: Boolean = false, seatIndex: Int = -1) { + UserModel.get().cacheLoginUserInfo?.gameStatus = gameStatus + val position = AvRoomDataManager.get().getMicPosition(mUid) + if (position != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (isJoin) notifySelfInState(true, seatIndex) + homePartyModel.updateMyMicQueue( + position, + AvRoomDataManager.get().roomId.toString(), + UserModel.get().cacheLoginUserInfo + ).subscribe() + } else if (isJoin) { + val upPosition = AvRoomDataManager.get().findGamePosition() + if (upPosition == Int.MIN_VALUE) { + showToast("當前遊戲人數已滿!") + } else { + UserModel.get().cacheLoginUserInfo?.gameStatus = 1 + homePartyModel.upMicroPhone(upPosition, + mUid, + AvRoomDataManager.get().roomId.toString(), + false, object : CallBack { + override fun onSuccess(data: String?) { + notifySelfInState(true, seatIndex) + } + + override fun onFail(code: Int, error: String?) { + showToast(error) + } + + }) + } + } + } + + private fun handlePlayerReady(userId: String, dataJson: String) { + if (userId != mUid) return + try { + val jsonObject = JSONObject(dataJson) + val retCode = jsonObject.getInt("retCode") + val isReady = jsonObject.getBoolean("isReady") + if (retCode != 0) { + return + } + updateMyMicQueue(if (isReady) GameStatus.STATUS_READY else GameStatus.STATUS_NOT_READY) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun handlePlayerCaptain(dataJson: String) { + try { + val jsonObject = JSONObject(dataJson) + val retCode = jsonObject.getInt("retCode") + if (retCode != 0) { + return + } + + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun handleGameState(dataJson: String) { + try { + val jsonObject = JSONObject(dataJson) + val gameState = jsonObject.getInt("gameState") + if (gameState == 0) { + onGameStatusChangeListener?.onGameEnd() + } else if (gameState == 2) { + onGameStatusChangeListener?.onGameStart() + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun handlePlayerPlaying(userId: String, dataJson: String) { + if (userId != mUid) return + try { + val jsonObject = JSONObject(dataJson) + val retCode = jsonObject.getInt("retCode") + if (retCode != 0) { + return + } + val isPlaying = jsonObject.getBoolean("isPlaying") + if (isPlaying) { + updateMyMicQueue(GameStatus.STATUS_PLAYING) + } else { + updateMyMicQueue(GameStatus.STATUS_NOT_READY) + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun notifySelfInState(isIn: Boolean, seatIndex: Int = -1) { + try { + if (!isIn) { + notifySelfReadyState(false) + } + //狀態名稱 + val state = SudMGPAPPState.APP_COMMON_SELF_IN + //狀態數據 + val jsonObject = JSONObject() + jsonObject.put("isIn", isIn) // true 加入遊戲,false 退出遊戲 + if (seatIndex != -1) { + jsonObject.put("seatIndex", seatIndex) + } + jsonObject.put("teamId", 1) //哪一隊伍(2v2,4v4) + val dataJson = jsonObject.toString() + + //調用接口 + iSudFSTAPP?.notifyStateChange(state, dataJson, null) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun notifySelfReadyState(isReady: Boolean) { + try { + //狀態名稱 + val state = SudMGPAPPState.APP_COMMON_SELF_READY + + //狀態數據 + val jsonObject = JSONObject() + jsonObject.put("isReady", isReady) // true 準備,false 取消準備 + val dataJson = jsonObject.toString() + + //調用接口 + iSudFSTAPP?.notifyStateChange(state, dataJson, null) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun notifySelfPlayingState(isPlaying: Boolean) { + try { + //狀態名稱 + val state = SudMGPAPPState.APP_COMMON_SELF_PLAYING + + //狀態數據 + val jsonObject = JSONObject() + jsonObject.put("isPlaying", isPlaying) // true 開始遊戲,false 結束遊戲 + val dataJson = jsonObject.toString() + + //調用接口 + iSudFSTAPP?.notifyStateChange(state, dataJson, null) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun notifySelfCaptainState(uid: String) { + try { + //狀態名稱 + val state = SudMGPAPPState.APP_COMMON_SELF_CAPTAIN + + //狀態數據 + val jsonObject = JSONObject() + jsonObject.put("curCaptainUID", uid) // 必填,指定隊長uid + val dataJson = jsonObject.toString() + + //調用接口 + iSudFSTAPP?.notifyStateChange(state, dataJson, null) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun notifySelfKickState(uid: String) { + try { + //狀態名稱 + val state = SudMGPAPPState.APP_COMMON_SELF_KICK + + //狀態數據 + val jsonObject = JSONObject() + jsonObject.put("kickedUID", uid) // 被踢用戶uid + val dataJson = jsonObject.toString() + + //調用接口 + iSudFSTAPP?.notifyStateChange(state, dataJson, null) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun notifySelfEndState() { + try { + //狀態名稱 + val state = SudMGPAPPState.APP_COMMON_SELF_END + + //狀態數據 + val jsonObject = JSONObject() + val dataJson = jsonObject.toString() + + //調用接口 + iSudFSTAPP?.notifyStateChange(state, dataJson, null) + } catch (e: Exception) { + e.printStackTrace() + } + } + + fun onStart() { + iSudFSTAPP?.startMG() //啟動遊戲 + } + + fun onResume() { + iSudFSTAPP?.playMG() //開始遊戲 + } + + fun onPause() { + iSudFSTAPP?.pauseMG() //暫停遊戲 + } + + fun onStop() { + iSudFSTAPP?.stopMG() //停止遊戲 + } + + fun onDestroy() { + updateMyMicQueue(GameStatus.STATUS_NOT_JOIN) + iSudFSTAPP?.destroyMG() + } + +} + +internal interface AppLoginListener { + /** + * App Server 登陸失敗, App Server 不能返回CODE + */ + fun onLoginFailure(err: String?) + + /** + * App Server 登陸成功, App Server調用服務端接入SDK的API獲取Code 返回給 App + * App 就要用CODE和自己生成的UserID去調用SDK的初始化函數,登陸小遊戲 + * 小遊戲登陸成功後,其UserID,就是App傳的UserID + */ + fun onLoginSuccess(new_code: String, expire_Date: Long) +} \ No newline at end of file diff --git a/app/src/main/java/com/chwl/app/avroom/game/OnGameStatusChangeListener.kt b/app/src/main/java/com/chwl/app/avroom/game/OnGameStatusChangeListener.kt new file mode 100644 index 000000000..0b5fc1e14 --- /dev/null +++ b/app/src/main/java/com/chwl/app/avroom/game/OnGameStatusChangeListener.kt @@ -0,0 +1,13 @@ +package com.chwl.app.avroom.game + +interface OnGameStatusChangeListener { + /** + * 游戏开始 + */ + fun onGameStart() + + /** + * 游戏结束 + */ + fun onGameEnd() +} \ No newline at end of file diff --git a/app/src/main/java/com/chwl/app/avroom/game/SudMGPAPPState.java b/app/src/main/java/com/chwl/app/avroom/game/SudMGPAPPState.java new file mode 100644 index 000000000..667b34c45 --- /dev/null +++ b/app/src/main/java/com/chwl/app/avroom/game/SudMGPAPPState.java @@ -0,0 +1,61 @@ +/* + Copyright © Sud.Tech + https://sud.tech + */ +package com.chwl.app.avroom.game; + +/** + * Time:2021/10/19 + * Description: APP to MG 的状态定义 + */ +public class SudMGPAPPState { + + // region 通用状态 + + /** + * 加入状态 + * 最低版本: v1.1.30.xx + */ + public static final String APP_COMMON_SELF_IN = "app_common_self_in"; + + /** + * 准备状态 + * 最低版本: v1.1.30.xx + */ + public static final String APP_COMMON_SELF_READY = "app_common_self_ready"; + + /** + * 游戏状态 + * 最低版本: v1.1.30.xx + */ + public static final String APP_COMMON_SELF_PLAYING = "app_common_self_playing"; + + /** + * 队长状态 + * 最低版本: v1.1.30.xx + */ + public static final String APP_COMMON_SELF_CAPTAIN = "app_common_self_captain"; + + /** + * 踢人 + * v1.1.30.xx + */ + public static final String APP_COMMON_SELF_KICK = "app_common_self_kick"; + + /** + * 结束游戏 + * v1.1.30.xx + */ + public static final String APP_COMMON_SELF_END = "app_common_self_end"; + + /** + * 麦克风状态 + */ + public static final String APP_COMMON_SELF_MICROPHONE = "app_common_self_microphone"; + + /** + * 文字命中状态 + */ + public static final String APP_COMMON_SELF_TEXT_HIT = "app_common_self_text_hit"; + +} diff --git a/app/src/main/java/com/chwl/app/avroom/game/SudMGPMGState.java b/app/src/main/java/com/chwl/app/avroom/game/SudMGPMGState.java new file mode 100644 index 000000000..b4309738e --- /dev/null +++ b/app/src/main/java/com/chwl/app/avroom/game/SudMGPMGState.java @@ -0,0 +1,125 @@ +/* + Copyright © Sud.Tech + https://sud.tech + */ +package com.chwl.app.avroom.game; + +/** + * Time:2021/10/19 + * Description: MG to APP 的状态定义 + */ +public class SudMGPMGState { + + // region 通用状态-游戏 + + /** + * 公屏消息 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PUBLIC_MESSAGE = "mg_common_public_message"; + + /** + * 关键词状态 + */ + public static final String MG_COMMON_KEY_WORD_TO_HIT = "mg_common_key_word_to_hit"; + + // endregion 通用状态-游戏 + + + // region 通用状态-玩家 + + /** + * 加入状态 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PLAYER_IN = "mg_common_player_in"; + + /** + * 准备状态 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PLAYER_READY = "mg_common_player_ready"; + + /** + * 队长状态 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PLAYER_CAPTAIN = "mg_common_player_captain"; + + /** + * 游戏状态 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PLAYER_PLAYING = "mg_common_player_playing"; + + /** + * 游戏状态(已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_GAME_STATE = "mg_common_game_state"; + + // endregion 通用状态-玩家 + + + // region 碰碰我最强 + // endregion 碰碰我最强 + + // region 飞刀达人 + // endregion 飞刀达人 + + // region 你画我猜 + + /** + * 选词中 + */ + public static final String MG_DG_SELECTING = "mg_dg_selecting"; + + /** + * 作画中 + */ + public static final String MG_DG_PAINTING = "mg_dg_painting"; + + /** + * 错误答案 + */ + public static final String MG_DG_ERRORANSWER = "mg_dg_erroranswer"; + + /** + * 总积分 + */ + public static final String MG_DG_TOTALSCORE = "mg_dg_totalscore"; + + /** + * 本次积分 + */ + public static final String MG_DG_SCORE = "mg_dg_score"; + + // endregion 你画我猜 + + + /** + * 加入游戏按钮点击状态 + */ + public static final String APP_COMMON_SELF_CLICK_JOIN_BTN = "mg_common_self_click_join_btn"; + /** + * 取消加入游戏按钮点击状态 + */ + public static final String APP_COMMON_SELF_CLICK_CANCEL_JOIN_BTN = "mg_common_self_click_cancel_join_btn"; + /** + * 准备按钮点击状态 + */ + public static final String APP_COMMON_SELF_CLICK_READY_BTN = "mg_common_self_click_ready_btn"; + /** + * 取消准备按钮点击状态 + */ + public static final String APP_COMMON_SELF_CLICK_CANCEL_READY_BTN = "mg_common_self_click_cancel_ready_btn"; + /** + * 开始游戏按钮点击状态 + */ + public static final String APP_COMMON_SELF_CLICK_START_BTN = "mg_common_self_click_start_btn"; + /** + * 分享按钮点击状态 + */ + public static final String APP_COMMON_SELF_CLICK_SHARE_BTN = "mg_common_self_click_share_btn"; + +} diff --git a/app/src/main/java/com/chwl/app/home/HomeViewModel.kt b/app/src/main/java/com/chwl/app/home/HomeViewModel.kt index d217945a8..0c0ccafe2 100644 --- a/app/src/main/java/com/chwl/app/home/HomeViewModel.kt +++ b/app/src/main/java/com/chwl/app/home/HomeViewModel.kt @@ -19,13 +19,13 @@ class HomeViewModel : BaseViewModel() { // private val _bannerLiveData = MutableLiveData?>() val bannerLiveData: MutableLiveData?> = _bannerLiveData -// -// private val _currentResourceLiveData = MutableLiveData?>() -// val currentResourceLiveData: MutableLiveData?> = _currentResourceLiveData -// -// private val _resourceJumpLiveData = MutableLiveData() -// val resourceJumpLiveData: LiveData = _resourceJumpLiveData -// + + private val _currentResourceLiveData = MutableLiveData?>() + val currentResourceLiveData: MutableLiveData?> = _currentResourceLiveData + + private val _resourceJumpLiveData = MutableLiveData() + val resourceJumpLiveData: LiveData = _resourceJumpLiveData + // private val _homeChatPickLiveData = MutableLiveData() // val homeChatPickLiveData: LiveData = _homeChatPickLiveData @@ -73,31 +73,31 @@ class HomeViewModel : BaseViewModel() { // ) // } -// /** -// * 首页改版资源位 -// */ -// fun getCurrentResourceInfo() { -// safeLaunch( -// onError = { -// _currentResourceLiveData.value = null -// }, -// block = { -// _currentResourceLiveData.value = HomeModel.getCurrentResource() -// } -// ) -// } + /** + * 首页改版资源位 + */ + fun getCurrentResourceInfo() { + safeLaunch( + onError = { + _currentResourceLiveData.value = null + }, + block = { + _currentResourceLiveData.value = HomeModel.getCurrentResource() + } + ) + } -// fun getResourceJumpInfo(id: Int) { -// safeLaunch( -// onError = { -// _resourceJumpLiveData.value = null -// it.message.toast() -// }, -// block = { -// _resourceJumpLiveData.value = HomeModel.getResourceJumpInfo(id) -// } -// ) -// } + fun getResourceJumpInfo(id: Int) { + safeLaunch( + onError = { + _resourceJumpLiveData.value = null + it.message.toast() + }, + block = { + _resourceJumpLiveData.value = HomeModel.getResourceJumpInfo(id) + } + ) + } // // fun getHomeChatPick() { // safeLaunch( diff --git a/app/src/main/java/com/chwl/app/home/fragment/HomeFragment.kt b/app/src/main/java/com/chwl/app/home/fragment/HomeFragment.kt index 7484b887f..6238662ed 100644 --- a/app/src/main/java/com/chwl/app/home/fragment/HomeFragment.kt +++ b/app/src/main/java/com/chwl/app/home/fragment/HomeFragment.kt @@ -1,15 +1,19 @@ package com.chwl.app.home.fragment import android.view.View +import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import com.chwl.app.R import com.chwl.app.application.IReportConstants import com.chwl.app.application.ReportManager +import com.chwl.app.avroom.activity.AVRoomActivity import com.chwl.app.base.BaseViewBindingFragment import com.chwl.app.databinding.FragmentHomeBinding import com.chwl.app.home.HomeViewModel import com.chwl.app.home.adapter.HomeBannerAdapter +import com.chwl.app.home.dialog.RecommendRoomDialog import com.chwl.app.ui.search.SearchActivity +import com.chwl.app.ui.utils.load import com.chwl.app.ui.webview.CommonWebViewActivity import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil import com.chwl.app.utils.CommonJumpHelper @@ -32,6 +36,49 @@ class HomeFragment : BaseViewBindingFragment(), View.OnClic initBanner() childFragmentManager.beginTransaction() .replace(R.id.frameLayout, RecommendFragment(), "RECOMMEND").commitAllowingStateLoss() + + homeViewModel.currentResourceLiveData.observe(this) { + it?.let { + val resourceViews = arrayOf( + binding.ivResource0, + binding.ivResource1 + ) + if (it.size != 2) { + resourceViews.forEach { + it.isVisible = false + } + return@observe + } + resourceViews.forEach { + it.isVisible = true + } + for (i in resourceViews.indices) { + resourceViews[i].load(it[i].icon) + resourceViews[i].setOnClickListener { _ -> + when { + it[i].resourceType == 5 -> { + CommonWebViewActivity.start(context, it[i].resourceContent) + } + else -> { + dialogManager.showProgressDialog(mContext) + homeViewModel.getResourceJumpInfo(it[i].id) + } + } + } + } + } + } + homeViewModel.resourceJumpLiveData.observe(this) { + dialogManager.dismissDialog() + it?.let { + if (it.isPick) { + AVRoomActivity.start(context, it.uid) + } else { + RecommendRoomDialog.newInstance(it).show(context) + } + } + } + homeViewModel.getCurrentResourceInfo() } private fun initListener() { diff --git a/app/src/main/java/com/chwl/app/ui/webview/room_game/RoomGameJSBridge.kt b/app/src/main/java/com/chwl/app/ui/webview/room_game/RoomGameJSBridge.kt new file mode 100644 index 000000000..6d8cd99d7 --- /dev/null +++ b/app/src/main/java/com/chwl/app/ui/webview/room_game/RoomGameJSBridge.kt @@ -0,0 +1,48 @@ +package com.chwl.app.ui.webview.room_game + +import android.webkit.JavascriptInterface +import androidx.annotation.Keep +import com.chwl.app.ui.pay.ChargeActivity +import com.example.lib_utils.log.ILog +import org.json.JSONObject + +@Keep +class RoomGameJSBridge(val activity: RoomGameWebDialogActivity) : ILog { + + @JavascriptInterface + public fun getConfig(params: String) { + logD("getConfig()") + try { + val obj = JSONObject(params) + callJs("") + } catch (ex: Exception) { + ex.printStackTrace() + } + } + + @JavascriptInterface + public fun destroy(params: String) { + logD("游戏调⽤destroy") + activity.runOnUiThread { + activity.finish() + } + } + + @JavascriptInterface + public fun gameRecharge(params: String) { + logD("游戏调⽤gameRecharge") + activity.runOnUiThread { + ChargeActivity.start(activity) + } + } + + @JavascriptInterface + public fun gameLoaded(params: String) { + logD("游戏调⽤gameLoaded") + //游戏加载完毕 + } + + private fun callJs(str: String) { + activity.callJs(str) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/chwl/app/ui/webview/room_game/RoomGameWebDialogActivity.kt b/app/src/main/java/com/chwl/app/ui/webview/room_game/RoomGameWebDialogActivity.kt new file mode 100644 index 000000000..ba8a91b4e --- /dev/null +++ b/app/src/main/java/com/chwl/app/ui/webview/room_game/RoomGameWebDialogActivity.kt @@ -0,0 +1,123 @@ +package com.chwl.app.ui.webview.room_game + +import android.annotation.SuppressLint +import android.net.http.SslError +import android.os.Build +import android.view.View +import android.view.WindowManager +import android.webkit.SslErrorHandler +import android.webkit.WebSettings +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.appcompat.app.AlertDialog +import com.chwl.app.R +import com.chwl.app.base.BaseViewBindingActivity +import com.chwl.app.databinding.RoomGameActivityBinding +import com.chwl.core.auth.AuthModel +import com.chwl.core.pay.event.UpdateWalletInfoEvent +import com.chwl.library.utils.ResUtil +import com.google.gson.Gson +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode + +class RoomGameWebDialogActivity : BaseViewBindingActivity() { + + override fun init() { + window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_FULLSCREEN + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) + window.setLayout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT + ) + initView() + } + + private fun initView() { + initWebView() + binding.webView.loadUrl("https://baidu.com") + } + + @SuppressLint("SetJavaScriptEnabled", "JavascriptInterface") + private fun initWebView() { + //防⽌⽤浏览器打开⽹⻚ + binding.webView.webViewClient = object : WebViewClient() { + + override fun onReceivedSslError( + view: WebView, + handler: SslErrorHandler, + error: SslError? + ) { + // super.onReceivedSslError(view, handler, error); + val builder = AlertDialog.Builder(view.context) + builder.setMessage(ResUtil.getString(R.string.ui_webview_commonwebviewactivity_07)) + builder.setPositiveButton( + ResUtil.getString(R.string.ui_webview_commonwebviewactivity_08) + ) { dialog, which -> + handler.proceed() // 接受https所有网站的证书 + } + builder.setNegativeButton( + ResUtil.getString(R.string.ui_webview_commonwebviewactivity_09) + ) { dialog, which -> handler.cancel() } + val dialog = builder.create() + dialog.show() + } + } + //设置webview背景透明,默认为⽩⾊ + binding.webView.setBackgroundColor(0) + //设置view背景透明,默认为⽩⾊ 可选(单独activity添加webView组件时需要添加) + binding.root.setBackgroundColor(0) + + val settings = binding.webView.settings + //设置⽀持Javascript + settings.javaScriptEnabled = true + //设置默认⽂本编码 + settings.defaultTextEncodingName = "UTF-8" + //设置可访问本地⽂件 + settings.allowFileAccess = true + //设置允许通过file url加载的Javascript读取全部资源(包括⽂件,http,https) + settings.allowUniversalAccessFromFileURLs = true + //设置优先加载缓存 + settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK + //设置启⽤HTML5 DOM storage + settings.domStorageEnabled = true + //设置开启数据库缓存 + settings.databaseEnabled = true + settings.databasePath = (applicationContext.filesDir.absolutePath) + //设置⽀持缩放 + settings.setSupportZoom(true); + //设置⾃适应 + settings.setUseWideViewPort(true); + //设置⾃动播放媒体 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + settings.mediaPlaybackRequiresUserGesture = false + } + //设置5.0以上允许加载http和https混合的⻚⾯ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW + } + + //游戏调⽤的类,必须定义为 NativeBridge + binding.webView.addJavascriptInterface(RoomGameJSBridge(this), "NativeBridge") + } + + fun callJs(str: String) { + binding.webView.post { + binding.webView.loadUrl("javascript:$str") + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onWalletInfoUpdate(event: UpdateWalletInfoEvent?) { + updateGameWallet() + } + + private fun updateGameWallet() { + //数据只是参考值,需要根据⾃⼰APP进⾏赋值 + val map = HashMap() + map["userId"] = AuthModel.get().currentUid + val str = "walletUpdate" + "(" + Gson().toJson(map) + ")" + this.callJs(str) + } +} diff --git a/app/src/main/res/layout/fragment_chatroom_game_main.xml b/app/src/main/res/layout/fragment_chatroom_game_main.xml index 70f7e40f4..16f6c3e79 100644 --- a/app/src/main/res/layout/fragment_chatroom_game_main.xml +++ b/app/src/main/res/layout/fragment_chatroom_game_main.xml @@ -34,27 +34,40 @@ android:layout_width="match_parent" android:layout_height="match_parent" /> - + + + android:src="@drawable/arrow_left_white" + app:layout_constraintBottom_toBottomOf="@id/space_title_bar" + app:layout_constraintStart_toStartOf="@id/space_title_bar" + app:layout_constraintTop_toTopOf="@id/space_title_bar" /> + android:orientation="vertical" + app:layout_constraintBottom_toBottomOf="@id/space_title_bar" + app:layout_constraintStart_toEndOf="@id/iv_back" + app:layout_constraintTop_toTopOf="@id/space_title_bar"> - + + + + + + + + + + + + + + + + android:src="@drawable/room_ic_collect_no" + app:layout_constraintBottom_toBottomOf="@id/space_title_bar" + app:layout_constraintEnd_toStartOf="@id/room_more" + app:layout_constraintTop_toTopOf="@id/space_title_bar" /> + android:src="@drawable/room_ic_more" + app:layout_constraintBottom_toBottomOf="@id/space_title_bar" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="@id/space_title_bar" /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 34f262216..58b225bd5 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -95,12 +95,46 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> + + + + diff --git a/app/src/main/res/layout/room_game_activity.xml b/app/src/main/res/layout/room_game_activity.xml new file mode 100644 index 000000000..10cd2e7c4 --- /dev/null +++ b/app/src/main/res/layout/room_game_activity.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 4735c5d06..b70796d5f 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -5263,4 +5263,6 @@ أنت لم تصل إلى المستوى الـ VIP المطلوب لإرسال %1$s. المستوى الـ VIP المطلوب: %2$s حدثت بعض الاستثناءات، يرجى المحاولة مرة أخرى لاحقًا! يرجى السماح بإذن الميكروفون والمحاولة مرة أخرى + + فشل تهيئة دليل تطوير الألعاب:%s \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index c68f72c8f..35408a71e 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -5204,4 +5204,7 @@ {0}運氣爆表!在{1}中開出了價值{2}金币的{3} {0}運氣爆表!在{1}中開出了價值{2}金币的{3}X{4} 發生一些異常,請稍後重試! + + + 初始化遊戲SDK失敗:%s \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b17c759be..5a0294a30 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -5243,6 +5243,9 @@ Some exceptions occurred, please try again later! Please allow microphone permission and try again + + + Failed to initialize game SDK:%s diff --git a/core/src/main/java/com/chwl/core/home/model/HomeModel.kt b/core/src/main/java/com/chwl/core/home/model/HomeModel.kt index ad6b1556d..8d93a47dc 100644 --- a/core/src/main/java/com/chwl/core/home/model/HomeModel.kt +++ b/core/src/main/java/com/chwl/core/home/model/HomeModel.kt @@ -158,6 +158,17 @@ object HomeModel : BaseModel() { api.getStarUserList(pageNum, pageSize) } + //首页改版资源位 + suspend fun getCurrentResource(): List? = + launchRequest { + api.getCurrentResource() + } + + suspend fun getResourceJumpInfo(id: Int): HomeRoomInfo? = + launchRequest { + api.getResourceJumpInfo(id) + } + private interface Api { /** * 提交反馈 @@ -322,6 +333,22 @@ object HomeModel : BaseModel() { @Query("pageNum") pageNum: Int, @Query("pageSize") pageSize: Int ): ServiceResult> + + /** + * 首页改版资源位 + * + * @return + */ + @GET("/home/currentResource") + suspend fun getCurrentResource(): ServiceResult> + + /** + * 首页资源位跳转 + * + * @return + */ + @GET("/home/pickResource") + suspend fun getResourceJumpInfo(@Query("id") id: Int): ServiceResult } } \ No newline at end of file