集成完直播后提交代码
1
LiveInteractive/live_interactive_common/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
55
LiveInteractive/live_interactive_common/build.gradle
Normal file
@@ -0,0 +1,55 @@
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion androidCompileSdkVersion
|
||||
buildToolsVersion androidBuildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion androidMinSdkVersion
|
||||
targetSdkVersion androidTargetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [AROUTER_MODULE_NAME :'interactiveCommon' ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation externalAndroidDesign
|
||||
|
||||
api project(':LiveCommon:live_commonbiz')
|
||||
api project(':LiveBeauty:live_queenbeauty')
|
||||
|
||||
if (project.hasProperty("sdk_type") && "AliVCSDK_InteractiveLive".equalsIgnoreCase(sdk_type)) {
|
||||
api externalLivePusherInteractive
|
||||
} else {
|
||||
api externalLivePusher
|
||||
}
|
||||
|
||||
implementation externalSimpleZXing
|
||||
implementation externalARouter
|
||||
annotationProcessor externalARouterCompiler
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.alivc.live.interactive_common">
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name="com.alivc.live.interactive_common.InteractiveInputActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
<activity
|
||||
android:name="com.alivc.live.interactive_common.InteractiveAppInfoActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
<activity
|
||||
android:name=".InteractiveSettingActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.alivc.live.interactive_common;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.alivc.live.commonbiz.SharedPreferenceUtils;
|
||||
|
||||
/**
|
||||
* AppInfo 相关信息录入 Fragment
|
||||
*/
|
||||
public class InteractLiveAppInfoFragment extends Fragment {
|
||||
|
||||
private TextView mAppInfoTv;
|
||||
private ImageView mArrowImageView;
|
||||
private ConstraintLayout mAppInfoConstraintLayout;
|
||||
private ImageView mEditImageView;
|
||||
private TextView mAppIdTextView;
|
||||
private TextView mAppKeyTextView;
|
||||
private TextView mPlayDomainTextView;
|
||||
private OnEditClickListener mOnEditClickListener;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_interact_live_appinfo, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mAppInfoTv = view.findViewById(R.id.tv_app_info);
|
||||
mArrowImageView = view.findViewById(R.id.iv_arrow);
|
||||
mEditImageView = view.findViewById(R.id.iv_edit);
|
||||
mAppInfoConstraintLayout = view.findViewById(R.id.cl_app_info);
|
||||
|
||||
mAppIdTextView = view.findViewById(R.id.tv_app_id);
|
||||
mAppKeyTextView = view.findViewById(R.id.tv_app_key);
|
||||
mPlayDomainTextView = view.findViewById(R.id.tv_play_domain);
|
||||
|
||||
mArrowImageView.setColorFilter(Color.WHITE);
|
||||
|
||||
initListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mAppIdTextView.setText(SharedPreferenceUtils.getAppId(getContext().getApplicationContext()));
|
||||
mAppKeyTextView.setText(SharedPreferenceUtils.getAppKey(getContext().getApplicationContext()));
|
||||
mPlayDomainTextView.setText(SharedPreferenceUtils.getPlayDomain(getContext().getApplicationContext()));
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
// 测试用,长按应用信息四个字,自动填写用户ID和房间号
|
||||
mAppInfoTv.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (mOnEditClickListener != null) {
|
||||
mOnEditClickListener.onLongClickAppInfoForDebug();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
mArrowImageView.setOnClickListener((view) -> {
|
||||
float mArrowImageViewRotation;
|
||||
if (mAppInfoConstraintLayout.isShown()) {
|
||||
mAppInfoConstraintLayout.setVisibility(View.GONE);
|
||||
mArrowImageViewRotation = 0;
|
||||
} else {
|
||||
mAppInfoConstraintLayout.setVisibility(View.VISIBLE);
|
||||
mArrowImageViewRotation = 180;
|
||||
}
|
||||
mArrowImageView.setRotation(mArrowImageViewRotation);
|
||||
});
|
||||
|
||||
mEditImageView.setOnClickListener((view) -> {
|
||||
if (mOnEditClickListener != null) {
|
||||
mOnEditClickListener.onEditClickListener();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface OnEditClickListener {
|
||||
void onLongClickAppInfoForDebug();
|
||||
|
||||
void onEditClickListener();
|
||||
}
|
||||
|
||||
public void setOnEditClickListener(OnEditClickListener listener) {
|
||||
this.mOnEditClickListener = listener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,1211 @@
|
||||
package com.alivc.live.interactive_common;
|
||||
|
||||
import static com.alivc.live.interactive_common.utils.LivePushGlobalConfig.mAlivcLivePushConfig;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.hardware.Camera;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.alivc.component.custom.AlivcLivePushCustomFilter;
|
||||
import com.alivc.live.annotations.AlivcLiveAudioFrameObserverOperationMode;
|
||||
import com.alivc.live.annotations.AlivcLiveAudioFrameObserverUserDefinedInfoBitMask;
|
||||
import com.alivc.live.annotations.AlivcLiveAudioSource;
|
||||
import com.alivc.live.annotations.AlivcLiveMode;
|
||||
import com.alivc.live.annotations.AlivcLiveMuteLocalAudioMode;
|
||||
import com.alivc.live.annotations.AlivcLiveNetworkQuality;
|
||||
import com.alivc.live.annotations.AlivcLivePushKickedOutType;
|
||||
import com.alivc.live.annotations.AlivcLiveRecordMediaEvent;
|
||||
import com.alivc.live.beauty.BeautyFactory;
|
||||
import com.alivc.live.beauty.BeautyInterface;
|
||||
import com.alivc.live.beauty.constant.BeautySDKType;
|
||||
import com.alivc.live.commonbiz.backdoor.BackDoorInstance;
|
||||
import com.alivc.live.commonbiz.seidelay.SEIDelayManager;
|
||||
import com.alivc.live.commonbiz.seidelay.SEISourceType;
|
||||
import com.alivc.live.commonbiz.seidelay.api.ISEIDelayEventListener;
|
||||
import com.alivc.live.commonbiz.test.AliLiveStreamURLUtil;
|
||||
import com.alivc.live.commonutils.ToastUtils;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveLivePlayer;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
import com.alivc.live.interactive_common.listener.InteractLivePushPullListener;
|
||||
import com.alivc.live.interactive_common.manager.TimestampWatermarkManager;
|
||||
import com.alivc.live.interactive_common.utils.LivePushGlobalConfig;
|
||||
import com.alivc.live.player.AlivcLivePlayConfig;
|
||||
import com.alivc.live.player.AlivcLivePlayer;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayError;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayVideoStreamType;
|
||||
import com.alivc.live.pusher.AlivcAudioChannelEnum;
|
||||
import com.alivc.live.pusher.AlivcAudioSampleRateEnum;
|
||||
import com.alivc.live.pusher.AlivcImageFormat;
|
||||
import com.alivc.live.pusher.AlivcLiveAudioEffectConfig;
|
||||
import com.alivc.live.pusher.AlivcLiveAudioFrameObserverConfig;
|
||||
import com.alivc.live.pusher.AlivcLiveBase;
|
||||
import com.alivc.live.pusher.AlivcLiveLocalRecordConfig;
|
||||
import com.alivc.live.pusher.AlivcLiveMixStream;
|
||||
import com.alivc.live.pusher.AlivcLivePublishState;
|
||||
import com.alivc.live.pusher.AlivcLivePushAudioEffectVoiceChangeMode;
|
||||
import com.alivc.live.pusher.AlivcLivePushAudioFrame;
|
||||
import com.alivc.live.pusher.AlivcLivePushAudioFrameListener;
|
||||
import com.alivc.live.pusher.AlivcLivePushError;
|
||||
import com.alivc.live.pusher.AlivcLivePushErrorListener;
|
||||
import com.alivc.live.pusher.AlivcLivePushExternalAudioStreamConfig;
|
||||
import com.alivc.live.pusher.AlivcLivePushInfoListener;
|
||||
import com.alivc.live.pusher.AlivcLivePushNetworkListener;
|
||||
import com.alivc.live.pusher.AlivcLivePushStatsInfo;
|
||||
import com.alivc.live.pusher.AlivcLivePushVideoConfig;
|
||||
import com.alivc.live.pusher.AlivcLivePusher;
|
||||
import com.alivc.live.pusher.AlivcLivePusherRawDataSample;
|
||||
import com.alivc.live.pusher.AlivcLiveTranscodingConfig;
|
||||
import com.alivc.live.pusher.AlivcPreviewDisplayMode;
|
||||
import com.alivc.live.pusher.AlivcResolutionEnum;
|
||||
import com.alivc.live.pusher.AlivcSoundFormat;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 直播连麦基础类
|
||||
*
|
||||
* @note 请参考 API 文档,了解对应接口的释义,辅助接入
|
||||
* @note 互动模式下,请使用`AlivcRTC`作为日志tag,进行自主排障。
|
||||
*/
|
||||
public class InteractLiveBaseManager {
|
||||
|
||||
static {
|
||||
// 1. 注册推流SDK
|
||||
AlivcLiveBase.registerSDK();
|
||||
}
|
||||
|
||||
protected static final String TAG = "InteractLiveBaseManager";
|
||||
|
||||
protected InteractiveMode mInteractiveMode;
|
||||
|
||||
// 这个TM用来做混流的
|
||||
protected FrameLayout mAudienceFrameLayout;
|
||||
|
||||
//多人连麦混流
|
||||
protected final ArrayList<AlivcLiveMixStream> mMultiInteractLiveMixStreamsArray = new ArrayList<>();
|
||||
|
||||
//多人连麦 Config
|
||||
protected final AlivcLiveTranscodingConfig mMixInteractLiveTranscodingConfig = new AlivcLiveTranscodingConfig();
|
||||
|
||||
protected Context mContext;
|
||||
|
||||
protected AlivcLivePusher mAlivcLivePusher;
|
||||
private InteractiveUserData mPushUserData;
|
||||
|
||||
protected final Map<String, InteractiveLivePlayer> mInteractiveLivePlayerMap = new HashMap<>();
|
||||
protected final Map<String, InteractiveUserData> mInteractiveUserDataMap = new HashMap<>();
|
||||
|
||||
protected InteractLivePushPullListener mInteractLivePushPullListener;
|
||||
|
||||
// 美颜处理类,需对接Queen美颜SDK,且拥有License拥有美颜能力
|
||||
private BeautyInterface mBeautyManager;
|
||||
// CameraId,美颜需要使用
|
||||
private int mCameraId;
|
||||
|
||||
// 互动模式下的水印处理类
|
||||
private TimestampWatermarkManager mTimestampWatermarkManager;
|
||||
|
||||
protected final SEIDelayManager mSEIDelayManager = new SEIDelayManager();
|
||||
|
||||
public void init(Context context, InteractiveMode interactiveMode) {
|
||||
mInteractiveMode = interactiveMode;
|
||||
mContext = context.getApplicationContext();
|
||||
initLivePusher(interactiveMode);
|
||||
// initWatermarks();
|
||||
mSEIDelayManager.registerReceiver(new ISEIDelayEventListener() {
|
||||
@Override
|
||||
public void onEvent(String src, String type, String msg) {
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onReceiveSEIDelay(src, type, msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. 初始化 AlivcLivePushConfig 和 AlivcLivePusher
|
||||
*
|
||||
* @param interactiveMode 直播连麦模式(直播连麦、RTS 2.0推拉裸流)
|
||||
*/
|
||||
private void initLivePusher(InteractiveMode interactiveMode) {
|
||||
// 初始化推流配置类
|
||||
|
||||
// 设置推流模式为 AlivcLiveInteractiveMode,即:互动模式;互动直播,支持连麦、PK等实时互动
|
||||
mAlivcLivePushConfig.setLivePushMode(AlivcLiveMode.AlivcLiveInteractiveMode);
|
||||
// 互动模式下,如需与Web连麦互通,必须使用H5兼容模式,否则,Web用户查看Native用户将是黑屏。
|
||||
mAlivcLivePushConfig.setH5CompatibleMode(LivePushGlobalConfig.IS_H5_COMPATIBLE);
|
||||
|
||||
// 互动模式下开启RTS推拉裸流(直推&直拉,不同于直播连麦)
|
||||
if (InteractiveMode.isBareStream(interactiveMode)) {
|
||||
mAlivcLivePushConfig.setEnableRTSForInteractiveMode(true);
|
||||
}
|
||||
|
||||
/// 如果是外部音视频推流,需要初始化的 Pusher 配置,以及自定义音频、视频的Profiles
|
||||
if (mAlivcLivePushConfig.isExternMainStream()) {
|
||||
mAlivcLivePushConfig.setExternMainStream(true, AlivcImageFormat.IMAGE_FORMAT_YUVNV12, AlivcSoundFormat.SOUND_FORMAT_S16);
|
||||
mAlivcLivePushConfig.setAudioChannels(AlivcAudioChannelEnum.AUDIO_CHANNEL_ONE);
|
||||
mAlivcLivePushConfig.setAudioSampleRate(AlivcAudioSampleRateEnum.AUDIO_SAMPLE_RATE_44100);
|
||||
}
|
||||
|
||||
// 如果需要开启 Data Channel 自定义消息通道,以代替 SEI 功能,需要预先开启 Data Channel 自定义消息通道
|
||||
if (LivePushGlobalConfig.IS_DATA_CHANNEL_MESSAGE_ENABLE) {
|
||||
mAlivcLivePushConfig.setEnableDataChannelMessage(true);
|
||||
}
|
||||
|
||||
// 开启强制耳返
|
||||
HashMap<String, String> earbackExtras = new HashMap<>(4);
|
||||
earbackExtras.put("earback_open_when_without_headset", LivePushGlobalConfig.IS_EARBACK_OPEN_WITHOUT_HEADSET ? "TRUE" : "FALSE");
|
||||
mAlivcLivePushConfig.setExtras(earbackExtras);
|
||||
|
||||
// Demo逻辑,用于测试,请勿follow!如果强制RTC预发环境,那么增加extra配置
|
||||
if (BackDoorInstance.getInstance().isForceRTCPreEnvironment()) {
|
||||
HashMap<String, String> extras = new HashMap<>(4);
|
||||
extras.put("user_specified_environment", "PRE_RELEASE");
|
||||
mAlivcLivePushConfig.setExtras(extras);
|
||||
}
|
||||
|
||||
// 初始化推流引擎
|
||||
mAlivcLivePusher = new AlivcLivePusher();
|
||||
mAlivcLivePusher.init(mContext.getApplicationContext(), mAlivcLivePushConfig);
|
||||
|
||||
// 设置音量回调频率和平滑系数
|
||||
mAlivcLivePusher.enableAudioVolumeIndication(300, 3, 1);
|
||||
|
||||
/*
|
||||
* 错误异常及特殊场景处理
|
||||
* 参考文档:https://help.aliyun.com/zh/live/developer-reference/handling-of-exceptions-and-special-scenarios-for-android
|
||||
*/
|
||||
|
||||
// 设置推流错误事件
|
||||
mAlivcLivePusher.setLivePushErrorListener(new AlivcLivePushErrorListener() {
|
||||
@Override
|
||||
public void onSystemError(AlivcLivePusher alivcLivePusher, AlivcLivePushError alivcLivePushError) {
|
||||
Log.e(TAG, "onSystemError: " + alivcLivePushError);
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPushError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSDKError(AlivcLivePusher alivcLivePusher, AlivcLivePushError alivcLivePushError) {
|
||||
Log.e(TAG, "onSDKError: " + alivcLivePushError);
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPushError();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 设置推流通知事件
|
||||
mAlivcLivePusher.setLivePushInfoListener(new AlivcLivePushInfoListener() {
|
||||
@Override
|
||||
public void onPreviewStarted(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onPreviewStarted: ");
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPushSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreviewStopped(AlivcLivePusher pusher) {
|
||||
Log.d(TAG, "onPreviewStopped: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushStarted(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onPushStarted: ");
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPushSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushPaused(AlivcLivePusher pusher) {
|
||||
Log.d(TAG, "onPushPaused: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushResumed(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onPushResumed: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushStopped(AlivcLivePusher pusher) {
|
||||
Log.d(TAG, "onPushStopped: ");
|
||||
pusher.stopPreview();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushRestarted(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onPushRestarted: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFirstFramePushed(AlivcLivePusher pusher) {
|
||||
Log.d(TAG, "onFirstFramePushed: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFirstFramePreviewed(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onFirstFramePreviewed: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDropFrame(AlivcLivePusher alivcLivePusher, int i, int i1) {
|
||||
Log.d(TAG, "onDropFrame: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdjustBitrate(AlivcLivePusher pusher, int currentBitrate, int targetBitrate) {
|
||||
Log.i(TAG, "onAdjustBitrate: " + currentBitrate + "->" + targetBitrate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdjustFps(AlivcLivePusher alivcLivePusher, int i, int i1) {
|
||||
Log.d(TAG, "onAdjustFps: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushStatistics(AlivcLivePusher alivcLivePusher, AlivcLivePushStatsInfo alivcLivePushStatsInfo) {
|
||||
// Log.i(TAG, "onPushStatistics: " + alivcLivePushStatsInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetLiveMixTranscodingConfig(AlivcLivePusher alivcLivePusher, boolean b, String s) {
|
||||
Log.d(TAG, "onSetLiveMixTranscodingConfig: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKickedOutByServer(AlivcLivePusher pusher, AlivcLivePushKickedOutType kickedOutType) {
|
||||
Log.d(TAG, "onKickedOutByServer: " + kickedOutType);
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPushError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMicrophoneVolumeUpdate(AlivcLivePusher pusher, int volume) {
|
||||
// 麦克风音量回调(仅互动模式下生效,需设置AlivcLivePusher#enableAudioVolumeIndication接口)
|
||||
// Log.d(TAG, "onMicrophoneVolumeUpdate: " + volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocalRecordEvent(AlivcLiveRecordMediaEvent mediaEvent, String storagePath) {
|
||||
ToastUtils.show(mediaEvent + ", " + storagePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoteUserEnterRoom(AlivcLivePusher pusher, String userId, boolean isOnline) {
|
||||
ToastUtils.show("onRemoteUserEnterRoom: " + userId + ", isOnline" + isOnline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoteUserAudioStream(AlivcLivePusher pusher, String userId, boolean isPushing) {
|
||||
ToastUtils.show("onRemoteUserAudioStream: " + userId + ", isPushing: " + isPushing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoteUserVideoStream(AlivcLivePusher pusher, String userId, AlivcLivePlayVideoStreamType videoStreamType, boolean isPushing) {
|
||||
ToastUtils.show("onRemoteUserVideoStream: " + userId + ", videoStreamType: " + videoStreamType + ", isPushing: " + isPushing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioPublishStateChanged(AlivcLivePublishState oldState, AlivcLivePublishState newState) {
|
||||
super.onAudioPublishStateChanged(oldState, newState);
|
||||
ToastUtils.show("onAudioPublishStateChanged: " + oldState + "->" + newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoPublishStateChanged(AlivcLivePublishState oldState, AlivcLivePublishState newState) {
|
||||
super.onVideoPublishStateChanged(oldState, newState);
|
||||
ToastUtils.show("onVideoPublishStateChanged: " + oldState + "->" + newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScreenSharePublishStateChanged(AlivcLivePublishState oldState, AlivcLivePublishState newState) {
|
||||
super.onScreenSharePublishStateChanged(oldState, newState);
|
||||
ToastUtils.show("onScreenSharePublishStateChanged: " + oldState + "->" + newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocalDualAudioStreamPushState(AlivcLivePusher pusher, boolean isPushing) {
|
||||
super.onLocalDualAudioStreamPushState(pusher, isPushing);
|
||||
ToastUtils.show("onLocalDualAudioStreamPushState: " + isPushing);
|
||||
}
|
||||
});
|
||||
|
||||
// 设置网络通知事件
|
||||
mAlivcLivePusher.setLivePushNetworkListener(new AlivcLivePushNetworkListener() {
|
||||
@Override
|
||||
public void onNetworkPoor(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onNetworkPoor: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkRecovery(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onNetworkRecovery: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReconnectStart(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onReconnectStart: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionLost(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onConnectionLost: ");
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onConnectionLost();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReconnectFail(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onReconnectFail: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReconnectSucceed(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onReconnectSucceed: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendDataTimeout(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onSendDataTimeout: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFail(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onConnectFail: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkQualityChanged(AlivcLiveNetworkQuality upQuality, AlivcLiveNetworkQuality downQuality) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onPushURLAuthenticationOverdue(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onPushURLAuthenticationOverdue: ");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushURLTokenWillExpire(AlivcLivePusher pusher) {
|
||||
Log.d(TAG, "onPushURLTokenWillExpire: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushURLTokenExpired(AlivcLivePusher pusher) {
|
||||
Log.d(TAG, "onPushURLTokenExpired: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendMessage(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onSendMessage: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketsLost(AlivcLivePusher alivcLivePusher) {
|
||||
Log.d(TAG, "onPacketsLost: ");
|
||||
}
|
||||
});
|
||||
|
||||
// 【美颜】注册视频前处理回调
|
||||
mAlivcLivePusher.setCustomFilter(new AlivcLivePushCustomFilter() {
|
||||
@Override
|
||||
public void customFilterCreate() {
|
||||
initBeautyManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int customFilterProcess(int inputTexture, int textureWidth, int textureHeight, long extra) {
|
||||
if (mBeautyManager == null) {
|
||||
return inputTexture;
|
||||
}
|
||||
|
||||
return mBeautyManager.onTextureInput(inputTexture, textureWidth, textureHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customFilterDestroy() {
|
||||
destroyBeautyManager();
|
||||
}
|
||||
});
|
||||
|
||||
// 记录当前摄像头状态
|
||||
mCameraId = mAlivcLivePushConfig.getCameraType();
|
||||
}
|
||||
|
||||
private void destroyLivePusher() {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPushing() {
|
||||
return mAlivcLivePusher != null && mAlivcLivePusher.isPushing();
|
||||
}
|
||||
|
||||
public boolean isPulling(InteractiveUserData userData) {
|
||||
if (userData == null) {
|
||||
return false;
|
||||
}
|
||||
InteractiveLivePlayer interactiveLivePlayer = mInteractiveLivePlayerMap.get(userData.getKey());
|
||||
if (interactiveLivePlayer != null) {
|
||||
return interactiveLivePlayer.isPulling();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void initWatermarks() {
|
||||
// 互动模式下使用该接口添加水印,最多添加一个,多则替代
|
||||
mTimestampWatermarkManager = new TimestampWatermarkManager();
|
||||
mTimestampWatermarkManager.init(new TimestampWatermarkManager.OnWatermarkListener() {
|
||||
@Override
|
||||
public void onWatermarkUpdate(Bitmap bitmap) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.addWaterMark(bitmap, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void destroyWatermarks() {
|
||||
if (mTimestampWatermarkManager != null) {
|
||||
mTimestampWatermarkManager.destroy();
|
||||
mTimestampWatermarkManager = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setInteractLivePushPullListener(InteractLivePushPullListener listener) {
|
||||
mInteractLivePushPullListener = listener;
|
||||
}
|
||||
|
||||
private boolean createAlivcLivePlayer(InteractiveUserData userData) {
|
||||
if (userData == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String userDataKey = userData.getKey();
|
||||
if (mInteractiveLivePlayerMap.containsKey(userDataKey)) {
|
||||
Log.i(TAG, "createAlivcLivePlayer already created " + userDataKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.d(TAG, "createAlivcLivePlayer: " + userDataKey);
|
||||
InteractiveLivePlayer alivcLivePlayer = new InteractiveLivePlayer(mContext, AlivcLiveMode.AlivcLiveInteractiveMode);
|
||||
alivcLivePlayer.setPullUserData(userData);
|
||||
alivcLivePlayer.setMultiInteractPlayInfoListener(new InteractLivePushPullListener() {
|
||||
@Override
|
||||
public void onPullSuccess(InteractiveUserData userData) {
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPullSuccess(userData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPullError(InteractiveUserData userData, AlivcLivePlayError errorType, String errorMsg) {
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPullError(userData, errorType, errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPullStop(InteractiveUserData userData) {
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPullStop(userData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushSuccess() {
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPushSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushError() {
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onPushError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveSEIMessage(int payload, byte[] data) {
|
||||
super.onReceiveSEIMessage(payload, data);
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onReceiveSEIMessage(payload, data);
|
||||
}
|
||||
String sei = new String(data, StandardCharsets.UTF_8);
|
||||
mSEIDelayManager.receiveSEI(SEISourceType.RTC, sei);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoEnabled(boolean enable) {
|
||||
super.onVideoEnabled(enable);
|
||||
if (mInteractLivePushPullListener != null) {
|
||||
mInteractLivePushPullListener.onVideoEnabled(enable);
|
||||
}
|
||||
}
|
||||
});
|
||||
mInteractiveLivePlayerMap.put(userDataKey, alivcLivePlayer);
|
||||
mInteractiveUserDataMap.put(userDataKey, userData);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void startPreviewAndPush(InteractiveUserData userData, FrameLayout frameLayout, boolean isAnchor) {
|
||||
if (userData == null) {
|
||||
Log.e(TAG, "startPreviewAndPush, userData invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
mPushUserData = userData;
|
||||
mAlivcLivePusher.startPreview(mContext, frameLayout, isAnchor);
|
||||
|
||||
String pushUrl = userData.url;
|
||||
if (TextUtils.isEmpty(pushUrl) && InteractiveMode.isInteractive(mInteractiveMode)) {
|
||||
pushUrl = AliLiveStreamURLUtil.generateInteractivePushUrl(userData.channelId, userData.userId);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(pushUrl)) {
|
||||
Log.e(TAG, "startPreviewAndPush, pushUrl invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "startPreviewAndPush: " + isAnchor + ", " + pushUrl);
|
||||
mAlivcLivePusher.startPushAsync(pushUrl);
|
||||
|
||||
mSEIDelayManager.registerProvider(userData.userId, new ISEIDelayEventListener() {
|
||||
@Override
|
||||
public void onEvent(String src, String type, String msg) {
|
||||
sendCustomMessage(msg, 5);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void stopPreview() {
|
||||
mAlivcLivePusher.stopPreview();
|
||||
}
|
||||
|
||||
public void updatePreview(FrameLayout frameLayout, boolean isFullScreen) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.updatePreview(mContext, frameLayout, isFullScreen);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopPush() {
|
||||
if (isPushing()) {
|
||||
mAlivcLivePusher.stopPush();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopCamera() {
|
||||
mAlivcLivePusher.stopCamera();
|
||||
}
|
||||
|
||||
public void setPullView(InteractiveUserData userData, FrameLayout frameLayout, boolean isAnchor) {
|
||||
if (userData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.mAudienceFrameLayout = frameLayout;
|
||||
|
||||
boolean isNew = createAlivcLivePlayer(userData);
|
||||
|
||||
AlivcLivePlayer livePlayer = mInteractiveLivePlayerMap.get(userData.getKey());
|
||||
if (livePlayer == null) {
|
||||
Log.e(TAG, "setPullView error: livePlayer is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNew) {
|
||||
AlivcLivePlayConfig config = new AlivcLivePlayConfig();
|
||||
config.isFullScreen = isAnchor;
|
||||
config.videoStreamType = userData.videoStreamType;
|
||||
config.audioStreamType = userData.audioStreamType;
|
||||
livePlayer.setupWithConfig(config);
|
||||
}
|
||||
|
||||
livePlayer.setPlayView(frameLayout);
|
||||
Log.i(TAG, "setPullView: " + userData);
|
||||
}
|
||||
|
||||
public void startPullRTCStream(InteractiveUserData userData) {
|
||||
if (userData == null || TextUtils.isEmpty(userData.url)) {
|
||||
Log.e(TAG, "startPull error: url is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
createAlivcLivePlayer(userData);
|
||||
|
||||
AlivcLivePlayer alivcLivePlayer = mInteractiveLivePlayerMap.get(userData.getKey());
|
||||
Log.d(TAG, "startPullRTCStream: " + userData.getKey() + ", " + userData.url + ", " + alivcLivePlayer);
|
||||
if (alivcLivePlayer != null) {
|
||||
alivcLivePlayer.startPlay(userData.url);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopPullRTCStream(InteractiveUserData userData) {
|
||||
if (userData == null) {
|
||||
return;
|
||||
}
|
||||
String userKey = userData.getKey();
|
||||
AlivcLivePlayer alivcLivePlayer = mInteractiveLivePlayerMap.get(userKey);
|
||||
Log.d(TAG, "stopPullRTCStream: " + userData.getKey() + ", " + userData.url + ", " + alivcLivePlayer);
|
||||
if (alivcLivePlayer != null) {
|
||||
alivcLivePlayer.stopPlay();
|
||||
alivcLivePlayer.destroy();
|
||||
}
|
||||
mInteractiveLivePlayerMap.remove(userKey);
|
||||
mInteractiveUserDataMap.remove(userKey);
|
||||
}
|
||||
|
||||
// 暂停推流
|
||||
public void pausePush() {
|
||||
if (isPushing()) {
|
||||
mAlivcLivePusher.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复推流
|
||||
public void resumePush() {
|
||||
if (isPushing()) {
|
||||
mAlivcLivePusher.resume();
|
||||
}
|
||||
}
|
||||
|
||||
// 停止播放RTC流
|
||||
public void pausePlayRTCStream(InteractiveUserData userData) {
|
||||
Log.d(TAG, "pausePlayRTCStream: " + userData);
|
||||
if (userData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String userKey = userData.getKey();
|
||||
InteractiveLivePlayer alivcLivePlayer = mInteractiveLivePlayerMap.get(userKey);
|
||||
if (alivcLivePlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
alivcLivePlayer.pauseVideoPlaying();
|
||||
}
|
||||
|
||||
// 恢复播放RTC流
|
||||
public void resumePlayRTCStream(InteractiveUserData userData) {
|
||||
Log.d(TAG, "resumePlayRTCStream: " + userData);
|
||||
if (userData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String userKey = userData.getKey();
|
||||
InteractiveLivePlayer alivcLivePlayer = mInteractiveLivePlayerMap.get(userKey);
|
||||
if (alivcLivePlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
alivcLivePlayer.resumeVideoPlaying();
|
||||
}
|
||||
|
||||
// 停止播放所有RTC流
|
||||
public void pausePlayRTCStream() {
|
||||
for (InteractiveUserData userData : mInteractiveUserDataMap.values()) {
|
||||
pausePlayRTCStream(userData);
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复播放所有RTC流
|
||||
public void resumePlayRTCStream() {
|
||||
for (InteractiveUserData userData : mInteractiveUserDataMap.values()) {
|
||||
resumePlayRTCStream(userData);
|
||||
}
|
||||
}
|
||||
|
||||
// 发送自定义消息,发送SEI
|
||||
public void sendCustomMessage(String text, int payload) {
|
||||
if (LivePushGlobalConfig.IS_DATA_CHANNEL_MESSAGE_ENABLE) {
|
||||
mAlivcLivePusher.sendDataChannelMessage(text);
|
||||
} else {
|
||||
mAlivcLivePusher.sendMessage(text, 0, 0, false, payload);
|
||||
}
|
||||
}
|
||||
|
||||
// 开始本地录制
|
||||
public void startLocalRecord(AlivcLiveLocalRecordConfig recordConfig) {
|
||||
boolean flag = false;
|
||||
if (mAlivcLivePusher != null) {
|
||||
flag = mAlivcLivePusher.startLocalRecord(recordConfig);
|
||||
}
|
||||
if (!flag) {
|
||||
ToastUtils.show("start local record failed!");
|
||||
}
|
||||
}
|
||||
|
||||
// 结束本地录制
|
||||
public void stopLocalRecord() {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.stopLocalRecord();
|
||||
}
|
||||
}
|
||||
|
||||
public void switchCamera() {
|
||||
if (isPushing()) {
|
||||
mAlivcLivePusher.switchCamera();
|
||||
if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
|
||||
mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
|
||||
} else {
|
||||
mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setMute(boolean isMute) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.setMute(isMute);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMute(boolean isMute, AlivcLiveMuteLocalAudioMode muteLocalAudioMode) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.setMute(isMute, muteLocalAudioMode);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBGMEarsBack(boolean isOpen) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.setBGMEarsBack(isOpen);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAudioEffectVoiceChangeMode(AlivcLivePushAudioEffectVoiceChangeMode voiceChangeMode) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.setAudioEffectVoiceChangeMode(voiceChangeMode);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVideoConfig(AlivcLivePushVideoConfig videoConfig) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.setVideoConfig(videoConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public void enableSpeakerPhone(boolean enableSpeakerPhone) {
|
||||
mAlivcLivePusher.enableSpeakerphone(enableSpeakerPhone);
|
||||
}
|
||||
|
||||
public void enableAudioCapture(boolean enable) {
|
||||
if (enable) {
|
||||
mAlivcLivePusher.startAudioCapture(true);
|
||||
} else {
|
||||
mAlivcLivePusher.stopAudioCapture();
|
||||
}
|
||||
}
|
||||
|
||||
public void muteLocalCamera(boolean muteLocalCamera) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.muteLocalCamera(muteLocalCamera);
|
||||
}
|
||||
}
|
||||
|
||||
public void enableLocalCamera(boolean enable) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.enableLocalCamera(enable);
|
||||
}
|
||||
}
|
||||
|
||||
public void changeResolution(AlivcResolutionEnum resolutionEnum) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.changeResolution(resolutionEnum);
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mSEIDelayManager.destroy();
|
||||
|
||||
// destroyWatermarks();
|
||||
clearLiveMixTranscodingConfig();
|
||||
|
||||
stopPush();
|
||||
destroyLivePusher();
|
||||
|
||||
mMultiInteractLiveMixStreamsArray.clear();
|
||||
mMixInteractLiveTranscodingConfig.mixStreams = mMultiInteractLiveMixStreamsArray;
|
||||
|
||||
for (AlivcLivePlayer alivcLivePlayer : mInteractiveLivePlayerMap.values()) {
|
||||
alivcLivePlayer.stopPlay();
|
||||
alivcLivePlayer.destroy();
|
||||
}
|
||||
|
||||
mInteractiveLivePlayerMap.clear();
|
||||
mInteractiveUserDataMap.clear();
|
||||
|
||||
mInteractLivePushPullListener = null;
|
||||
}
|
||||
|
||||
// 单切混的逻辑在各自场景的manager里面,因为PK和连麦的混流布局不太一样。
|
||||
// 更新混流、混切单
|
||||
public void clearLiveMixTranscodingConfig() {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.setLiveMixTranscodingConfig(null);
|
||||
}
|
||||
}
|
||||
|
||||
// 遍历当前混流子布局信息
|
||||
public AlivcLiveMixStream findMixStreamByUserData(InteractiveUserData userData) {
|
||||
if (userData == null || TextUtils.isEmpty(userData.userId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (AlivcLiveMixStream alivcLiveMixStream : mMultiInteractLiveMixStreamsArray) {
|
||||
if (userData.userId.equals(alivcLiveMixStream.userId)
|
||||
&& alivcLiveMixStream.mixSourceType == InteractiveBaseUtil.covertVideoStreamType2MixSourceType(userData.videoStreamType)) {
|
||||
return alivcLiveMixStream;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public InteractiveUserData getUserDataByKey(String key) {
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (String userKey : mInteractiveUserDataMap.keySet()) {
|
||||
if (TextUtils.equals(userKey, key)) {
|
||||
return mInteractiveUserDataMap.get(userKey);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// 初始化美颜相关资源
|
||||
private void initBeautyManager() {
|
||||
if (mBeautyManager == null && LivePushGlobalConfig.ENABLE_BEAUTY) {
|
||||
// v4.4.4版本-v6.1.0版本,互动模式下的美颜,处理逻辑参考BeautySDKType.INTERACT_QUEEN,即:InteractQueenBeautyImpl;
|
||||
// v6.1.0以后的版本(从v6.2.0开始),基础模式下的美颜,和互动模式下的美颜,处理逻辑保持一致,即:QueenBeautyImpl;
|
||||
mBeautyManager = BeautyFactory.createBeauty(BeautySDKType.QUEEN, mContext);
|
||||
// initialize in texture thread.
|
||||
mBeautyManager.init();
|
||||
mBeautyManager.setBeautyEnable(LivePushGlobalConfig.ENABLE_BEAUTY);
|
||||
mBeautyManager.switchCameraId(mCameraId);
|
||||
}
|
||||
}
|
||||
|
||||
// 销毁美颜相关资源
|
||||
private void destroyBeautyManager() {
|
||||
if (mBeautyManager != null) {
|
||||
mBeautyManager.release();
|
||||
mBeautyManager = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ****************** 音频数据回调(参考示例) ****************** [START]
|
||||
* <p>
|
||||
* 调用建议:1. 调用时机任意;2. 注意清除逻辑
|
||||
*/
|
||||
private static final AlivcLiveAudioSource AUDIO_FRAME_OBSERVER_SOURCE = AlivcLiveAudioSource.PROCESS_CAPTURED;
|
||||
private static final AlivcLiveAudioFrameObserverOperationMode AUDIO_FRAME_OBSERVER_MODE = AlivcLiveAudioFrameObserverOperationMode.READ_WRITE;
|
||||
private static final AlivcLiveAudioFrameObserverUserDefinedInfoBitMask AUDIO_FRAME_OBSERVER_BIT_MASK = AlivcLiveAudioFrameObserverUserDefinedInfoBitMask.MIX_EXTERNAL_CAPTURE;
|
||||
|
||||
/**
|
||||
* 设置音频裸数据回调
|
||||
* <p>
|
||||
* 注意:该接口较耗时,会影响性能,如果不需要对音频裸数据进行前处理,建议关闭
|
||||
*/
|
||||
public void enableAudioFrameObserver(boolean enable) {
|
||||
if (mAlivcLivePusher == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
AlivcLiveAudioFrameObserverConfig audioFrameObserverConfig = new AlivcLiveAudioFrameObserverConfig();
|
||||
audioFrameObserverConfig.mode = AUDIO_FRAME_OBSERVER_MODE;
|
||||
audioFrameObserverConfig.userDefinedInfo = AUDIO_FRAME_OBSERVER_BIT_MASK;
|
||||
mAlivcLivePusher.enableAudioFrameObserver(true, AUDIO_FRAME_OBSERVER_SOURCE, audioFrameObserverConfig);
|
||||
mAlivcLivePusher.setLivePushAudioFrameListener(new AlivcLivePushAudioFrameListener() {
|
||||
@Override
|
||||
public boolean onCapturedAudioFrame(AlivcLivePushAudioFrame audioFrame) {
|
||||
// 设置 enableAudioFrameObserver 接口中的 AlivcLiveAudioSource 为 CAPTURED,会执行该回调
|
||||
// do audio process here, and then, return true value if audio data need to be rewrited
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onProcessCapturedAudioFrame(AlivcLivePushAudioFrame audioFrame) {
|
||||
// 设置 enableAudioFrameObserver 接口中的 AlivcLiveAudioSource 为 PROCESS_CAPTURED,会执行该回调
|
||||
// do audio process here, and then, return true value if audio data need to be rewrited
|
||||
return false;
|
||||
|
||||
// // 清空 byte buffer,测试是否生效
|
||||
// Arrays.fill(audioFrame.data, (byte) 0);
|
||||
// return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPublishAudioFrame(AlivcLivePushAudioFrame audioFrame) {
|
||||
// 设置 enableAudioFrameObserver 接口中的 AlivcLiveAudioSource 为 PUB,会执行该回调
|
||||
// do audio process here, and then, return true value if audio data need to be rewrited
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPlaybackAudioFrame(AlivcLivePushAudioFrame audioFrame) {
|
||||
// 设置 enableAudioFrameObserver 接口中的 AlivcLiveAudioSource 为 PLAYBACK,会执行该回调
|
||||
// do audio process here, and then, return true value if audio data need to be rewrited
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMixedAllAudioFrame(AlivcLivePushAudioFrame audioFrame) {
|
||||
// 设置 enableAudioFrameObserver 接口中的 AlivcLiveAudioSource 为 MIXED_ALL,会执行该回调
|
||||
// 注意:设置 AlivcLiveAudioSource.MIXED_ALL 时,只能读不能写
|
||||
// do audio process here, and then, return true value if audio data need to be rewrited
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// please ensure the callback unregistration to prevent memory leaks
|
||||
mAlivcLivePusher.enableAudioFrameObserver(false, AUDIO_FRAME_OBSERVER_SOURCE, null);
|
||||
mAlivcLivePusher.setLivePushAudioFrameListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [END] ****************** 音频数据回调(参考示例) ******************
|
||||
*/
|
||||
|
||||
/**
|
||||
* ****************** 音效接口(参考示例) ****************** [START]
|
||||
*/
|
||||
|
||||
// 音效文件 assets 路径
|
||||
private static final String SOUND_EFFECT_ASSETS_PATH = "alivc_resource/sound_effect/";
|
||||
|
||||
// 预加载音效
|
||||
public void loadAudioEffects() {
|
||||
if (mAlivcLivePusher == null || mContext == null) {
|
||||
return;
|
||||
}
|
||||
String soundEffectPath1 = mContext.getFilesDir().getPath() + File.separator + SOUND_EFFECT_ASSETS_PATH + "sound_effect_man_smile.mp3";
|
||||
String soundEffectPath2 = mContext.getFilesDir().getPath() + File.separator + SOUND_EFFECT_ASSETS_PATH + "sound_effect_roar.mp3";
|
||||
String soundEffectPath3 = mContext.getFilesDir().getPath() + File.separator + SOUND_EFFECT_ASSETS_PATH + "sound_effect_sinister_smile.mp3";
|
||||
mAlivcLivePusher.preloadAudioEffect(1, soundEffectPath1);
|
||||
mAlivcLivePusher.preloadAudioEffect(2, soundEffectPath2);
|
||||
mAlivcLivePusher.preloadAudioEffect(3, soundEffectPath3);
|
||||
}
|
||||
|
||||
// 取消预加载音效
|
||||
public void unloadAudioEffects() {
|
||||
if (mAlivcLivePusher == null || mContext == null) {
|
||||
return;
|
||||
}
|
||||
mAlivcLivePusher.unloadAudioEffect(1);
|
||||
mAlivcLivePusher.unloadAudioEffect(2);
|
||||
mAlivcLivePusher.unloadAudioEffect(3);
|
||||
}
|
||||
|
||||
// 播放音效
|
||||
public void playAudioEffects() {
|
||||
if (mAlivcLivePusher == null || mContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String soundEffectPath1 = mContext.getFilesDir().getPath() + File.separator + SOUND_EFFECT_ASSETS_PATH + "sound_effect_man_smile.mp3";
|
||||
String soundEffectPath2 = mContext.getFilesDir().getPath() + File.separator + SOUND_EFFECT_ASSETS_PATH + "sound_effect_roar.mp3";
|
||||
String soundEffectPath3 = mContext.getFilesDir().getPath() + File.separator + SOUND_EFFECT_ASSETS_PATH + "sound_effect_sinister_smile.mp3";
|
||||
|
||||
AlivcLiveAudioEffectConfig audioEffectConfig1 = new AlivcLiveAudioEffectConfig();
|
||||
audioEffectConfig1.needPublish = false;
|
||||
audioEffectConfig1.publishVolume = 0;
|
||||
audioEffectConfig1.playoutVolume = 0;
|
||||
|
||||
AlivcLiveAudioEffectConfig audioEffectConfig2 = new AlivcLiveAudioEffectConfig();
|
||||
audioEffectConfig2.needPublish = true;
|
||||
audioEffectConfig2.publishVolume = 100;
|
||||
audioEffectConfig2.playoutVolume = 100;
|
||||
|
||||
AlivcLiveAudioEffectConfig audioEffectConfig3 = new AlivcLiveAudioEffectConfig();
|
||||
audioEffectConfig3.needPublish = true;
|
||||
audioEffectConfig3.publishVolume = 100;
|
||||
audioEffectConfig3.playoutVolume = 100;
|
||||
audioEffectConfig3.loopCycles = 3;
|
||||
|
||||
mAlivcLivePusher.playAudioEffect(1, soundEffectPath1, audioEffectConfig1);
|
||||
mAlivcLivePusher.playAudioEffect(2, soundEffectPath2, audioEffectConfig2);
|
||||
mAlivcLivePusher.playAudioEffect(3, soundEffectPath3, audioEffectConfig3);
|
||||
}
|
||||
|
||||
public void stopAudioEffect() {
|
||||
if (mAlivcLivePusher == null) {
|
||||
return;
|
||||
}
|
||||
mAlivcLivePusher.stopAudioEffect(1);
|
||||
mAlivcLivePusher.stopAudioEffect(2);
|
||||
mAlivcLivePusher.stopAudioEffect(3);
|
||||
// mAlivcLivePusher.stopAllAudioEffects();
|
||||
}
|
||||
|
||||
public void pauseAudioEffect() {
|
||||
if (mAlivcLivePusher == null) {
|
||||
return;
|
||||
}
|
||||
mAlivcLivePusher.pauseAudioEffect(1);
|
||||
mAlivcLivePusher.pauseAudioEffect(2);
|
||||
mAlivcLivePusher.pauseAudioEffect(3);
|
||||
// mAlivcLivePusher.pauseAllAudioEffects();
|
||||
}
|
||||
|
||||
public void resumeAudioEffect() {
|
||||
if (mAlivcLivePusher == null) {
|
||||
return;
|
||||
}
|
||||
mAlivcLivePusher.resumeAudioEffect(1);
|
||||
mAlivcLivePusher.resumeAudioEffect(2);
|
||||
mAlivcLivePusher.resumeAudioEffect(3);
|
||||
// mAlivcLivePusher.resumeAllAudioEffects();
|
||||
}
|
||||
|
||||
/**
|
||||
* [END] ****************** 音效接口(参考示例) ******************
|
||||
*/
|
||||
|
||||
/**
|
||||
* ****************** 外部音视频输入/三方推流(参考示例) ****************** [START]
|
||||
*/
|
||||
// 新增外部音频流
|
||||
public int addExternalAudioStream(AlivcLivePushExternalAudioStreamConfig externalAudioStreamConfig) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.addExternalAudioStream(externalAudioStreamConfig);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 删除外部音频流
|
||||
public int removeExternalAudioStream(int streamId) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.removeExternalAudioStream(streamId);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 输入外部音频流数据
|
||||
public int pushExternalAudioStream(int streamId, AlivcLivePushAudioFrame audioFrame) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.pushExternalAudioStream(streamId, audioFrame);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 设置是否与麦克风采集音频混合
|
||||
public int setMixedWithMic(boolean mixed) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.setMixedWithMic(mixed);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 设置外部音频流播放音量
|
||||
public int setExternalAudioStreamPlayoutVolume(int streamId, int playoutVolume) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.setExternalAudioStreamPlayoutVolume(streamId, playoutVolume);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 设置外部音频流推流音量
|
||||
public int setExternalAudioStreamPublishVolume(int streamId, int publishVolume) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.setExternalAudioStreamPublishVolume(streamId, publishVolume);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 启用外部视频输入源
|
||||
public void setExternalVideoSource(boolean enable, boolean useTexture, AlivcLivePlayVideoStreamType videoStreamType, AlivcPreviewDisplayMode previewDisplayMode) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.setExternalVideoSource(enable, useTexture, videoStreamType, previewDisplayMode);
|
||||
}
|
||||
}
|
||||
|
||||
// 外部视频输入/三方推流
|
||||
public void inputStreamVideoData(byte[] data, int width, int height, int stride, int size, long pts, int rotation) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.inputStreamVideoData(data, width, height, stride, size, pts, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
// 外部音频输入/三方推流
|
||||
public void inputStreamAudioData(byte[] data, int size, int sampleRate, int channels, long pts) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.inputStreamAudioData(data, size, sampleRate, channels, pts);
|
||||
}
|
||||
}
|
||||
|
||||
// 输入外部视频流数据
|
||||
public void pushExternalVideoFrame(AlivcLivePusherRawDataSample rawDataSample, AlivcLivePlayVideoStreamType videoStreamType) {
|
||||
if (mAlivcLivePusher != null) {
|
||||
mAlivcLivePusher.pushExternalVideoFrame(rawDataSample, videoStreamType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [END] ****************** 外部音视频输入/三方推流(参考示例) ******************
|
||||
*/
|
||||
|
||||
/**
|
||||
* ****************** 视频双流(参考示例) ****************** [START]
|
||||
*/
|
||||
// 开始屏幕共享流
|
||||
public int startScreenShare() {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.startScreenShare();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 停止屏幕共享流
|
||||
public int stopScreenShare() {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.stopScreenShare();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* [END] ****************** 视频双流(参考示例) ******************
|
||||
*/
|
||||
|
||||
/**
|
||||
* ****************** 音频双流(参考示例) ****************** [START]
|
||||
*/
|
||||
// 开启第二路音频流推送
|
||||
public int startDualAudioStream() {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.startLocalDualAudioStream();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 停止第二路音频流推送
|
||||
public int stopDualAudioStream() {
|
||||
if (mAlivcLivePusher != null) {
|
||||
return mAlivcLivePusher.stopLocalDualAudioStream();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* [END] ****************** 音频双流(参考示例) ******************
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package com.alivc.live.interactive_common;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.acker.simplezxing.activity.CaptureActivity;
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.alivc.live.commonbiz.SharedPreferenceUtils;
|
||||
import com.alivc.live.commonui.utils.StatusBarUtil;
|
||||
|
||||
public class InteractiveAppInfoActivity extends AppCompatActivity {
|
||||
|
||||
public static final String FROM_EDITOR = "from_editor";
|
||||
private static final int REQ_CODE_PERMISSION = 0x1111;
|
||||
|
||||
private ImageView mBackImageView;
|
||||
private EditText mAppIdEditText;
|
||||
private EditText mAppKeyEditText;
|
||||
private EditText mPlayDomainEditText;
|
||||
private TextView mConfirmTextView;
|
||||
private ImageView mAppIdClearImageView;
|
||||
private ImageView mAppKeyClearImageView;
|
||||
private ImageView mPlayDomainClearImageView;
|
||||
|
||||
private boolean mFromEditor = false;
|
||||
private int mSceneType = InteractiveConstants.SCENE_TYPE_INTERACTIVE_LIVE;
|
||||
private EditText mCurrentEditText = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
StatusBarUtil.translucent(this, Color.TRANSPARENT);
|
||||
|
||||
setContentView(R.layout.activity_interactive_app_info);
|
||||
|
||||
mFromEditor = getIntent().getBooleanExtra(FROM_EDITOR, false);
|
||||
mSceneType = getIntent().getIntExtra(InteractiveConstants.DATA_TYPE_SCENE, InteractiveConstants.SCENE_TYPE_INTERACTIVE_LIVE);
|
||||
|
||||
initView();
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mBackImageView = findViewById(R.id.iv_back);
|
||||
|
||||
mAppIdEditText = findViewById(R.id.et_app_id);
|
||||
mAppKeyEditText = findViewById(R.id.et_app_key);
|
||||
mPlayDomainEditText = findViewById(R.id.et_play_domain);
|
||||
|
||||
mAppIdClearImageView = findViewById(R.id.iv_app_id_clear);
|
||||
mAppKeyClearImageView = findViewById(R.id.iv_app_key_clear);
|
||||
mPlayDomainClearImageView = findViewById(R.id.iv_play_domain_clear);
|
||||
|
||||
mConfirmTextView = findViewById(R.id.tv_confirm);
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mBackImageView.setOnClickListener((view) -> finish());
|
||||
|
||||
mAppIdEditText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
mAppIdClearImageView.setImageResource(TextUtils.isEmpty(editable.toString()) ? R.drawable.ic_scan_icon : R.drawable.ic_close);
|
||||
changeConfirmTextView(checkEnable());
|
||||
}
|
||||
});
|
||||
|
||||
mAppKeyEditText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
mAppKeyClearImageView.setImageResource(TextUtils.isEmpty(editable.toString()) ? R.drawable.ic_scan_icon : R.drawable.ic_close);
|
||||
changeConfirmTextView(checkEnable());
|
||||
}
|
||||
});
|
||||
|
||||
mPlayDomainEditText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
mPlayDomainClearImageView.setImageResource(TextUtils.isEmpty(editable.toString()) ? R.drawable.ic_scan_icon : R.drawable.ic_close);
|
||||
changeConfirmTextView(checkEnable());
|
||||
}
|
||||
});
|
||||
|
||||
mAppIdClearImageView.setOnClickListener((view) -> checkForQrOrClear(mAppIdEditText));
|
||||
mAppKeyClearImageView.setOnClickListener((view) -> checkForQrOrClear(mAppKeyEditText));
|
||||
mPlayDomainClearImageView.setOnClickListener((view) -> checkForQrOrClear(mPlayDomainEditText));
|
||||
|
||||
mConfirmTextView.setOnClickListener((view) -> {
|
||||
if (checkEnable()) {
|
||||
String appId = mAppIdEditText.getText().toString();
|
||||
String appKey = mAppKeyEditText.getText().toString();
|
||||
String playDomain = mPlayDomainEditText.getText().toString();
|
||||
SharedPreferenceUtils.setAppInfo(getApplicationContext(), appId, appKey, playDomain);
|
||||
if (!mFromEditor) {
|
||||
ARouter.getInstance()
|
||||
.build("/interactiveCommon/liveInput")
|
||||
.withInt(InteractiveConstants.DATA_TYPE_SCENE, mSceneType)
|
||||
.navigation();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
mAppIdEditText.setText(SharedPreferenceUtils.getAppId(getApplicationContext().getApplicationContext()));
|
||||
mAppKeyEditText.setText(SharedPreferenceUtils.getAppKey(getApplicationContext().getApplicationContext()));
|
||||
mPlayDomainEditText.setText(SharedPreferenceUtils.getPlayDomain(getApplicationContext().getApplicationContext()));
|
||||
}
|
||||
|
||||
private void checkForQrOrClear(EditText editText) {
|
||||
String content = editText.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
mCurrentEditText = editText;
|
||||
startQr();
|
||||
} else {
|
||||
editText.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
private void changeConfirmTextView(boolean enable) {
|
||||
if (enable) {
|
||||
mConfirmTextView.setBackground(getResources().getDrawable(R.drawable.shape_pysh_btn_bg));
|
||||
} else {
|
||||
mConfirmTextView.setBackground(getResources().getDrawable(R.drawable.shape_rect_blue));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkEnable() {
|
||||
String appId = mAppIdEditText.getText().toString();
|
||||
String appKey = mAppKeyEditText.getText().toString();
|
||||
String playDomain = mPlayDomainEditText.getText().toString();
|
||||
return !TextUtils.isEmpty(appId) && !TextUtils.isEmpty(appKey) && !TextUtils.isEmpty(playDomain);
|
||||
}
|
||||
|
||||
private void startQr() {
|
||||
if (ContextCompat.checkSelfPermission(InteractiveAppInfoActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||
// Do not have the permission of camera, request it.
|
||||
ActivityCompat.requestPermissions(InteractiveAppInfoActivity.this, new String[]{Manifest.permission.CAMERA}, REQ_CODE_PERMISSION);
|
||||
} else {
|
||||
// Have gotten the permission
|
||||
startCaptureActivityForResult();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
switch (requestCode) {
|
||||
case REQ_CODE_PERMISSION: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// User agree the permission
|
||||
startCaptureActivityForResult();
|
||||
} else {
|
||||
// User disagree the permission
|
||||
Toast.makeText(this, "You must agree the camera permission request before you use the code scan function", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case CaptureActivity.REQ_CODE:
|
||||
switch (resultCode) {
|
||||
case RESULT_OK:
|
||||
if (mCurrentEditText != null) {
|
||||
mCurrentEditText.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
break;
|
||||
case RESULT_CANCELED:
|
||||
if (data != null && mCurrentEditText != null) {
|
||||
// for some reason camera is not working correctly
|
||||
mCurrentEditText.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void startCaptureActivityForResult() {
|
||||
Intent intent = new Intent(InteractiveAppInfoActivity.this, CaptureActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(CaptureActivity.KEY_NEED_BEEP, CaptureActivity.VALUE_BEEP);
|
||||
bundle.putBoolean(CaptureActivity.KEY_NEED_VIBRATION, CaptureActivity.VALUE_VIBRATION);
|
||||
bundle.putBoolean(CaptureActivity.KEY_NEED_EXPOSURE, CaptureActivity.VALUE_NO_EXPOSURE);
|
||||
bundle.putByte(CaptureActivity.KEY_FLASHLIGHT_MODE, CaptureActivity.VALUE_FLASHLIGHT_OFF);
|
||||
bundle.putByte(CaptureActivity.KEY_ORIENTATION_MODE, CaptureActivity.VALUE_ORIENTATION_AUTO);
|
||||
bundle.putBoolean(CaptureActivity.KEY_SCAN_AREA_FULL_SCREEN, CaptureActivity.VALUE_SCAN_AREA_FULL_SCREEN);
|
||||
bundle.putBoolean(CaptureActivity.KEY_NEED_SCAN_HINT_TEXT, CaptureActivity.VALUE_SCAN_HINT_TEXT);
|
||||
intent.putExtra(CaptureActivity.EXTRA_SETTING_BUNDLE, bundle);
|
||||
startActivityForResult(intent, CaptureActivity.REQ_CODE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.alivc.live.interactive_common;
|
||||
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayVideoStreamType;
|
||||
import com.alivc.live.pusher.AlivcLiveMixSourceType;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* @author keria
|
||||
* @date 2023/10/30
|
||||
* @brief
|
||||
*/
|
||||
public class InteractiveBaseUtil {
|
||||
|
||||
private InteractiveBaseUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机房间号和用户id
|
||||
*
|
||||
* @param sceneType 场景;直播连麦场景随机数0-100,PK场景随机数100-999,以此区分
|
||||
* @param listener 回调结果
|
||||
*/
|
||||
public static void generateRandomId(int sceneType, OnRandomIdListener listener) {
|
||||
Random random = new Random();
|
||||
int randomNumber;
|
||||
|
||||
String channelId;
|
||||
String userId;
|
||||
if (sceneType == InteractiveConstants.SCENE_TYPE_INTERACTIVE_LIVE) {
|
||||
randomNumber = random.nextInt(99) + 1;
|
||||
String randomNumberStr = String.valueOf(randomNumber);
|
||||
userId = randomNumberStr; // 互动直播的场景,用户ID随机数范围 0-99
|
||||
channelId = randomNumberStr; // 互动直播的场景,房间ID随机数范围 0-99
|
||||
} else {
|
||||
randomNumber = random.nextInt(900) + 100; // 非互动直播的场景,随机数范围 0-999
|
||||
String randomNumberStr = String.valueOf(randomNumber);
|
||||
channelId = randomNumberStr;// 设置房间ID
|
||||
userId = randomNumberStr;// 设置用户ID,与房间ID相同
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
listener.onResult(channelId, userId);
|
||||
}
|
||||
}
|
||||
|
||||
public static AlivcLiveMixSourceType covertVideoStreamType2MixSourceType(AlivcLivePlayVideoStreamType videoStreamType) {
|
||||
if (videoStreamType == AlivcLivePlayVideoStreamType.STREAM_SCREEN) {
|
||||
return AlivcLiveMixSourceType.SOURCE_SCREEN;
|
||||
}
|
||||
return AlivcLiveMixSourceType.SOURCE_CAMERA;
|
||||
}
|
||||
|
||||
public interface OnRandomIdListener {
|
||||
void onResult(String channelId, String userId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.alivc.live.interactive_common;
|
||||
|
||||
/**
|
||||
* @author keria
|
||||
* @date 2024/5/29
|
||||
* @brief 互动直播常量类
|
||||
*/
|
||||
public @interface InteractiveConstants {
|
||||
String DATA_TYPE_INTERACTIVE_USER_DATA = "user_data";
|
||||
String DATA_TYPE_IS_ANCHOR = "IS_ANCHOR";
|
||||
String DATA_TYPE_SCENE = "SCENE";
|
||||
|
||||
String KEY_TYPE_SCENE_MULTI_PK_16IN = "scene_multi_pk_16in";
|
||||
|
||||
int SCENE_TYPE_INTERACTIVE_LIVE = 0;
|
||||
int SCENE_TYPE_PK_LIVE = 1;
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
package com.alivc.live.interactive_common;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.acker.simplezxing.activity.CaptureActivity;
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.alivc.live.commonbiz.backdoor.BackDoorInstance;
|
||||
import com.alivc.live.commonbiz.test.AliLiveStreamURLUtil;
|
||||
import com.alivc.live.commonui.utils.StatusBarUtil;
|
||||
import com.alivc.live.commonutils.TextFormatUtil;
|
||||
import com.alivc.live.commonutils.ToastUtils;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
import com.alivc.live.interactive_common.utils.LivePushGlobalConfig;
|
||||
import com.alivc.live.interactive_common.widget.InteractLiveRadioButton;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author keria
|
||||
* @date 2024/5/29
|
||||
* @brief 互动直播房间号/用户ID输入页面
|
||||
*/
|
||||
@Route(path = "/interactiveCommon/liveInput")
|
||||
public class InteractiveInputActivity extends AppCompatActivity {
|
||||
|
||||
private EditText mUserIdEdt;
|
||||
private EditText mRoomIdEdt;
|
||||
|
||||
private ImageView mUserIdClearIv;
|
||||
private ImageView mRoomIdClearIv;
|
||||
|
||||
private TextView mURLEntranceTv;
|
||||
private TextView mInteractiveURLTv;
|
||||
|
||||
private TextView mSettingTv;
|
||||
private TextView mConfirmTv;
|
||||
private ImageView mBackIv;
|
||||
|
||||
// 直播连麦场景下的主播/观众角色选取
|
||||
private InteractLiveRadioButton mAnchorRb;
|
||||
private InteractLiveRadioButton mAudienceRb;
|
||||
|
||||
// 场景类型,PK直播 or 连麦直播
|
||||
private int mSceneType = InteractiveConstants.SCENE_TYPE_INTERACTIVE_LIVE;
|
||||
private boolean isAnchor = true;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
StatusBarUtil.translucent(this, Color.TRANSPARENT);
|
||||
|
||||
setContentView(R.layout.activity_interactive_input);
|
||||
|
||||
// 获取场景类型
|
||||
mSceneType = getIntent().getIntExtra(InteractiveConstants.DATA_TYPE_SCENE, InteractiveConstants.SCENE_TYPE_INTERACTIVE_LIVE);
|
||||
|
||||
initView();
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mUserIdEdt = findViewById(R.id.et_user_id);
|
||||
mRoomIdEdt = findViewById(R.id.et_room_id);
|
||||
mUserIdClearIv = findViewById(R.id.iv_user_id_clear);
|
||||
mRoomIdClearIv = findViewById(R.id.iv_room_id_clear);
|
||||
|
||||
mURLEntranceTv = findViewById(R.id.tv_url_entrance);
|
||||
mInteractiveURLTv = findViewById(R.id.tv_interactive_url);
|
||||
|
||||
// Update page title
|
||||
TextView titleTv = findViewById(R.id.tv_title);
|
||||
titleTv.setText(mSceneType == InteractiveConstants.SCENE_TYPE_PK_LIVE ? getString(R.string.pk_live) : getString(R.string.interact_live));
|
||||
|
||||
mSettingTv = findViewById(R.id.tv_setting);
|
||||
mBackIv = findViewById(R.id.iv_back);
|
||||
mConfirmTv = findViewById(R.id.tv_confirm);
|
||||
|
||||
View roleContainer = findViewById(R.id.role_container);
|
||||
roleContainer.setVisibility(mSceneType == InteractiveConstants.SCENE_TYPE_PK_LIVE ? View.GONE : View.VISIBLE);
|
||||
|
||||
mAnchorRb = findViewById(R.id.radio_button_anchor);
|
||||
mAnchorRb.setChecked(true);
|
||||
mAudienceRb = findViewById(R.id.radio_button_audience);
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
InteractLiveAppInfoFragment interactLiveAppInfoFragment = (InteractLiveAppInfoFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_app_info);
|
||||
if (interactLiveAppInfoFragment != null) {
|
||||
interactLiveAppInfoFragment.setOnEditClickListener(new InteractLiveAppInfoFragment.OnEditClickListener() {
|
||||
@Override
|
||||
public void onLongClickAppInfoForDebug() {
|
||||
InteractiveBaseUtil.generateRandomId(mSceneType, (channelId, userId) -> {
|
||||
if (TextUtils.isEmpty(mRoomIdEdt.getText())) {
|
||||
mRoomIdEdt.setText(channelId);
|
||||
}
|
||||
if (TextUtils.isEmpty(mUserIdEdt.getText())) {
|
||||
mUserIdEdt.setText(userId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEditClickListener() {
|
||||
Intent intent = new Intent(InteractiveInputActivity.this, InteractiveAppInfoActivity.class);
|
||||
intent.putExtra(InteractiveAppInfoActivity.FROM_EDITOR, true);
|
||||
intent.putExtra(InteractiveConstants.DATA_TYPE_SCENE, mSceneType);
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mBackIv.setOnClickListener(view -> finish());
|
||||
|
||||
mURLEntranceTv.setOnClickListener(v -> {
|
||||
startCaptureActivityForResult();
|
||||
});
|
||||
|
||||
mSettingTv.setOnClickListener(view -> {
|
||||
Intent intent = new Intent(this, InteractiveSettingActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
mUserIdEdt.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
changeConfirmTextView(checkEnable());
|
||||
}
|
||||
});
|
||||
|
||||
mRoomIdEdt.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
changeConfirmTextView(checkEnable());
|
||||
}
|
||||
});
|
||||
|
||||
mAnchorRb.setOnClickListener(view -> {
|
||||
isAnchor = true;
|
||||
mAnchorRb.setChecked(true);
|
||||
mAudienceRb.setChecked(false);
|
||||
});
|
||||
|
||||
mAudienceRb.setOnClickListener(view -> {
|
||||
isAnchor = false;
|
||||
mAnchorRb.setChecked(false);
|
||||
mAudienceRb.setChecked(true);
|
||||
});
|
||||
|
||||
mUserIdClearIv.setOnClickListener(view -> mUserIdEdt.setText(""));
|
||||
mRoomIdClearIv.setOnClickListener(view -> mRoomIdEdt.setText(""));
|
||||
|
||||
mConfirmTv.setOnClickListener(view -> {
|
||||
if (checkEnable()) {
|
||||
startInteractiveActivity();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void changeConfirmTextView(boolean enable) {
|
||||
if (enable) {
|
||||
mConfirmTv.setBackground(getResources().getDrawable(R.drawable.shape_pysh_btn_bg));
|
||||
} else {
|
||||
mConfirmTv.setBackground(getResources().getDrawable(R.drawable.shape_rect_blue));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkEnable() {
|
||||
String url = mInteractiveURLTv.getText().toString();
|
||||
if (!TextUtils.isEmpty(url)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String userId = mUserIdEdt.getText().toString();
|
||||
String roomId = mRoomIdEdt.getText().toString();
|
||||
return !TextUtils.isEmpty(userId) && !TextUtils.isEmpty(roomId) && Pattern.matches(TextFormatUtil.REGULAR, userId) && Pattern.matches(TextFormatUtil.REGULAR, roomId);
|
||||
}
|
||||
|
||||
private void startInteractiveActivity() {
|
||||
String schema;
|
||||
if (mSceneType == InteractiveConstants.SCENE_TYPE_PK_LIVE) {
|
||||
schema = LivePushGlobalConfig.IS_MULTI_INTERACT
|
||||
? "/interactivePK/multiPKLive"
|
||||
: "/interactivePK/pkLive";
|
||||
} else {
|
||||
schema = LivePushGlobalConfig.IS_MULTI_INTERACT
|
||||
? "/interactiveLive/multiInteractLive"
|
||||
: "/interactiveLive/interactLive";
|
||||
}
|
||||
|
||||
ARouter.getInstance()
|
||||
.build(schema)
|
||||
.withSerializable(InteractiveConstants.DATA_TYPE_INTERACTIVE_USER_DATA, generateUserData())
|
||||
.withBoolean(InteractiveConstants.DATA_TYPE_IS_ANCHOR, isAnchor)
|
||||
.withBoolean(InteractiveConstants.KEY_TYPE_SCENE_MULTI_PK_16IN, BackDoorInstance.getInstance().isUseMultiPK16IN())
|
||||
.navigation();
|
||||
}
|
||||
|
||||
private void startCaptureActivityForResult() {
|
||||
Intent intent = new Intent(InteractiveInputActivity.this, CaptureActivity.class);
|
||||
startActivityForResult(intent, CaptureActivity.REQ_CODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == CaptureActivity.REQ_CODE) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
String pushUrl = data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT);
|
||||
if (TextUtils.isEmpty(pushUrl)) {
|
||||
return;
|
||||
}
|
||||
mInteractiveURLTv.setText(pushUrl);
|
||||
clearInputUserInfo(true);
|
||||
changeConfirmTextView(checkEnable());
|
||||
checkPushURLSDKAppID(pushUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清除输入的用户信息
|
||||
private void clearInputUserInfo(boolean useUrl) {
|
||||
if (useUrl) {
|
||||
mUserIdEdt.setText("");
|
||||
mRoomIdEdt.setText("");
|
||||
} else {
|
||||
mInteractiveURLTv.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果当前以URL方式输入的 sdkAppId 和 demo 当前环境使用的 sdkAppId 不一致,则提示 toast,以免业务异常
|
||||
private void checkPushURLSDKAppID(String pushURL) {
|
||||
if (TextUtils.isEmpty(pushURL)) {
|
||||
return;
|
||||
}
|
||||
HashMap<String, String> params = AliLiveStreamURLUtil.parseUrl(pushURL);
|
||||
String sdkAppId = params.get(AliLiveStreamURLUtil.SDK_APP_ID);
|
||||
if (!TextUtils.equals(sdkAppId, AliLiveStreamURLUtil.APP_ID)) {
|
||||
ToastUtils.show(getString(R.string.tips_interactive_url_use_different_sdkappid));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 user data,里面存有房间号,用户id,实际推流地址等信息
|
||||
*
|
||||
* @return user data
|
||||
*/
|
||||
private InteractiveUserData generateUserData() {
|
||||
String channelId = mRoomIdEdt.getText().toString();
|
||||
String userId = mUserIdEdt.getText().toString();
|
||||
String pushURL = mInteractiveURLTv.getText().toString();
|
||||
|
||||
InteractiveUserData userData = new InteractiveUserData();
|
||||
if (!TextUtils.isEmpty(channelId) && !TextUtils.isEmpty(userId)) {
|
||||
userData.userId = userId;
|
||||
userData.channelId = channelId;
|
||||
userData.url = AliLiveStreamURLUtil.generateInteractivePushUrl(channelId, userId);
|
||||
} else if (!TextUtils.isEmpty(pushURL)) {
|
||||
HashMap<String, String> params = AliLiveStreamURLUtil.parseUrl(pushURL);
|
||||
userData.channelId = AliLiveStreamURLUtil.parseURLStreamName(params);
|
||||
userData.userId = params.get(AliLiveStreamURLUtil.USER_ID);
|
||||
userData.url = pushURL;
|
||||
}
|
||||
return userData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.alivc.live.interactive_common;
|
||||
|
||||
/**
|
||||
* @author keria
|
||||
* @date 2023/10/27
|
||||
* @brief DEMO互动模式业务类型
|
||||
*/
|
||||
public enum InteractiveMode {
|
||||
|
||||
/**
|
||||
* 1v1连麦
|
||||
*/
|
||||
INTERACTIVE(0x10),
|
||||
|
||||
/**
|
||||
* 多人连麦
|
||||
*/
|
||||
MULTI_INTERACTIVE(0x11),
|
||||
|
||||
/**
|
||||
* 1v1 PK
|
||||
*/
|
||||
PK(0x20),
|
||||
|
||||
/**
|
||||
* 多人PK
|
||||
*/
|
||||
MULTI_PK(0x21),
|
||||
|
||||
/**
|
||||
* 1v1推拉裸流
|
||||
*/
|
||||
BARE_STREAM(0x30),
|
||||
|
||||
/**
|
||||
* 多人推拉裸流
|
||||
*/
|
||||
MULTI_BARE_STREAM(0x31),
|
||||
;
|
||||
|
||||
private final int mode;
|
||||
|
||||
InteractiveMode(int mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是直播连麦(先推后拉)
|
||||
*
|
||||
* @param interactiveMode 互动模式业务类型
|
||||
* @return true->是,false->否
|
||||
*/
|
||||
public static boolean isInteractive(InteractiveMode interactiveMode) {
|
||||
return interactiveMode == INTERACTIVE
|
||||
|| interactiveMode == MULTI_INTERACTIVE
|
||||
|| interactiveMode == PK
|
||||
|| interactiveMode == MULTI_PK;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是推拉裸流(直推直拉)
|
||||
*
|
||||
* @param interactiveMode 互动模式业务类型
|
||||
* @return true->是,false->否
|
||||
*/
|
||||
public static boolean isBareStream(InteractiveMode interactiveMode) {
|
||||
return interactiveMode == BARE_STREAM
|
||||
|| interactiveMode == MULTI_BARE_STREAM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
package com.alivc.live.interactive_common;
|
||||
|
||||
import static com.alivc.live.interactive_common.utils.LivePushGlobalConfig.mAlivcLivePushConfig;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.alivc.live.annotations.AlivcLiveCameraCaptureOutputPreference;
|
||||
import com.alivc.live.commonbiz.ResourcesDownload;
|
||||
import com.alivc.live.commonbiz.SharedPreferenceUtils;
|
||||
import com.alivc.live.commonui.configview.LivePushSettingView;
|
||||
import com.alivc.live.commonui.utils.StatusBarUtil;
|
||||
import com.alivc.live.commonui.widgets.AVLiveLoadingDialog;
|
||||
import com.alivc.live.commonutils.DownloadUtil;
|
||||
import com.alivc.live.commonutils.ToastUtils;
|
||||
import com.alivc.live.interactive_common.utils.LivePushGlobalConfig;
|
||||
import com.alivc.live.pusher.AlivcAudioChannelEnum;
|
||||
import com.alivc.live.pusher.AlivcAudioSampleRateEnum;
|
||||
import com.alivc.live.pusher.AlivcAudioSceneModeEnum;
|
||||
import com.alivc.live.pusher.AlivcEncodeModeEnum;
|
||||
import com.alivc.live.pusher.AlivcImageFormat;
|
||||
import com.alivc.live.pusher.AlivcLivePushCameraTypeEnum;
|
||||
import com.alivc.live.pusher.AlivcPreviewOrientationEnum;
|
||||
import com.alivc.live.pusher.AlivcResolutionEnum;
|
||||
import com.alivc.live.pusher.AlivcSoundFormat;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class InteractiveSettingActivity extends AppCompatActivity {
|
||||
|
||||
private View mTabArgsLayout;
|
||||
private View mTabActionLayout;
|
||||
private View mTabArgsView;
|
||||
private View mTabActionView;
|
||||
private ImageView mBackImageView;
|
||||
private Switch mMultiInteractSwitch;
|
||||
private Switch mH5CompatibleSwitch;
|
||||
private Switch mDataChannelSwitch;
|
||||
private Switch mEarbackOpenWithoutHeadsetSwitch;
|
||||
private TextView mCameraCaptureOutputPreferenceTv;
|
||||
private Button mCommitButton;
|
||||
private AVLiveLoadingDialog mLoadingDialog;
|
||||
|
||||
private LivePushSettingView mLivePushSettingView;
|
||||
private AlivcResolutionEnum mCurrentResolution;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
StatusBarUtil.translucent(this, Color.TRANSPARENT);
|
||||
|
||||
setContentView(R.layout.activity_interactive_setting);
|
||||
|
||||
initView();
|
||||
initData();
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mBackImageView = findViewById(R.id.iv_back);
|
||||
mCommitButton = findViewById(R.id.btn_commit);
|
||||
mMultiInteractSwitch = findViewById(R.id.multi_interaction_control);
|
||||
mMultiInteractSwitch.setChecked(LivePushGlobalConfig.IS_MULTI_INTERACT);
|
||||
mH5CompatibleSwitch = findViewById(R.id.h5_compatible_control);
|
||||
mH5CompatibleSwitch.setChecked(LivePushGlobalConfig.IS_H5_COMPATIBLE);
|
||||
mDataChannelSwitch = findViewById(R.id.data_channel_control);
|
||||
mDataChannelSwitch.setChecked(LivePushGlobalConfig.IS_DATA_CHANNEL_MESSAGE_ENABLE);
|
||||
|
||||
mEarbackOpenWithoutHeadsetSwitch = findViewById(R.id.earback_open_without_headset_control);
|
||||
mEarbackOpenWithoutHeadsetSwitch.setChecked(LivePushGlobalConfig.IS_EARBACK_OPEN_WITHOUT_HEADSET);
|
||||
|
||||
mCameraCaptureOutputPreferenceTv = findViewById(R.id.setting_camera_capture_output_preference);
|
||||
String cameraCaptureOutputPreferenceText = getTextFromCameraCaptureOutputPreference(LivePushGlobalConfig.CAMERA_CAPTURE_OUTPUT_PREFERENCE);
|
||||
mCameraCaptureOutputPreferenceTv.setText(cameraCaptureOutputPreferenceText);
|
||||
|
||||
mTabArgsLayout = findViewById(R.id.tab_args_layout);
|
||||
mTabActionLayout = findViewById(R.id.tab_action_layout);
|
||||
mTabArgsView = findViewById(R.id.tab_args_view);
|
||||
mTabActionView = findViewById(R.id.tab_action_view);
|
||||
mLivePushSettingView = findViewById(R.id.setting_view);
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mLivePushSettingView.setDefaultConfig(mAlivcLivePushConfig, LivePushGlobalConfig.ENABLE_BEAUTY, LivePushGlobalConfig.ENABLE_LOCAL_LOG, LivePushGlobalConfig.ENABLE_WATER_MARK);
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mLivePushSettingView.bitrateControl.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setEnableBitrateControl(isChecked);
|
||||
});
|
||||
mLivePushSettingView.targetVideoBitrate.observe(this, bitrate -> {
|
||||
SharedPreferenceUtils.setHintTargetBit(getApplicationContext(), bitrate);
|
||||
mAlivcLivePushConfig.setTargetVideoBitrate(bitrate);
|
||||
});
|
||||
mLivePushSettingView.minVideoBitrate.observe(this, bitrate -> {
|
||||
SharedPreferenceUtils.setHintMinBit(getApplicationContext(), bitrate);
|
||||
mAlivcLivePushConfig.setMinVideoBitrate(bitrate);
|
||||
});
|
||||
mLivePushSettingView.initialVideoBitrate.observe(this, bitrate -> {
|
||||
SharedPreferenceUtils.setHintMinBit(getApplicationContext(), bitrate);
|
||||
mAlivcLivePushConfig.setInitialVideoBitrate(bitrate);
|
||||
});
|
||||
mLivePushSettingView.audioBitrate.observe(this, bitrate -> {
|
||||
SharedPreferenceUtils.setHintMinBit(getApplicationContext(), bitrate);
|
||||
mAlivcLivePushConfig.setAudioBitRate(bitrate);
|
||||
});
|
||||
mLivePushSettingView.variableResolution.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setEnableAutoResolution(isChecked);
|
||||
});
|
||||
mLivePushSettingView.minFps.observe(this, minFps -> {
|
||||
mAlivcLivePushConfig.setMinFps(minFps);
|
||||
});
|
||||
mLivePushSettingView.audioSampleRate.observe(this, sampleRate -> {
|
||||
mAlivcLivePushConfig.setAudioSampleRate(sampleRate);
|
||||
});
|
||||
mLivePushSettingView.gop.observe(this, gop -> {
|
||||
mAlivcLivePushConfig.setVideoEncodeGop(gop);
|
||||
});
|
||||
mLivePushSettingView.fps.observe(this, fps -> {
|
||||
mAlivcLivePushConfig.setFps(fps);
|
||||
});
|
||||
mLivePushSettingView.videoHardwareDecode.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setVideoEncodeMode(isChecked ? AlivcEncodeModeEnum.Encode_MODE_HARD : AlivcEncodeModeEnum.Encode_MODE_SOFT);
|
||||
});
|
||||
mLivePushSettingView.audioHardwareDecode.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setAudioEncodeMode(isChecked ? AlivcEncodeModeEnum.Encode_MODE_HARD : AlivcEncodeModeEnum.Encode_MODE_SOFT);
|
||||
});
|
||||
mLivePushSettingView.pushMirror.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setPushMirror(isChecked);
|
||||
});
|
||||
mLivePushSettingView.previewMirror.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setPreviewMirror(isChecked);
|
||||
});
|
||||
mLivePushSettingView.enableFrontCamera.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setCameraType(isChecked ? AlivcLivePushCameraTypeEnum.CAMERA_TYPE_FRONT : AlivcLivePushCameraTypeEnum.CAMERA_TYPE_BACK);
|
||||
// mCameraId = (isChecked ? AlivcLivePushCameraTypeEnum.CAMERA_TYPE_FRONT.getCameraId() : AlivcLivePushCameraTypeEnum.CAMERA_TYPE_BACK.getCameraId());
|
||||
});
|
||||
mLivePushSettingView.autoFocus.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setAutoFocus(isChecked);
|
||||
});
|
||||
mLivePushSettingView.enableBeauty.observe(this, isChecked -> {
|
||||
LivePushGlobalConfig.ENABLE_BEAUTY = isChecked;
|
||||
});
|
||||
mLivePushSettingView.videoOnly.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setVideoOnly(isChecked);
|
||||
});
|
||||
mLivePushSettingView.audioOnly.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setAudioOnly(isChecked);
|
||||
});
|
||||
mLivePushSettingView.pauseImage.observe(this, isChecked -> {
|
||||
if (!isChecked) {
|
||||
mAlivcLivePushConfig.setPausePushImage("");
|
||||
} else {
|
||||
if (mAlivcLivePushConfig.getPreviewOrientation() == AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_LEFT.getOrientation() || mAlivcLivePushConfig.getPreviewOrientation() == AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_RIGHT.getOrientation()) {
|
||||
mAlivcLivePushConfig.setPausePushImage(getFilesDir().getPath() + File.separator + "alivc_resource/background_push_land.png");
|
||||
} else {
|
||||
mAlivcLivePushConfig.setPausePushImage(getFilesDir().getPath() + File.separator + "alivc_resource/background_push.png");
|
||||
}
|
||||
}
|
||||
});
|
||||
mLivePushSettingView.netWorkImage.observe(this, isChecked -> {
|
||||
if (!isChecked) {
|
||||
mAlivcLivePushConfig.setNetworkPoorPushImage("");
|
||||
} else {
|
||||
if (mAlivcLivePushConfig.getPreviewOrientation() == AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_LEFT.getOrientation() || mAlivcLivePushConfig.getPreviewOrientation() == AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_RIGHT.getOrientation()) {
|
||||
mAlivcLivePushConfig.setNetworkPoorPushImage(getFilesDir().getPath() + File.separator + "alivc_resource/poor_network_land.png");
|
||||
} else {
|
||||
mAlivcLivePushConfig.setNetworkPoorPushImage(getFilesDir().getPath() + File.separator + "alivc_resource/poor_network.png");
|
||||
}
|
||||
}
|
||||
});
|
||||
mLivePushSettingView.musicMode.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setAudioSceneMode(isChecked ? AlivcAudioSceneModeEnum.AUDIO_SCENE_MUSIC_MODE : AlivcAudioSceneModeEnum.AUDIO_SCENE_DEFAULT_MODE);
|
||||
});
|
||||
mLivePushSettingView.extern.observe(this, isChecked -> {
|
||||
mAlivcLivePushConfig.setExternMainStream(isChecked, AlivcImageFormat.IMAGE_FORMAT_YUVNV12, AlivcSoundFormat.SOUND_FORMAT_S16);
|
||||
mAlivcLivePushConfig.setAudioChannels(AlivcAudioChannelEnum.AUDIO_CHANNEL_ONE);
|
||||
mAlivcLivePushConfig.setAudioSampleRate(AlivcAudioSampleRateEnum.AUDIO_SAMPLE_RATE_44100);
|
||||
if (isChecked) {
|
||||
startDownloadYUV();
|
||||
}
|
||||
});
|
||||
mLivePushSettingView.localLog.observe(this, isChecked -> {
|
||||
LivePushGlobalConfig.ENABLE_LOCAL_LOG = isChecked;
|
||||
});
|
||||
|
||||
mLivePushSettingView.previewDisplayMode.observe(this, previewDisplayMode -> {
|
||||
mAlivcLivePushConfig.setPreviewDisplayMode(previewDisplayMode);
|
||||
});
|
||||
|
||||
mLivePushSettingView.cameraCaptureOutputPreference.observe(this, preference -> {
|
||||
mAlivcLivePushConfig.setCameraCaptureOutputPreference(preference);
|
||||
});
|
||||
|
||||
mLivePushSettingView.audioChannel.observe(this, audioChannel -> {
|
||||
mAlivcLivePushConfig.setAudioChannels(audioChannel);
|
||||
});
|
||||
|
||||
mLivePushSettingView.audioProfile.observe(this, audioProfile -> {
|
||||
mAlivcLivePushConfig.setAudioProfile(audioProfile);
|
||||
});
|
||||
|
||||
mLivePushSettingView.videoEncodeType.observe(this, videoEncodeType -> {
|
||||
mAlivcLivePushConfig.setVideoEncodeType(videoEncodeType);
|
||||
});
|
||||
|
||||
mLivePushSettingView.bFrame.observe(this, bFrame -> {
|
||||
mAlivcLivePushConfig.setBFrames(bFrame);
|
||||
});
|
||||
|
||||
mLivePushSettingView.previewOrientation.observe(this, orientation -> {
|
||||
mAlivcLivePushConfig.setPreviewOrientation(orientation);
|
||||
});
|
||||
|
||||
mLivePushSettingView.pauseImagePath.observe(this, path -> {
|
||||
if (mAlivcLivePushConfig.getPausePushImage() == null || mAlivcLivePushConfig.getPausePushImage().equals("")) {
|
||||
mAlivcLivePushConfig.setPausePushImage(path);
|
||||
}
|
||||
});
|
||||
|
||||
mLivePushSettingView.netWorkImagePath.observe(this, path -> {
|
||||
if (mAlivcLivePushConfig.getNetworkPoorPushImage() != null && !mAlivcLivePushConfig.getNetworkPoorPushImage().equals("")) {
|
||||
mAlivcLivePushConfig.setNetworkPoorPushImage(path);
|
||||
}
|
||||
});
|
||||
|
||||
mLivePushSettingView.qualityMode.observe(this, quality -> {
|
||||
mAlivcLivePushConfig.setQualityMode(quality);
|
||||
});
|
||||
|
||||
mLivePushSettingView.resolution.observe(this, resolution -> {
|
||||
this.mCurrentResolution = resolution;
|
||||
if (resolution != AlivcResolutionEnum.RESOLUTION_SELF_DEFINE) {
|
||||
mAlivcLivePushConfig.setResolution(resolution);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
mTabArgsLayout.setOnClickListener(view -> {
|
||||
mTabArgsView.setVisibility(View.VISIBLE);
|
||||
mTabActionView.setVisibility(View.INVISIBLE);
|
||||
mLivePushSettingView.showArgsContent(true);
|
||||
});
|
||||
|
||||
mTabActionLayout.setOnClickListener(view -> {
|
||||
mTabActionView.setVisibility(View.VISIBLE);
|
||||
mTabArgsView.setVisibility(View.INVISIBLE);
|
||||
mLivePushSettingView.showArgsContent(false);
|
||||
});
|
||||
|
||||
mBackImageView.setOnClickListener(view -> {
|
||||
finish();
|
||||
});
|
||||
mCommitButton.setOnClickListener(view -> {
|
||||
if (mCurrentResolution == AlivcResolutionEnum.RESOLUTION_SELF_DEFINE) {
|
||||
AlivcResolutionEnum.RESOLUTION_SELF_DEFINE.setSelfDefineResolution(mLivePushSettingView.getSelfDefineResolutionWidth(), mLivePushSettingView.getSelfDefineResolutionHeight());
|
||||
mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_SELF_DEFINE);
|
||||
}
|
||||
mAlivcLivePushConfig.setConnectRetryCount(mLivePushSettingView.getRetryCount());
|
||||
mAlivcLivePushConfig.setConnectRetryInterval(mLivePushSettingView.getRetryInterval());
|
||||
finish();
|
||||
});
|
||||
mMultiInteractSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
LivePushGlobalConfig.IS_MULTI_INTERACT = isChecked;
|
||||
}
|
||||
});
|
||||
mH5CompatibleSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
LivePushGlobalConfig.IS_H5_COMPATIBLE = isChecked;
|
||||
}
|
||||
});
|
||||
mDataChannelSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
LivePushGlobalConfig.IS_DATA_CHANNEL_MESSAGE_ENABLE = isChecked;
|
||||
}
|
||||
});
|
||||
mEarbackOpenWithoutHeadsetSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
LivePushGlobalConfig.IS_EARBACK_OPEN_WITHOUT_HEADSET = isChecked;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showProgressDialog(@StringRes int tipsResId) {
|
||||
if (null == mLoadingDialog) {
|
||||
mLoadingDialog = new AVLiveLoadingDialog(this).tip(getString(tipsResId));
|
||||
}
|
||||
if (!mLoadingDialog.isShowing()) {
|
||||
mLoadingDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void hideProgressDialog() {
|
||||
if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
|
||||
mLoadingDialog.dismiss();
|
||||
mLoadingDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void startDownloadYUV() {
|
||||
long mCaptureDownloadId = ResourcesDownload.downloadCaptureYUV(this, new DownloadUtil.OnDownloadListener() {
|
||||
@Override
|
||||
public void onDownloadSuccess(long downloadId) {
|
||||
hideProgressDialog();
|
||||
ToastUtils.show("Download Success");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadProgress(long downloadId, double percent) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadError(long downloadId, int errorCode, String errorMsg) {
|
||||
hideProgressDialog();
|
||||
ToastUtils.show(errorMsg);
|
||||
if (errorCode != DownloadManager.ERROR_FILE_ALREADY_EXISTS) {
|
||||
mLivePushSettingView.externDownloadError();
|
||||
}
|
||||
}
|
||||
});
|
||||
showProgressDialog(R.string.waiting_download_video_resources);
|
||||
}
|
||||
|
||||
private String getTextFromCameraCaptureOutputPreference(AlivcLiveCameraCaptureOutputPreference cameraCaptureOutputPreference) {
|
||||
if (cameraCaptureOutputPreference == AlivcLiveCameraCaptureOutputPreference.AUTO) {
|
||||
return getString(R.string.camera_capture_output_preference_auto);
|
||||
} else if (cameraCaptureOutputPreference == AlivcLiveCameraCaptureOutputPreference.PERFORMANCE) {
|
||||
return getString(R.string.camera_capture_output_preference_performance);
|
||||
} else if (cameraCaptureOutputPreference == AlivcLiveCameraCaptureOutputPreference.PREVIEW) {
|
||||
return getString(R.string.camera_capture_output_preference_preview);
|
||||
} else {
|
||||
return getString(R.string.camera_capture_output_preference_preview);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.alivc.live.interactive_common.bean;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.alivc.live.annotations.AlivcLiveMode;
|
||||
import com.alivc.live.annotations.AlivcLiveNetworkQuality;
|
||||
import com.alivc.live.commonutils.ToastUtils;
|
||||
import com.alivc.live.interactive_common.listener.InteractLivePushPullListener;
|
||||
import com.alivc.live.player.AlivcLivePlayInfoListener;
|
||||
import com.alivc.live.player.AlivcLivePlayerImpl;
|
||||
import com.alivc.live.player.AlivcLivePlayerStatsInfo;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayError;
|
||||
|
||||
/**
|
||||
* AlivcLivePlayer 封装类,用于直播连麦拉流
|
||||
*/
|
||||
public class InteractiveLivePlayer extends AlivcLivePlayerImpl {
|
||||
private static final String TAG = InteractiveLivePlayer.class.getSimpleName();
|
||||
|
||||
private InteractLivePushPullListener mListener;
|
||||
private boolean mIsPulling = false;
|
||||
|
||||
private final AlivcLivePlayInfoListener mAlivcLivePlayInfoListener = new AlivcLivePlayInfoListener() {
|
||||
|
||||
@Override
|
||||
public void onPlayStarted() {
|
||||
Log.i(TAG, "onPlayStarted: " + mPullUserData);
|
||||
mIsPulling = true;
|
||||
if (mListener != null) {
|
||||
mListener.onPullSuccess(mPullUserData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayStopped() {
|
||||
Log.i(TAG, "onPlayStopped: " + mPullUserData);
|
||||
notifyPullStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFirstVideoFrameDrawn() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkQualityChanged(AlivcLiveNetworkQuality upQuality, AlivcLiveNetworkQuality downQuality) {
|
||||
Log.w(TAG, "onNetworkQualityChanged: " + upQuality + ", " + downQuality);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveSEIMessage(int payload, byte[] data) {
|
||||
//Log.d(TAG, "onReceiveSEIMessage: " + payload + ", " + new String(data, StandardCharsets.UTF_8));
|
||||
if (mListener != null) {
|
||||
mListener.onReceiveSEIMessage(payload, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveDataChannelMessage(byte[] data) {
|
||||
super.onReceiveDataChannelMessage(data);
|
||||
//Log.d(TAG, "onReceiveDataChannelMessage: " + new String(data, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayoutVolumeUpdate(int volume, boolean isSpeaking) {
|
||||
// 音频音量(仅互动模式下生效,需设置AlivcLivePusher#enableAudioVolumeIndication接口)
|
||||
// Log.d(TAG, "onPlayoutVolumeUpdate: " + volume + ", " + isSpeaking);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioMuted(boolean mute) {
|
||||
ToastUtils.show("onAudioMuted: " + mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoMuted(boolean mute) {
|
||||
ToastUtils.show("onVideoMuted: " + mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoEnabled(boolean enable) {
|
||||
ToastUtils.show("onVideoEnabled: " + enable);
|
||||
if (mListener != null) {
|
||||
mListener.onVideoEnabled(enable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoResolutionChanged(int width, int height) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(AlivcLivePlayError alivcLivePlayError, String s) {
|
||||
Log.e(TAG, "onError: " + mPullUserData + ", " + alivcLivePlayError + ", " + s);
|
||||
mIsPulling = false;
|
||||
if (mListener != null) {
|
||||
mListener.onPullError(mPullUserData, alivcLivePlayError, s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerStatistics(AlivcLivePlayerStatsInfo statsInfo) {
|
||||
//Log.i(TAG, "onPlayerStatistics: " + statsInfo);
|
||||
}
|
||||
};
|
||||
|
||||
private InteractiveUserData mPullUserData;
|
||||
|
||||
public InteractiveLivePlayer(Context context, AlivcLiveMode mode) {
|
||||
super(context, mode);
|
||||
setPlayInfoListener(mAlivcLivePlayInfoListener);
|
||||
}
|
||||
|
||||
public void setMultiInteractPlayInfoListener(InteractLivePushPullListener listener) {
|
||||
this.mListener = listener;
|
||||
}
|
||||
|
||||
public boolean isPulling() {
|
||||
return mIsPulling;
|
||||
}
|
||||
|
||||
public void setPullUserData(InteractiveUserData userData) {
|
||||
this.mPullUserData = userData;
|
||||
}
|
||||
|
||||
// ugly codes: fix the issue of async callbacks not being executed in stopPlay after executing destroy immediately
|
||||
@Override
|
||||
public void destroy() {
|
||||
notifyPullStop();
|
||||
setPlayInfoListener(null);
|
||||
mListener = null;
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
private void notifyPullStop() {
|
||||
mIsPulling = false;
|
||||
if (mListener != null) {
|
||||
mListener.onPullStop(mPullUserData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.alivc.live.interactive_common.bean;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayAudioStreamType;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayVideoStreamType;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author keria
|
||||
* @date 2023/10/18
|
||||
* @note 直播连麦推拉流用户信息
|
||||
*/
|
||||
public class InteractiveUserData implements Serializable {
|
||||
|
||||
private static final String TAG = InteractiveUserData.class.getSimpleName();
|
||||
|
||||
public String channelId;
|
||||
public String userId;
|
||||
|
||||
public AlivcLivePlayVideoStreamType videoStreamType;
|
||||
public AlivcLivePlayAudioStreamType audioStreamType;
|
||||
|
||||
public String url;
|
||||
|
||||
public String getKey() {
|
||||
if (!TextUtils.isEmpty(channelId) && !TextUtils.isEmpty(userId)) {
|
||||
return String.format("%s_%s_%s", channelId, userId, videoStreamType == AlivcLivePlayVideoStreamType.STREAM_SCREEN ? "screen" : "camera");
|
||||
} else if (!TextUtils.isEmpty(url)) {
|
||||
return url;
|
||||
}
|
||||
Log.e(TAG, "invalid interactive user data");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.alivc.live.interactive_common.listener;
|
||||
|
||||
public interface ConnectionLostListener {
|
||||
void onConfirm();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.alivc.live.interactive_common.listener;
|
||||
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayError;
|
||||
|
||||
public abstract class InteractLivePushPullListener {
|
||||
public void onPullSuccess(InteractiveUserData userData) {}
|
||||
public void onPullError(InteractiveUserData userData, AlivcLivePlayError errorType, String errorMsg) {}
|
||||
public void onPullStop(InteractiveUserData userData) {}
|
||||
public void onPushSuccess(){}
|
||||
public void onPushError(){}
|
||||
public void onVideoEnabled(boolean enable){}
|
||||
public void onConnectionLost(){}
|
||||
public void onReceiveSEIMessage(int payload, byte[] data) {}
|
||||
public void onPlayerSei(int payload, byte[] uuid, byte[] data) {}
|
||||
public void onReceiveSEIDelay(String src, String type, String msg) {}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.alivc.live.interactive_common.listener;
|
||||
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
|
||||
public abstract class InteractLiveTipsViewListener {
|
||||
public void onCancel() {}
|
||||
public void onConfirm() {}
|
||||
public void onInputConfirm(InteractiveUserData userData) {}
|
||||
public void onQrClick() {}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.alivc.live.interactive_common.manager;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.alivc.live.commonutils.BitmapUtil;
|
||||
import com.alivc.live.commonutils.ContextUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author keria
|
||||
* @date 2023/9/15
|
||||
* @brief 时间戳文字水印管理类
|
||||
* @note 每秒生成一帧文字水印的bitmap,回调给外层进行添加水印处理
|
||||
*/
|
||||
public class TimestampWatermarkManager {
|
||||
|
||||
private static final long TIME_INTERVAL = 1000L;
|
||||
|
||||
private final Handler sHandler = new Handler();
|
||||
|
||||
private final Runnable sRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
processEvent();
|
||||
sHandler.postDelayed(this, TIME_INTERVAL);
|
||||
}
|
||||
};
|
||||
|
||||
private OnWatermarkListener mOnWatermarkListener;
|
||||
|
||||
public void init(OnWatermarkListener listener) {
|
||||
mOnWatermarkListener = listener;
|
||||
startHandler();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
removeHandler();
|
||||
mOnWatermarkListener = null;
|
||||
}
|
||||
|
||||
public void processEvent() {
|
||||
if (mOnWatermarkListener != null) {
|
||||
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
|
||||
Bitmap bitmap = BitmapUtil.createTextBitmap(ContextUtils.getContext(), timestamp);
|
||||
mOnWatermarkListener.onWatermarkUpdate(bitmap);
|
||||
if (bitmap != null && !bitmap.isRecycled()) {
|
||||
bitmap.recycle();
|
||||
bitmap = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startHandler() {
|
||||
sHandler.postDelayed(sRunnable, TIME_INTERVAL);
|
||||
}
|
||||
|
||||
private void removeHandler() {
|
||||
sHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
|
||||
public interface OnWatermarkListener {
|
||||
public void onWatermarkUpdate(Bitmap bitmap);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.alivc.live.interactive_common.utils;
|
||||
|
||||
public enum InteractLiveIntent {
|
||||
/**
|
||||
* 关闭页面
|
||||
*/
|
||||
INTENT_FINISH,
|
||||
/**
|
||||
* 停止拉流
|
||||
*/
|
||||
INTENT_STOP_PULL,
|
||||
/**
|
||||
*
|
||||
* 停止推流
|
||||
*/
|
||||
INTENT_STOP_PUSH
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.alivc.live.interactive_common.utils;
|
||||
|
||||
import com.alivc.live.annotations.AlivcLiveCameraCaptureOutputPreference;
|
||||
import com.alivc.live.pusher.AlivcLivePushConfig;
|
||||
|
||||
/**
|
||||
* 直播连麦公共配置
|
||||
*
|
||||
* @note 用于传递配置页的一些公共参数到直播连麦页面
|
||||
*/
|
||||
public class LivePushGlobalConfig {
|
||||
|
||||
/**
|
||||
* 推流配置
|
||||
*/
|
||||
public static AlivcLivePushConfig mAlivcLivePushConfig = new AlivcLivePushConfig();
|
||||
|
||||
/**
|
||||
* 多人互动模式/PK
|
||||
*/
|
||||
public static boolean IS_MULTI_INTERACT = false;
|
||||
|
||||
/**
|
||||
* 开启 Data Channel 自定义消息通道
|
||||
*/
|
||||
public static boolean IS_DATA_CHANNEL_MESSAGE_ENABLE = false;
|
||||
|
||||
/**
|
||||
* 开启强制耳返
|
||||
*/
|
||||
public static boolean IS_EARBACK_OPEN_WITHOUT_HEADSET = false;
|
||||
|
||||
/**
|
||||
* H5兼容模式(可与web连麦互通)
|
||||
*/
|
||||
public static boolean IS_H5_COMPATIBLE = false;
|
||||
|
||||
/**
|
||||
* 美颜
|
||||
*/
|
||||
public static boolean ENABLE_BEAUTY = true;
|
||||
/**
|
||||
* 本地日志
|
||||
*/
|
||||
public static boolean ENABLE_LOCAL_LOG = true;
|
||||
|
||||
/**
|
||||
* 水印
|
||||
*/
|
||||
public static boolean ENABLE_WATER_MARK = false;
|
||||
|
||||
/**
|
||||
* 摄像头采集偏好
|
||||
*/
|
||||
public static AlivcLiveCameraCaptureOutputPreference CAMERA_CAPTURE_OUTPUT_PREFERENCE = AlivcLiveCameraCaptureOutputPreference.PREVIEW;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.alivc.live.commonui.avdialog.AUILiveDialog;
|
||||
import com.alivc.live.interactive_common.R;
|
||||
import com.alivc.live.interactive_common.listener.ConnectionLostListener;
|
||||
|
||||
public class ConnectionLostTipsView extends ConstraintLayout {
|
||||
|
||||
private final Context mContext;
|
||||
private final View inflate;
|
||||
private TextView mConfirmTextView;
|
||||
private AUILiveDialog mAUILiveDialog;
|
||||
private ConnectionLostListener mConnectionLostListener;
|
||||
|
||||
public ConnectionLostTipsView(@NonNull Context context) {
|
||||
this(context,null);
|
||||
}
|
||||
|
||||
public ConnectionLostTipsView(@NonNull Context context, AttributeSet attrs) {
|
||||
this(context, attrs,-1);
|
||||
}
|
||||
|
||||
public ConnectionLostTipsView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
this.mContext = context;
|
||||
mAUILiveDialog = new AUILiveDialog(context);
|
||||
inflate = LayoutInflater.from(mContext).inflate(R.layout.layout_connect_lost_tips_view, this, true);
|
||||
initView();
|
||||
initListener();
|
||||
|
||||
mAUILiveDialog.setContentView(this);
|
||||
}
|
||||
|
||||
private void initView(){
|
||||
mConfirmTextView = inflate.findViewById(R.id.tv_confirm);
|
||||
}
|
||||
|
||||
private void initListener(){
|
||||
mConfirmTextView.setOnClickListener(view -> {
|
||||
if(mConnectionLostListener != null){
|
||||
mConnectionLostListener.onConfirm();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void show(){
|
||||
mAUILiveDialog.show();
|
||||
}
|
||||
|
||||
public void hide(){
|
||||
mAUILiveDialog.dismiss();
|
||||
}
|
||||
|
||||
public void setConnectionLostListener(ConnectionLostListener listener){
|
||||
this.mConnectionLostListener = listener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.alivc.live.interactive_common.R;
|
||||
|
||||
public class InteractLiveRadioButton extends ConstraintLayout {
|
||||
|
||||
private final Context mContext;
|
||||
private ConstraintLayout mConstraintLayoutRootView;
|
||||
private TextView mTitleTextView;
|
||||
|
||||
public InteractLiveRadioButton(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public InteractLiveRadioButton(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, -1);
|
||||
}
|
||||
|
||||
public InteractLiveRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
this.mContext = context;
|
||||
initView();
|
||||
initAttribute(attrs);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
View mRootView = LayoutInflater.from(mContext).inflate(R.layout.layout_interact_live_radio_button, this, true);
|
||||
|
||||
mConstraintLayoutRootView = mRootView.findViewById(R.id.root);
|
||||
mTitleTextView = mRootView.findViewById(R.id.tv_title);
|
||||
}
|
||||
|
||||
private void initAttribute(AttributeSet attrs) {
|
||||
TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.InteractLiveRadioButton);
|
||||
String mText = typedArray.getString(R.styleable.InteractLiveRadioButton_ilrb_text);
|
||||
typedArray.recycle();
|
||||
|
||||
mTitleTextView.setText(mText);
|
||||
}
|
||||
|
||||
public void setChecked(boolean isChecked) {
|
||||
if (isChecked) {
|
||||
mConstraintLayoutRootView.setBackground(getResources().getDrawable(R.drawable.shape_interact_live_selected));
|
||||
} else {
|
||||
mConstraintLayoutRootView.setBackground(getResources().getDrawable(R.drawable.shape_interact_live_unselected));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.alivc.live.interactive_common.R;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
import com.alivc.live.interactive_common.listener.InteractLiveTipsViewListener;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayAudioStreamType;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayVideoStreamType;
|
||||
|
||||
/**
|
||||
* 直播连麦用户信息输入框
|
||||
*/
|
||||
public class InteractiveCommonInputView extends ConstraintLayout {
|
||||
|
||||
public enum ViewType {
|
||||
INTERACTIVE,
|
||||
PK,
|
||||
BARE_STREAM
|
||||
}
|
||||
|
||||
private ViewType mViewType;
|
||||
|
||||
private final Context mContext;
|
||||
private final View inflate;
|
||||
|
||||
private TextView mCancelTextView;
|
||||
private TextView mConfirmTextView;
|
||||
|
||||
private TextView mTipsTextView;
|
||||
private EditText mInputUserIdEditText;
|
||||
private EditText mInputRoomIdEditText;
|
||||
private EditText mInputUrlEditText;
|
||||
|
||||
private ImageView mClearUserIdImageView;
|
||||
private ImageView mClearRoomIdImageView;
|
||||
private ImageView mScanQrImageView;
|
||||
|
||||
private LinearLayout mVideoRadioGroupLayout;
|
||||
private RadioGroup mVideoStreamTypeRadioGroup;
|
||||
private RadioButton mVideoCamaraRadioButton;
|
||||
private RadioButton mVideoScreenRadioButton;
|
||||
|
||||
private LinearLayout mAudioRadioGroupLayout;
|
||||
private RadioGroup mAudioStreamTypeRadioGroup;
|
||||
private RadioButton mAudioMicRadioButton;
|
||||
private RadioButton mAudioDualRadioButton;
|
||||
|
||||
private InteractLiveTipsViewListener mInteractLiveTipsViewListener;
|
||||
|
||||
private boolean mShowInputView;
|
||||
|
||||
public InteractiveCommonInputView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public InteractiveCommonInputView(@NonNull Context context, AttributeSet attrs) {
|
||||
this(context, attrs, -1);
|
||||
}
|
||||
|
||||
public InteractiveCommonInputView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
this.mContext = context;
|
||||
inflate = LayoutInflater.from(mContext).inflate(R.layout.layout_interactive_common_input, this, true);
|
||||
initView();
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mCancelTextView = inflate.findViewById(R.id.tv_cancel);
|
||||
mConfirmTextView = inflate.findViewById(R.id.tv_confirm);
|
||||
mTipsTextView = inflate.findViewById(R.id.tv_tips);
|
||||
|
||||
mInputUserIdEditText = inflate.findViewById(R.id.et_input_user_id);
|
||||
mInputRoomIdEditText = inflate.findViewById(R.id.et_input_room_id);
|
||||
mInputUrlEditText = inflate.findViewById(R.id.et_input_url);
|
||||
|
||||
mClearUserIdImageView = inflate.findViewById(R.id.iv_clear_user_id);
|
||||
mClearRoomIdImageView = inflate.findViewById(R.id.iv_clear_room_id);
|
||||
mScanQrImageView = inflate.findViewById(R.id.iv_scan_qr);
|
||||
|
||||
mVideoRadioGroupLayout = inflate.findViewById(R.id.video_radio_group);
|
||||
mVideoStreamTypeRadioGroup = inflate.findViewById(R.id.rg_video_stream_type);
|
||||
mVideoCamaraRadioButton = inflate.findViewById(R.id.rb_camera);
|
||||
mVideoScreenRadioButton = inflate.findViewById(R.id.rb_screen);
|
||||
|
||||
mAudioRadioGroupLayout = inflate.findViewById(R.id.audio_radio_group);
|
||||
mAudioStreamTypeRadioGroup = inflate.findViewById(R.id.rg_audio_stream_type);
|
||||
mAudioMicRadioButton = inflate.findViewById(R.id.rb_mic);
|
||||
mAudioDualRadioButton = inflate.findViewById(R.id.rb_dual);
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mCancelTextView.setOnClickListener(view -> {
|
||||
if (mInteractLiveTipsViewListener != null) {
|
||||
mInteractLiveTipsViewListener.onCancel();
|
||||
}
|
||||
});
|
||||
|
||||
mConfirmTextView.setOnClickListener(view -> {
|
||||
if (mInteractLiveTipsViewListener == null) {
|
||||
return;
|
||||
}
|
||||
if (!mShowInputView) {
|
||||
mInteractLiveTipsViewListener.onConfirm();
|
||||
return;
|
||||
}
|
||||
InteractiveUserData inputData = new InteractiveUserData();
|
||||
if (mViewType == ViewType.INTERACTIVE) {
|
||||
inputData.userId = mInputUserIdEditText.getText().toString().trim();
|
||||
} else if (mViewType == ViewType.PK) {
|
||||
inputData.userId = mInputUserIdEditText.getText().toString().trim();
|
||||
inputData.channelId = mInputRoomIdEditText.getText().toString().trim();
|
||||
} else if (mViewType == ViewType.BARE_STREAM) {
|
||||
inputData.url = mInputUrlEditText.getText().toString().trim();
|
||||
}
|
||||
inputData.videoStreamType = (mVideoStreamTypeRadioGroup.getCheckedRadioButtonId() == mVideoCamaraRadioButton.getId())
|
||||
? AlivcLivePlayVideoStreamType.STREAM_CAMERA
|
||||
: AlivcLivePlayVideoStreamType.STREAM_SCREEN;
|
||||
inputData.audioStreamType = (mAudioStreamTypeRadioGroup.getCheckedRadioButtonId() == mAudioMicRadioButton.getId())
|
||||
? AlivcLivePlayAudioStreamType.STREAM_MIC
|
||||
: AlivcLivePlayAudioStreamType.STREAM_DUAL;
|
||||
mInteractLiveTipsViewListener.onInputConfirm(inputData);
|
||||
});
|
||||
|
||||
mClearUserIdImageView.setOnClickListener(view -> mInputUserIdEditText.setText(""));
|
||||
mClearRoomIdImageView.setOnClickListener(view -> mInputRoomIdEditText.setText(""));
|
||||
mScanQrImageView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mInteractLiveTipsViewListener != null) {
|
||||
mInteractLiveTipsViewListener.onQrClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setViewType(ViewType viewType) {
|
||||
mViewType = viewType;
|
||||
|
||||
if (viewType == ViewType.INTERACTIVE) {
|
||||
mInputUserIdEditText.setVisibility(View.VISIBLE);
|
||||
mClearUserIdImageView.setVisibility(View.VISIBLE);
|
||||
mInputRoomIdEditText.setVisibility(View.GONE);
|
||||
mClearRoomIdImageView.setVisibility(View.GONE);
|
||||
mInputUrlEditText.setVisibility(View.GONE);
|
||||
mScanQrImageView.setVisibility(View.GONE);
|
||||
mTipsTextView.setVisibility(View.VISIBLE);
|
||||
mAudioRadioGroupLayout.setVisibility(View.VISIBLE);
|
||||
mVideoRadioGroupLayout.setVisibility(View.VISIBLE);
|
||||
} else if (viewType == ViewType.PK) {
|
||||
mInputUserIdEditText.setVisibility(View.VISIBLE);
|
||||
mClearUserIdImageView.setVisibility(View.VISIBLE);
|
||||
mInputRoomIdEditText.setVisibility(View.VISIBLE);
|
||||
mClearRoomIdImageView.setVisibility(View.VISIBLE);
|
||||
mInputUrlEditText.setVisibility(View.GONE);
|
||||
mScanQrImageView.setVisibility(View.GONE);
|
||||
mTipsTextView.setVisibility(View.VISIBLE);
|
||||
mAudioRadioGroupLayout.setVisibility(View.VISIBLE);
|
||||
mVideoRadioGroupLayout.setVisibility(View.VISIBLE);
|
||||
} else if (viewType == ViewType.BARE_STREAM) {
|
||||
mInputUserIdEditText.setVisibility(View.GONE);
|
||||
mInputRoomIdEditText.setVisibility(View.GONE);
|
||||
mClearUserIdImageView.setVisibility(View.GONE);
|
||||
mClearRoomIdImageView.setVisibility(View.GONE);
|
||||
mInputUrlEditText.setVisibility(View.VISIBLE);
|
||||
mScanQrImageView.setVisibility(View.VISIBLE);
|
||||
mTipsTextView.setVisibility(View.VISIBLE);
|
||||
mAudioRadioGroupLayout.setVisibility(View.GONE);
|
||||
mVideoRadioGroupLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDefaultRoomId(String roomId) {
|
||||
if (!TextUtils.isEmpty(roomId)) {
|
||||
mInputRoomIdEditText.setText(roomId);
|
||||
}
|
||||
}
|
||||
|
||||
public void showInputView(String content, boolean showInputView) {
|
||||
this.mShowInputView = showInputView;
|
||||
if (!mShowInputView) {
|
||||
mInputUserIdEditText.setVisibility(View.GONE);
|
||||
mInputRoomIdEditText.setVisibility(View.GONE);
|
||||
mInputUrlEditText.setVisibility(View.GONE);
|
||||
mClearUserIdImageView.setVisibility(View.GONE);
|
||||
mClearRoomIdImageView.setVisibility(View.GONE);
|
||||
mTipsTextView.setVisibility(View.VISIBLE);
|
||||
mTipsTextView.setText(content);
|
||||
mAudioRadioGroupLayout.setVisibility(View.GONE);
|
||||
mVideoRadioGroupLayout.setVisibility(View.GONE);
|
||||
} else {
|
||||
setViewType(mViewType);
|
||||
}
|
||||
}
|
||||
|
||||
public void setQrResult(String content) {
|
||||
mInputUrlEditText.setText(content);
|
||||
}
|
||||
|
||||
public void setOnInteractLiveTipsViewListener(InteractLiveTipsViewListener listener) {
|
||||
this.mInteractLiveTipsViewListener = listener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.alivc.live.interactive_common.R;
|
||||
|
||||
/**
|
||||
* 连麦 View
|
||||
*/
|
||||
public class InteractiveConnectView extends LinearLayout {
|
||||
|
||||
private FrameLayout mConnectFrameLayout;
|
||||
private TextView mConnectTextView;
|
||||
private OnConnectClickListener mOnConnectClickListener;
|
||||
|
||||
public InteractiveConnectView(@NonNull Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public InteractiveConnectView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public InteractiveConnectView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
setOrientation(LinearLayout.VERTICAL);
|
||||
View inflate = LayoutInflater.from(context).inflate(R.layout.layout_interactive_connect_view, this, true);
|
||||
mConnectFrameLayout = inflate.findViewById(R.id.fl_un_connect);
|
||||
mConnectTextView = inflate.findViewById(R.id.tv_connect);
|
||||
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mConnectTextView.setOnClickListener(view -> {
|
||||
if (mOnConnectClickListener != null) {
|
||||
mOnConnectClickListener.onConnectClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void isShow(boolean isShowSurfaceView) {
|
||||
mConnectFrameLayout.setVisibility(isShowSurfaceView ? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
|
||||
public void setDefaultText(String text) {
|
||||
mConnectTextView.setText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始连接
|
||||
*/
|
||||
public void connected() {
|
||||
connected(getResources().getString(R.string.interact_stop_connect));
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开连接
|
||||
*/
|
||||
public void unConnected() {
|
||||
unConnected(getResources().getString(R.string.interact_start_connect));
|
||||
}
|
||||
|
||||
public void connected(String text) {
|
||||
mConnectTextView.setText(text);
|
||||
mConnectTextView.setBackground(getResources().getDrawable(R.drawable.shape_interact_live_un_connect_btn_bg));
|
||||
}
|
||||
|
||||
public void unConnected(String text) {
|
||||
mConnectTextView.setText(text);
|
||||
mConnectTextView.setBackground(getResources().getDrawable(R.drawable.shape_pysh_btn_bg));
|
||||
}
|
||||
|
||||
public FrameLayout getConnectFrameLayout() {
|
||||
return mConnectFrameLayout;
|
||||
}
|
||||
|
||||
public TextView getConnectTextView() {
|
||||
return mConnectTextView;
|
||||
}
|
||||
|
||||
|
||||
public void setConnectClickListener(OnConnectClickListener listener) {
|
||||
this.mOnConnectClickListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* 连麦按钮点击监听
|
||||
*/
|
||||
public interface OnConnectClickListener {
|
||||
void onConnectClick();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.alivc.live.interactive_common.R;
|
||||
|
||||
/**
|
||||
* @author keria
|
||||
* @date 2024/5/28
|
||||
* @brief 直播连麦窗格控制操作栏
|
||||
*/
|
||||
public class InteractivePaneControlView extends LinearLayout {
|
||||
|
||||
private ImageView mInteractMuteImageView;
|
||||
private ImageView mInteractSetEmptyView;
|
||||
private ImageView mInteractResizeView;
|
||||
|
||||
private OnClickEventListener mOnClickEventListener;
|
||||
|
||||
private boolean mMuteAudio = false;
|
||||
private boolean mEmptyView = false;
|
||||
private boolean mResize = false;
|
||||
|
||||
public InteractivePaneControlView(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public InteractivePaneControlView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public InteractivePaneControlView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.layout_interactive_pane_control, this, true);
|
||||
|
||||
mInteractMuteImageView = findViewById(R.id.iv_mute_audio);
|
||||
mInteractSetEmptyView = findViewById(R.id.iv_show_view);
|
||||
mInteractResizeView = findViewById(R.id.iv_view_resize);
|
||||
|
||||
setupListeners();
|
||||
}
|
||||
|
||||
private void setupListeners() {
|
||||
mInteractMuteImageView.setOnClickListener(v -> toggleState(
|
||||
() -> mMuteAudio = !mMuteAudio,
|
||||
() -> mInteractMuteImageView.setImageResource(mMuteAudio ? R.drawable.ic_interact_mute : R.drawable.ic_interact_unmute),
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickMuteAudio(mMuteAudio) : null
|
||||
));
|
||||
|
||||
mInteractSetEmptyView.setOnClickListener(v -> toggleState(
|
||||
() -> mEmptyView = !mEmptyView,
|
||||
() -> mInteractSetEmptyView.setImageResource(mEmptyView ? R.drawable.ic_view_container_hide : R.drawable.ic_view_container_show),
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickEmptyView(mEmptyView) : null
|
||||
));
|
||||
|
||||
mInteractResizeView.setOnClickListener(v -> toggleState(
|
||||
() -> mResize = !mResize,
|
||||
() -> mInteractResizeView.setImageResource(mResize ? R.drawable.ic_full_screen : R.drawable.ic_half_screen),
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickResize(mResize) : null
|
||||
));
|
||||
}
|
||||
|
||||
private void toggleState(@Nullable Runnable viewState, @Nullable Runnable viewStateToggler, @Nullable Runnable eventCallback) {
|
||||
// 执行状态转换
|
||||
if (viewState != null) {
|
||||
viewState.run();
|
||||
}
|
||||
|
||||
// 更新视图状态
|
||||
if (viewStateToggler != null) {
|
||||
viewStateToggler.run();
|
||||
}
|
||||
|
||||
// 执行事件回调
|
||||
if (eventCallback != null) {
|
||||
eventCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void enableMute(boolean mute) {
|
||||
if (mInteractMuteImageView != null) {
|
||||
mInteractMuteImageView.setVisibility(mute ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnClickEventListener(OnClickEventListener listener) {
|
||||
this.mOnClickEventListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mOnClickEventListener = null;
|
||||
}
|
||||
|
||||
public interface OnClickEventListener {
|
||||
void onClickMuteAudio(boolean mute);
|
||||
|
||||
void onClickEmptyView(boolean empty);
|
||||
|
||||
void onClickResize(boolean resize);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.alivc.live.interactive_common.R;
|
||||
|
||||
public class InteractiveQrEditView extends ConstraintLayout {
|
||||
|
||||
private TextView titleView;
|
||||
private EditText etContentView;
|
||||
private ImageView qrImageView;
|
||||
private OnQrClickListener mQrClickListener;
|
||||
|
||||
public InteractiveQrEditView(@NonNull Context context) {
|
||||
super(context);
|
||||
init(context, null);
|
||||
}
|
||||
|
||||
public InteractiveQrEditView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public InteractiveQrEditView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
View inflateView = LayoutInflater.from(context).inflate(R.layout.layout_interactive_qr_input_view, this, true);
|
||||
titleView = inflateView.findViewById(R.id.tv_interactive_pull_url);
|
||||
etContentView = inflateView.findViewById(R.id.et_interactive_pull_url);
|
||||
qrImageView = inflateView.findViewById(R.id.iv_qr_pull_url);
|
||||
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.InteractiveQrEditView);
|
||||
String title = typedArray.getString(R.styleable.InteractiveQrEditView_title);
|
||||
typedArray.recycle();
|
||||
titleView.setText(title);
|
||||
}
|
||||
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
qrImageView.setOnClickListener(view -> {
|
||||
if (mQrClickListener != null) {
|
||||
mQrClickListener.onQrClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
titleView.setText(title);
|
||||
}
|
||||
|
||||
public void setEditText(String text) {
|
||||
etContentView.setText(text);
|
||||
}
|
||||
|
||||
public String getEditText() {
|
||||
return etContentView.getText().toString();
|
||||
}
|
||||
|
||||
public void setOnQrClickListener(OnQrClickListener listener) {
|
||||
this.mQrClickListener = listener;
|
||||
}
|
||||
|
||||
public interface OnQrClickListener {
|
||||
void onQrClick();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.alivc.live.interactive_common.R;
|
||||
|
||||
/**
|
||||
* @Author keria
|
||||
* @Date 2024/5/28
|
||||
* @Brief 直播连麦房间控制操作栏
|
||||
*/
|
||||
public class InteractiveRoomControlView extends LinearLayout {
|
||||
private ImageView mSwitchCameraIv;
|
||||
private ImageView mUseSpeakerPhoneIv;
|
||||
private ImageView mMuteAudioIv;
|
||||
private ImageView mMuteVideoIv;
|
||||
private ImageView mEnableAudioCaptureIv;
|
||||
private ImageView mEnableVideoCaptureIv;
|
||||
|
||||
private boolean mUseSpeakerPhone = false;
|
||||
private boolean mMuteAudio = false;
|
||||
private boolean mMuteVideo = false;
|
||||
private boolean mEnableAudioCapture = true;
|
||||
private boolean mEnableVideoCapture = true;
|
||||
|
||||
private OnClickEventListener mOnClickEventListener;
|
||||
|
||||
public InteractiveRoomControlView(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public InteractiveRoomControlView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public InteractiveRoomControlView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.layout_interactive_room_control, this, true);
|
||||
|
||||
mSwitchCameraIv = findViewById(R.id.iv_camera);
|
||||
mUseSpeakerPhoneIv = findViewById(R.id.iv_speaker_phone);
|
||||
mMuteAudioIv = findViewById(R.id.iv_mute_audio);
|
||||
mMuteVideoIv = findViewById(R.id.iv_mute_video);
|
||||
mEnableAudioCaptureIv = findViewById(R.id.iv_enable_audio);
|
||||
mEnableVideoCaptureIv = findViewById(R.id.iv_enable_video);
|
||||
|
||||
setupListeners();
|
||||
}
|
||||
|
||||
private void setupListeners() {
|
||||
mSwitchCameraIv.setOnClickListener(v -> toggleState(
|
||||
null,
|
||||
null,
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickSwitchCamera() : null
|
||||
));
|
||||
|
||||
mUseSpeakerPhoneIv.setOnClickListener(v -> toggleState(
|
||||
() -> mUseSpeakerPhone = !mUseSpeakerPhone,
|
||||
() -> mUseSpeakerPhoneIv.setImageResource(mUseSpeakerPhone ? R.drawable.ic_speaker_phone_on : R.drawable.ic_speaker_phone_off),
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickSpeakerPhone(mUseSpeakerPhone) : null
|
||||
));
|
||||
|
||||
mMuteAudioIv.setOnClickListener(v -> toggleState(
|
||||
() -> mMuteAudio = !mMuteAudio,
|
||||
() -> mMuteAudioIv.setImageResource(mMuteAudio ? R.drawable.ic_audio_capture_off : R.drawable.ic_audio_capture_on),
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickMuteAudio(mMuteAudio) : null
|
||||
));
|
||||
|
||||
mMuteVideoIv.setOnClickListener(v -> toggleState(
|
||||
() -> mMuteVideo = !mMuteVideo,
|
||||
() -> mMuteVideoIv.setImageResource(mMuteVideo ? R.drawable.ic_local_video_off : R.drawable.ic_local_video_on),
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickMuteVideo(mMuteVideo) : null
|
||||
));
|
||||
|
||||
mEnableAudioCaptureIv.setOnClickListener(v -> toggleState(
|
||||
() -> mEnableAudioCapture = !mEnableAudioCapture,
|
||||
() -> mEnableAudioCaptureIv.setImageResource(mEnableAudioCapture ? R.drawable.ic_audio_capture_on : R.drawable.ic_audio_capture_off),
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickEnableAudio(mEnableAudioCapture) : null
|
||||
));
|
||||
|
||||
mEnableVideoCaptureIv.setOnClickListener(v -> toggleState(
|
||||
() -> mEnableVideoCapture = !mEnableVideoCapture,
|
||||
() -> mEnableVideoCaptureIv.setImageResource(mEnableVideoCapture ? R.drawable.ic_local_video_on : R.drawable.ic_local_video_off),
|
||||
mOnClickEventListener != null ? () -> mOnClickEventListener.onClickEnableVideo(mEnableVideoCapture) : null
|
||||
));
|
||||
}
|
||||
|
||||
private void toggleState(@Nullable Runnable viewState, @Nullable Runnable viewStateToggler, @Nullable Runnable eventCallback) {
|
||||
// 执行状态转换
|
||||
if (viewState != null) {
|
||||
viewState.run();
|
||||
}
|
||||
|
||||
// 更新视图状态
|
||||
if (viewStateToggler != null) {
|
||||
viewStateToggler.run();
|
||||
}
|
||||
|
||||
// 执行事件回调
|
||||
if (eventCallback != null) {
|
||||
eventCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnClickEventListener(OnClickEventListener listener) {
|
||||
this.mOnClickEventListener = listener;
|
||||
}
|
||||
|
||||
public interface OnClickEventListener {
|
||||
void onClickSwitchCamera();
|
||||
|
||||
void onClickSpeakerPhone(boolean enable);
|
||||
|
||||
void onClickMuteAudio(boolean mute);
|
||||
|
||||
void onClickMuteVideo(boolean mute);
|
||||
|
||||
void onClickEnableAudio(boolean enable);
|
||||
|
||||
void onClickEnableVideo(boolean enable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class MultiAlivcLiveView {
|
||||
|
||||
private FrameLayout mUnConnectFrameLayout;
|
||||
private FrameLayout mSmallFrameLayout;
|
||||
private TextView mConnectTextView;
|
||||
|
||||
public MultiAlivcLiveView(FrameLayout unConnectFrameLayout,FrameLayout smallFrameLayout,TextView connectTextView){
|
||||
this.mUnConnectFrameLayout = unConnectFrameLayout;
|
||||
this.mSmallFrameLayout = smallFrameLayout;
|
||||
this.mConnectTextView = connectTextView;
|
||||
}
|
||||
|
||||
public FrameLayout getUnConnectFrameLayout() {
|
||||
return mUnConnectFrameLayout;
|
||||
}
|
||||
|
||||
public void setUnConnectFrameLayout(FrameLayout mUnConnectFrameLayout) {
|
||||
this.mUnConnectFrameLayout = mUnConnectFrameLayout;
|
||||
}
|
||||
|
||||
public FrameLayout getSmallFrameLayout() {
|
||||
return mSmallFrameLayout;
|
||||
}
|
||||
|
||||
public void setSmallFrameLayout(FrameLayout mSmallFrameLayout) {
|
||||
this.mSmallFrameLayout = mSmallFrameLayout;
|
||||
}
|
||||
|
||||
public TextView getConnectTextView() {
|
||||
return mConnectTextView;
|
||||
}
|
||||
|
||||
public void setConnectTextView(TextView mConnectTextView) {
|
||||
this.mConnectTextView = mConnectTextView;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.alivc.live.interactive_common.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.alivc.live.commonbiz.test.AliLiveStreamURLUtil;
|
||||
import com.alivc.live.interactive_common.R;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 用户连麦窗口显示'房间ID'和'用户ID'
|
||||
*/
|
||||
public class RoomAndUserInfoView extends LinearLayout {
|
||||
private TextView mInfoTv;
|
||||
|
||||
public RoomAndUserInfoView(@NonNull Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public RoomAndUserInfoView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public RoomAndUserInfoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
View inflateView = LayoutInflater.from(context).inflate(R.layout.layout_room_user_info_view, this, true);
|
||||
mInfoTv = inflateView.findViewById(R.id.tv_info);
|
||||
}
|
||||
|
||||
public void setUserInfo(String channelId, String userId) {
|
||||
mInfoTv.setText(String.format("Room:%s\nUser:%s", channelId, userId));
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
HashMap<String, String> params = AliLiveStreamURLUtil.parseUrl(url);
|
||||
mInfoTv.setText(String.format("Room:%s\nUser:%s",
|
||||
AliLiveStreamURLUtil.parseURLStreamName(params),
|
||||
params.get(AliLiveStreamURLUtil.USER_ID)));
|
||||
}
|
||||
|
||||
public void setUserData(InteractiveUserData userData) {
|
||||
mInfoTv.setText(String.format("Room:%s\nUser:%s",
|
||||
userData != null ? userData.channelId : "",
|
||||
userData != null ? userData.userId : ""));
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 502 B |
|
After Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 484 B |
|
After Width: | Height: | Size: 477 B |
|
After Width: | Height: | Size: 568 B |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 257 B |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="16dp" />
|
||||
<solid android:color="#23262F" />
|
||||
</shape>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<stroke android:width="1dp" android:color="#747A8C"/>
|
||||
<corners android:radius="2dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="#23262F" />
|
||||
|
||||
<corners android:radius="12dp" />
|
||||
|
||||
<stroke android:color="@color/colourful_border_weak" android:width="2dp" />
|
||||
|
||||
</shape>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="24dp"/>
|
||||
<solid android:color="@color/shape_red_rectangle"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="#23262F" />
|
||||
|
||||
<corners android:radius="12dp" />
|
||||
|
||||
</shape>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="24dp"/>
|
||||
<solid android:color="@color/colourful_ic_strong"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#4D4DCFE1"/>
|
||||
<stroke android:color="#4DCFE1" android:width="1px"/>
|
||||
<corners android:radius="24dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 按钮的选择器,可以设置按钮在不同状态下的时候,按钮不同的颜色 -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_checked="true" android:drawable="@drawable/thumb_on" />
|
||||
<item android:drawable="@drawable/thumb_off" />
|
||||
</selector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
|
||||
<size android:height="26dp" android:width="26dp"/>
|
||||
<corners android:radius="13dp"/>
|
||||
<solid android:color="#747A8C"/>
|
||||
<stroke android:width="2dp"
|
||||
android:color="#23262F"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<!-- 高度40 -->
|
||||
<size
|
||||
android:width="26dp"
|
||||
android:height="26dp" />
|
||||
<!-- 圆角弧度 20 -->
|
||||
<corners android:radius="13dp" />
|
||||
<solid android:color="#FCFCFD" />
|
||||
<stroke android:width="2dp"
|
||||
android:color="#4DCFE1"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 底层下滑条的样式选择器,可控制Switch在不同状态下,底下下滑条的颜色 -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_checked="true" android:drawable="@drawable/track_on" />
|
||||
<item android:drawable="@drawable/track_off" />
|
||||
|
||||
</selector>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
|
||||
<!-- 高度30 此处设置宽度无效-->
|
||||
<size android:height="26dp"/>
|
||||
<!-- 圆角弧度 15 -->
|
||||
<corners android:radius="13dp"/>
|
||||
<!-- 变化率 定义从左到右的颜色不变 -->
|
||||
<solid android:color="#23262F"/>
|
||||
|
||||
|
||||
</shape>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
|
||||
<size android:height="26dp"
|
||||
android:width="50dp"/>
|
||||
<corners android:radius="13dp" />
|
||||
<solid android:height="26dp" android:color="#4DCFE1" />
|
||||
</shape>
|
||||
@@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#1C1D22">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_back"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:src="@drawable/ic_live_action_bar_back"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginTop="44dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_info"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_id_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:text="@string/app_info_app_id"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_title" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_app_id"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
|
||||
android:hint="@string/interact_live_user_id_hint"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#E6E7EC"
|
||||
android:theme="@style/AUIEditText"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_app_id_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_app_id_title" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_app_id_clear"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:src="@drawable/ic_scan_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_app_id"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_app_id"
|
||||
app:layout_constraintTop_toTopOf="@id/et_app_id" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_key"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="30dp"
|
||||
android:text="@string/app_info_app_key"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_app_id_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_app_id" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_app_key"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
|
||||
android:hint="@string/interact_live_user_id_hint"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#E6E7EC"
|
||||
android:theme="@style/AUIEditText"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_app_id"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_app_key"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_app_key" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_app_key_clear"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:src="@drawable/ic_scan_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_app_key"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_app_key"
|
||||
app:layout_constraintTop_toTopOf="@id/et_app_key" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_play_domain_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="30dp"
|
||||
android:text="@string/app_info_play_domain"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_app_id_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_app_key" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_play_domain"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
|
||||
android:hint="@string/interact_live_user_id_hint"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#E6E7EC"
|
||||
android:theme="@style/AUIEditText"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_app_id"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_app_id_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_play_domain_title" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_play_domain_clear"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:src="@drawable/ic_scan_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_play_domain"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_play_domain"
|
||||
app:layout_constraintTop_toTopOf="@id/et_play_domain" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_confirm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="44dp"
|
||||
android:background="@drawable/shape_rect_blue"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="2"
|
||||
android:clickable="false"
|
||||
android:text="@string/interact_live_next"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,235 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#1C1D22">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_back"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:src="@drawable/ic_live_action_bar_back"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginTop="44dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_setting"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginTop="44dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_setting"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="12sp"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="40dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_confirm"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_title">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_user_id_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:text="@string/interact_live_user_id"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_user_id"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
android:hint="@string/interact_live_user_id_hint"
|
||||
android:maxLength="20"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#E6E7EC"
|
||||
android:theme="@style/AUIEditText"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_user_id_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_user_id_title" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_user_id_clear"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_close"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_user_id"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_user_id"
|
||||
app:layout_constraintTop_toTopOf="@id/et_user_id" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_room_number"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="30dp"
|
||||
android:text="@string/interact_live_room_id"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_user_id_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_user_id" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_room_id"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
android:hint="@string/interact_live_user_id_hint"
|
||||
android:maxLength="20"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#E6E7EC"
|
||||
android:theme="@style/AUIEditText"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_user_id"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_user_id_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_room_number" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_room_id_clear"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_close"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_room_id"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_room_id"
|
||||
app:layout_constraintTop_toTopOf="@id/et_room_id" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/fragment_app_info"
|
||||
android:name="com.alivc.live.interactive_common.InteractLiveAppInfoFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_room_id" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/role_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/fragment_app_info"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractLiveRadioButton
|
||||
android:id="@+id/radio_button_anchor"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
app:ilrb_text="@string/interact_live_anchor" />
|
||||
|
||||
<View
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="1dp" />
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractLiveRadioButton
|
||||
android:id="@+id/radio_button_audience"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
app:ilrb_text="@string/interact_live_audience" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="30dp"
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/role_container">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_url_entrance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#00000000"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:lineSpacingExtra="3dp"
|
||||
android:padding="10dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/tips_use_url_for_interactive"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_interactive_url"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:includeFontPadding="false"
|
||||
android:lineSpacingExtra="3dp"
|
||||
android:padding="5dp"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="12dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_confirm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="44dp"
|
||||
android:background="@drawable/shape_rect_blue"
|
||||
android:clickable="false"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="2"
|
||||
android:text="@string/interact_live_confirm"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,299 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#1C1D22">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_back"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:src="@drawable/ic_live_action_bar_back"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginTop="44dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_setting"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="#3A3D48"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_title" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/view_divider"
|
||||
app:layout_constraintBottom_toTopOf="@id/btn_commit">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="45dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/tab_args_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tab_args_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="17dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:text="@string/push_args"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="@dimen/font_size_28px" />
|
||||
|
||||
<View
|
||||
android:id="@+id/tab_args_view"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="3dp"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:background="#4DCFE1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/tab_action_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tab_action_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="17dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:text="@string/stream_pusher_tip"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="@dimen/font_size_28px" />
|
||||
|
||||
<View
|
||||
android:id="@+id/tab_action_view"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="3dp"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:background="#4DCFE1"
|
||||
android:visibility="invisible" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/multi_interactive_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/view_divider">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/pull_multi_interact_name_tv"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/multi_interaction_control"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="16dp"
|
||||
android:checked="false"
|
||||
android:textOff=""
|
||||
android:textOn=""
|
||||
android:thumb="@drawable/thumb"
|
||||
android:track="@drawable/track" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="#3A3D48" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/h5_compatible_name_tv"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/h5_compatible_control"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="16dp"
|
||||
android:checked="false"
|
||||
android:textOff=""
|
||||
android:textOn=""
|
||||
android:thumb="@drawable/thumb"
|
||||
android:track="@drawable/track" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="#3A3D48" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/data_channel_name_tv"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/data_channel_control"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="16dp"
|
||||
android:checked="false"
|
||||
android:textOff=""
|
||||
android:textOn=""
|
||||
android:thumb="@drawable/thumb"
|
||||
android:track="@drawable/track" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="#3A3D48" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/earback_open_without_headset"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/earback_open_without_headset_control"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="16dp"
|
||||
android:checked="false"
|
||||
android:textOff=""
|
||||
android:textOn=""
|
||||
android:thumb="@drawable/thumb"
|
||||
android:track="@drawable/track" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="#3A3D48" />
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.alivc.live.commonui.configview.LivePushSettingView
|
||||
android:id="@+id/setting_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_commit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:background="@drawable/shape_pysh_btn_bg"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:text="@string/interact_live_confirm"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="normal"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#1C1D22">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="39dp"
|
||||
android:text="@string/app_info"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_arrow"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_chevron_down"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_app_info"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_app_info" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cl_app_info"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="@id/iv_arrow"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_app_info"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_app_info"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_id_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_info_app_id"
|
||||
android:textColor="#B2B7C4"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#B2B7C4"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_app_id_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_key_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/app_info_app_key"
|
||||
android:textColor="#B2B7C4"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_app_id_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_key"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#B2B7C4"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_app_key_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_play_domain_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/app_info_play_domain"
|
||||
android:textColor="#B2B7C4"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_app_key_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_play_domain"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#B2B7C4"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_play_domain_title" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_edit"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="36dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:src="@drawable/ic_edit"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_play_domain" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="#3A3D48"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cl_app_info" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="312dp"
|
||||
android:layout_height="128dp"
|
||||
android:background="@drawable/shape_interact_live_dialog_bg">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_tips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="70dp"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live_lost_connect"
|
||||
app:layout_constraintBottom_toBottomOf="@id/view_horizontal_line"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view_horizontal_line"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#3A3D48"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_tips"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_confirm"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live_confirm"
|
||||
android:textColor="#4DCFE1"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/view_horizontal_line" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:background="@drawable/shape_interact_live_unselected">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:src="@drawable/ic_decorate"
|
||||
app:layout_constraintEnd_toEndOf="@id/tv_title"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_title" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:src="@drawable/ic_anchor"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="312dp"
|
||||
android:layout_height="128dp"
|
||||
android:background="@drawable/shape_interact_live_dialog_bg">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_tips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/view_horizontal_line"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_input"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:background="@drawable/shape_interact_live_edit_bg"
|
||||
android:gravity="start|center_vertical"
|
||||
android:hint="@string/interact_live_connect_tips"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#747A8C"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/view_horizontal_line"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_clear"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:src="@drawable/ic_close"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_input"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_input"
|
||||
app:layout_constraintTop_toTopOf="@id/et_input"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view_horizontal_line"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#3A3D48"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_cancel"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_cancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live_cancel"
|
||||
android:textColor="#B2B7C4"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/view_vertical_line"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view_vertical_line"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="#3A3D48"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_confirm"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_cancel"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_cancel" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_confirm"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live_confirm"
|
||||
android:textColor="#4DCFE1"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/view_vertical_line" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,258 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="312dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/shape_interact_live_dialog_bg">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_tips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/view_horizontal_line"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_input_user_id"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:background="@drawable/shape_interact_live_edit_bg"
|
||||
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
android:gravity="start|center_vertical"
|
||||
android:hint="@string/interact_live_connect_author_tips"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#747A8C"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_clear_user_id"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:src="@drawable/ic_close"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_input_user_id"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_input_user_id"
|
||||
app:layout_constraintTop_toTopOf="@id/et_input_user_id" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_input_room_id"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:background="@drawable/shape_interact_live_edit_bg"
|
||||
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
android:gravity="start|center_vertical"
|
||||
android:hint="@string/interact_live_connect_room_tips"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#747A8C"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_input_user_id"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_clear_room_id"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:src="@drawable/ic_close"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_input_room_id"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_input_room_id"
|
||||
app:layout_constraintTop_toTopOf="@id/et_input_room_id" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_input_url"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:background="@drawable/shape_interact_live_edit_bg"
|
||||
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
android:gravity="start|center_vertical"
|
||||
android:hint="@string/interact_live_url_connect_tips"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#747A8C"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_input_room_id"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_scan_qr"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:src="@drawable/ic_scan_icon"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_input_url"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_input_url"
|
||||
app:layout_constraintTop_toTopOf="@id/et_input_url" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/video_radio_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="5dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/et_input_url">
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/interact_live_video_stream_type"
|
||||
android:textColor="#FCFCFD" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_video_stream_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_camera"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/interact_live_video_stream_type_camera"
|
||||
android:textColor="#FCFCFD" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_screen"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:text="@string/interact_live_video_stream_type_screen"
|
||||
android:textColor="#FCFCFD" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/audio_radio_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="5dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/view_horizontal_line"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/video_radio_group">
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/interact_live_audio_stream_type"
|
||||
android:textColor="#FCFCFD" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_audio_stream_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_mic"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/interact_live_audio_stream_type_mic"
|
||||
android:textColor="#FCFCFD" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_dual"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/interact_live_audio_stream_type_dual"
|
||||
android:textColor="#FCFCFD" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/view_horizontal_line"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#3A3D48"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_cancel"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_cancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live_cancel"
|
||||
android:textColor="#B2B7C4"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/view_vertical_line"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view_vertical_line"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="#3A3D48"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_confirm"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_cancel"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_cancel" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_confirm"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live_confirm"
|
||||
android:textColor="#4DCFE1"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/view_vertical_line" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fl_un_connect"
|
||||
android:layout_width="95dp"
|
||||
android:layout_height="160dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:background="#23262F">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_interact_live_un_connect_bg" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_connect"
|
||||
android:layout_width="94dp"
|
||||
android:layout_height="30dp"
|
||||
android:background="@drawable/shape_pysh_btn_bg"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="1"
|
||||
android:text="@string/interact_start_connect"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</merge>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_mute_audio"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:padding="3dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_interact_unmute" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_show_view"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:padding="3dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_view_container_show" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_view_resize"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:padding="3dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_half_screen" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_interactive_pull_url"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live_pull_url"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_interactive_pull_url"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="22dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#E6E7EC"
|
||||
android:theme="@style/AUIEditText"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_interactive_pull_url"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_interactive_pull_url" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_qr_pull_url"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_scan_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_interactive_pull_url"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_interactive_pull_url"
|
||||
app:layout_constraintTop_toTopOf="@id/et_interactive_pull_url" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_camera"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:padding="3dp"
|
||||
android:src="@drawable/ic_camera" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_speaker_phone"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="3dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_speaker_phone_off" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_mute_audio"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="3dp"
|
||||
android:src="@drawable/ic_audio_capture_on" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_mute_video"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="3dp"
|
||||
android:src="@drawable/ic_local_video_on" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_enable_audio"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="3dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_audio_capture_on" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_enable_video"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="3dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_local_video_on" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="15dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_interact_name_tv">Connect Interact</string>
|
||||
<string name="pull_interact_name_url">Connect Input URL</string>
|
||||
<string name="pull_multi_interact_name_tv">Multi Connect Interact/PK</string>
|
||||
<string name="h5_compatible_name_tv">H5 Compatible</string>
|
||||
<string name="earback_open_without_headset">Earback Without Headset</string>
|
||||
<string name="data_channel_name_tv">Data Channel</string>
|
||||
<string name="external_audio_stream_tv">External Audio Stream</string>
|
||||
<string name="external_video_stream_tv">External Video Stream</string>
|
||||
<string name="dual_audio_stream">Push Dual Audio</string>
|
||||
<string name="screen_share_stream">Push Screen Share</string>
|
||||
<string name="change_resolution_and_fps">Change Resolution FPS</string>
|
||||
<string name="force_ear_monitor">Force Ear Monitor</string>
|
||||
<string name="push_interactive_setting_audio_only">Audio Only</string>
|
||||
<string name="push_interactive_setting_gop">GOP</string>
|
||||
<string name="push_interactive_setting_hardware_decode">Enable Hardware Decode</string>
|
||||
<string name="push_interactive_h265">H265</string>
|
||||
<string name="interact_live">Interact Live</string>
|
||||
<string name="interact_live_url_title">Interact Live URL</string>
|
||||
<string name="interact_live_push_url">Interact Live PUSH URL</string>
|
||||
<string name="interact_live_pull_url">Interact Live PULL URL</string>
|
||||
<string name="interact_start_push">Start Push</string>
|
||||
<string name="interact_stop_push">Stop Push</string>
|
||||
<string name="pk_live">PK Interaction</string>
|
||||
<string name="interact_setting">Interact Setting</string>
|
||||
<string name="interact_live_cancel">Cancel</string>
|
||||
<string name="interact_live_confirm">Confirm</string>
|
||||
<string name="interact_live_audio_stream_type">Audio Stream</string>
|
||||
<string name="interact_live_audio_stream_type_mic">Mic</string>
|
||||
<string name="interact_live_audio_stream_type_dual">Dual</string>
|
||||
<string name="interact_live_video_stream_type">Video Stream</string>
|
||||
<string name="interact_live_video_stream_type_camera">Camera</string>
|
||||
<string name="interact_live_video_stream_type_screen">Screen</string>
|
||||
<string name="interact_live_next">Next</string>
|
||||
<string name="interact_live_user_id">User ID</string>
|
||||
<string name="interact_live_room_id">Room ID</string>
|
||||
<string name="app_info">APP Info</string>
|
||||
<string name="app_info_app_id">App ID</string>
|
||||
<string name="app_info_app_key">App Key</string>
|
||||
<string name="app_info_play_domain">PlayDomain</string>
|
||||
<string name="interact_live_user_id_hint">Please enter letters and numbers</string>
|
||||
<string name="interact_live_anchor">anchor</string>
|
||||
<string name="interact_live_audience">audience</string>
|
||||
<string name="interact_input_limit">0/5</string>
|
||||
<string name="interact_start_connect">Connect</string>
|
||||
<string name="pk_start_connect">PK</string>
|
||||
<string name="interact_stop_connect">UnConnect</string>
|
||||
<string name="pk_stop_connect">EndPK</string>
|
||||
<string name="interact_live_connecting">Connecting</string>
|
||||
<string name="pk_live_connecting">Connecting</string>
|
||||
<string name="interact_live_connect_tips">Enter the User ID</string>
|
||||
<string name="interact_live_url_connect_tips">Enter the User URL</string>
|
||||
<string name="interact_live_connect_author_tips">Enter the author ID</string>
|
||||
<string name="interact_live_connect_room_tips">Enter the room ID</string>
|
||||
<string name="interact_live_connect_input_error_tips">Input content</string>
|
||||
<string name="interact_live_connect_finish_tips">End connect?</string>
|
||||
<string name="pk_live_connect_finish_tips">End PK?</string>
|
||||
<string name="interact_live_leave_room_tips">Leave room?</string>
|
||||
<string name="interact_live_viewer_left">Viewer Left</string>
|
||||
|
||||
<string name="interact_live_lost_connect">Disconnect the link, please re-enter the live room</string>
|
||||
<string name="extern_stream_main">Main Extern Stream</string>
|
||||
<string name="beauty_switch">Beauty</string>
|
||||
<string name="waiting_download_video_resources">waiting for download external video resources</string>
|
||||
<string name="interact_live_setting_resolution">Resolution</string>
|
||||
<string name="target_bitrate">Target bitrate</string>
|
||||
<string name="target_rate_value">1200</string>
|
||||
<string name="captrue_fps">Captrue fps</string>
|
||||
<string name="init_fps">20</string>
|
||||
<string name="min_fps">Min fps</string>
|
||||
|
||||
<string name="live_push_switch_to_facing_back_camera">Switch to facing back camera,before scanning code</string>
|
||||
<string name="tips_use_url_for_interactive">Use URL for interactive live</string>
|
||||
<string name="tips_interactive_url_use_different_sdkappid">The sdkAppId used in the URL is different from the one in the App Info. Please note that this may cause pulling stream failure!</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_interact_name_tv">连麦互动</string>
|
||||
<string name="pull_interact_name_url">推拉裸流</string>
|
||||
<string name="pull_multi_interact_name_tv">多人连麦/PK</string>
|
||||
<string name="h5_compatible_name_tv">H5兼容模式</string>
|
||||
<string name="earback_open_without_headset">强制耳返</string>
|
||||
<string name="data_channel_name_tv">DataChannel消息通道</string>
|
||||
<string name="external_audio_stream_tv">自定义音频</string>
|
||||
<string name="external_video_stream_tv">自定义视频</string>
|
||||
<string name="dual_audio_stream">推音频辅流</string>
|
||||
<string name="screen_share_stream">推屏幕共享流</string>
|
||||
<string name="change_resolution_and_fps">切换分辨率与FPS</string>
|
||||
<string name="force_ear_monitor">强制耳返</string>
|
||||
<string name="push_interactive_setting_audio_only">纯音频</string>
|
||||
<string name="push_interactive_setting_gop">GOP</string>
|
||||
<string name="push_interactive_setting_hardware_decode">开启硬解</string>
|
||||
<string name="push_interactive_h265">H265</string>
|
||||
<string name="interact_live">连麦互动</string>
|
||||
<string name="interact_live_url_title">推拉裸流配置</string>
|
||||
<string name="interact_live_push_url">请输入推流地址</string>
|
||||
<string name="interact_live_pull_url">请输入拉流地址</string>
|
||||
<string name="interact_start_push">开始推流</string>
|
||||
<string name="interact_stop_push">停止推流</string>
|
||||
<string name="pk_live">PK互动</string>
|
||||
<string name="interact_setting">参数设置</string>
|
||||
<string name="interact_live_cancel">取消</string>
|
||||
<string name="interact_live_confirm">确认</string>
|
||||
<string name="interact_live_audio_stream_type">音频流类型</string>
|
||||
<string name="interact_live_audio_stream_type_mic">麦克风流</string>
|
||||
<string name="interact_live_audio_stream_type_dual">音频辅流</string>
|
||||
<string name="interact_live_video_stream_type">视频流类型</string>
|
||||
<string name="interact_live_video_stream_type_camera">摄像头流</string>
|
||||
<string name="interact_live_video_stream_type_screen">屏幕共享</string>
|
||||
<string name="interact_live_next">下一步</string>
|
||||
<string name="interact_live_user_id">用户 ID</string>
|
||||
<string name="interact_live_room_id">房间号</string>
|
||||
<string name="app_info">应用信息</string>
|
||||
<string name="app_info_app_id">App ID</string>
|
||||
<string name="app_info_app_key">App Key</string>
|
||||
<string name="app_info_play_domain">播流域名</string>
|
||||
<string name="interact_live_user_id_hint">请输入字母、数字</string>
|
||||
<string name="interact_live_anchor">主播</string>
|
||||
<string name="interact_live_audience">观众</string>
|
||||
<string name="interact_input_limit">0/5</string>
|
||||
<string name="interact_start_connect">开始连麦</string>
|
||||
<string name="pk_start_connect">开始PK</string>
|
||||
<string name="interact_stop_connect">结束连麦</string>
|
||||
<string name="pk_stop_connect">结束PK</string>
|
||||
<string name="interact_live_connect_tips">请输入观众的用户ID</string>
|
||||
<string name="interact_live_url_connect_tips">请输入连麦观众的 URL</string>
|
||||
<string name="interact_live_connect_author_tips">请输入主播的用户ID</string>
|
||||
<string name="interact_live_connect_room_tips">请输入主播的房间号</string>
|
||||
<string name="interact_live_connect_input_error_tips">请输入内容</string>
|
||||
<string name="interact_live_connecting">正在连麦</string>
|
||||
<string name="pk_live_connecting">正在PK</string>
|
||||
<string name="interact_live_connect_finish_tips">确认要结束本次连麦吗?</string>
|
||||
<string name="pk_live_connect_finish_tips">确认要结束本次 PK 吗?</string>
|
||||
<string name="interact_live_leave_room_tips">确认要退出房间吗?</string>
|
||||
<string name="interact_live_viewer_left">观众已离开,结束连麦</string>
|
||||
<string name="interact_live_lost_connect">断开链接,请重新进入直播间</string>
|
||||
<string name="extern_stream_main">外部音视频</string>
|
||||
<string name="beauty_switch">美颜</string>
|
||||
<string name="waiting_download_video_resources">正在下载外部音视频资源中,请等待</string>
|
||||
<string name="interact_live_setting_resolution">分辨率</string>
|
||||
<string name="target_bitrate">视频目标码率</string>
|
||||
<string name="target_rate_value">1200</string>
|
||||
<string name="captrue_fps">采集帧率</string>
|
||||
<string name="init_fps">20</string>
|
||||
<string name="min_fps">最小帧率</string>
|
||||
|
||||
<string name="live_push_switch_to_facing_back_camera">扫码前请切换到后置摄像头</string>
|
||||
<string name="tips_use_url_for_interactive">使用URL方式进行互动直播</string>
|
||||
<string name="tips_interactive_url_use_different_sdkappid">URL中使用的sdkAppId与应用信息中的不同,请注意这可能会导致拉流失败!</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="InteractLiveRadioButton">
|
||||
<attr name="ilrb_text" format="string" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="InteractiveQrEditView">
|
||||
<attr name="title" format="string" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="wheel_black">#000000</color>
|
||||
<color name="transparent">#50000000</color>
|
||||
<color name="alivc_color_black">#000</color>
|
||||
<color name="shape_red_rectangle">#F53F3F</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_interact_name_tv">Connect Interact</string>
|
||||
<string name="pull_interact_name_url">Connect Input URL</string>
|
||||
<string name="pull_multi_interact_name_tv">Multi Connect Interact/PK</string>
|
||||
<string name="h5_compatible_name_tv">H5 Compatible</string>
|
||||
<string name="earback_open_without_headset">Earback Without Headset</string>
|
||||
<string name="data_channel_name_tv">Data Channel</string>
|
||||
<string name="external_audio_stream_tv">External Audio Stream</string>
|
||||
<string name="external_video_stream_tv">External Video Stream</string>
|
||||
<string name="dual_audio_stream">Push Dual Audio</string>
|
||||
<string name="screen_share_stream">Push Screen Share</string>
|
||||
<string name="change_resolution_and_fps">Change Resolution FPS</string>
|
||||
<string name="force_ear_monitor">Force Ear Monitor</string>
|
||||
<string name="push_interactive_setting_audio_only">Audio Only</string>
|
||||
<string name="push_interactive_setting_gop">GOP</string>
|
||||
<string name="push_interactive_setting_hardware_decode">Enable Hardware Decode</string>
|
||||
<string name="push_interactive_h265">H265</string>
|
||||
<string name="interact_live">Interact Live</string>
|
||||
<string name="interact_live_url_title">Interact Live URL</string>
|
||||
<string name="interact_live_push_url">Interact Live PUSH URL</string>
|
||||
<string name="interact_live_pull_url">Interact Live PULL URL</string>
|
||||
<string name="interact_start_push">Start Push</string>
|
||||
<string name="interact_stop_push">Stop Push</string>
|
||||
<string name="pk_live">PK Interaction</string>
|
||||
<string name="interact_setting">Interact Setting</string>
|
||||
<string name="interact_live_cancel">Cancel</string>
|
||||
<string name="interact_live_confirm">Confirm</string>
|
||||
<string name="interact_live_audio_stream_type">Audio Stream</string>
|
||||
<string name="interact_live_audio_stream_type_mic">Mic</string>
|
||||
<string name="interact_live_audio_stream_type_dual">Dual</string>
|
||||
<string name="interact_live_video_stream_type">Video Stream</string>
|
||||
<string name="interact_live_video_stream_type_camera">Camera</string>
|
||||
<string name="interact_live_video_stream_type_screen">Screen</string>
|
||||
<string name="interact_live_next">Next</string>
|
||||
<string name="interact_live_user_id">User ID</string>
|
||||
<string name="interact_live_room_id">Room ID</string>
|
||||
<string name="app_info">APP Info</string>
|
||||
<string name="app_info_app_id">App ID</string>
|
||||
<string name="app_info_app_key">App Key</string>
|
||||
<string name="app_info_play_domain">PlayDomain</string>
|
||||
<string name="interact_live_user_id_hint">Please enter letters and numbers</string>
|
||||
<string name="interact_live_anchor">anchor</string>
|
||||
<string name="interact_live_audience">audience</string>
|
||||
<string name="interact_input_limit">0/5</string>
|
||||
<string name="interact_start_connect">Connect</string>
|
||||
<string name="pk_start_connect">PK</string>
|
||||
<string name="interact_stop_connect">UnConnect</string>
|
||||
<string name="pk_stop_connect">EndPK</string>
|
||||
<string name="interact_live_connecting">Connecting</string>
|
||||
<string name="pk_live_connecting">Connecting</string>
|
||||
<string name="interact_live_connect_tips">Enter the User ID</string>
|
||||
<string name="interact_live_url_connect_tips">Enter the User URL</string>
|
||||
<string name="interact_live_connect_author_tips">Enter the author ID</string>
|
||||
<string name="interact_live_connect_room_tips">Enter the room ID</string>
|
||||
<string name="interact_live_connect_input_error_tips">Input content</string>
|
||||
<string name="interact_live_connect_finish_tips">End connect?</string>
|
||||
<string name="pk_live_connect_finish_tips">End PK?</string>
|
||||
<string name="interact_live_leave_room_tips">Leave room?</string>
|
||||
<string name="interact_live_viewer_left">Viewer Left</string>
|
||||
|
||||
<string name="interact_live_lost_connect">Disconnect the link, please re-enter the live room</string>
|
||||
<string name="extern_stream_main">Main Extern Stream</string>
|
||||
<string name="beauty_switch">Beauty</string>
|
||||
<string name="waiting_download_video_resources">waiting for download external video resources</string>
|
||||
<string name="interact_live_setting_resolution">Resolution</string>
|
||||
<string name="target_bitrate">Target bitrate</string>
|
||||
<string name="target_rate_value">1200</string>
|
||||
<string name="captrue_fps">Captrue fps</string>
|
||||
<string name="init_fps">20</string>
|
||||
<string name="min_fps">Min fps</string>
|
||||
|
||||
<string name="live_push_switch_to_facing_back_camera">Switch to facing back camera,before scanning code</string>
|
||||
<string name="tips_use_url_for_interactive">Use URL for interactive live</string>
|
||||
<string name="tips_interactive_url_use_different_sdkappid">The sdkAppId used in the URL is different from the one in the App Info. Please note that this may cause pulling stream failure!</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,12 @@
|
||||
<resources>
|
||||
|
||||
<style name="AUIEditText">
|
||||
<item name="colorControlNormal">#3A3D48</item>
|
||||
<item name="colorControlActivated">#3A3D48</item>
|
||||
</style>
|
||||
|
||||
<style name="Push_SeekBar_Style"
|
||||
parent="Widget.AppCompat.SeekBar">
|
||||
<item name="colorAccent">#4DCFE1</item>
|
||||
</style>
|
||||
</resources>
|
||||