集成完直播后提交代码
This commit is contained in:
1
LiveInteractive/live_barestream/.gitignore
vendored
Normal file
1
LiveInteractive/live_barestream/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
44
LiveInteractive/live_barestream/build.gradle
Normal file
44
LiveInteractive/live_barestream/build.gradle
Normal file
@@ -0,0 +1,44 @@
|
||||
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 :'interactiveBareStream' ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
implementation externalSimpleZXing
|
||||
|
||||
api project(':LiveInteractive:live_interactive_common')
|
||||
implementation externalARouter
|
||||
annotationProcessor externalARouterCompiler
|
||||
}
|
||||
0
LiveInteractive/live_barestream/consumer-rules.pro
Normal file
0
LiveInteractive/live_barestream/consumer-rules.pro
Normal file
21
LiveInteractive/live_barestream/proguard-rules.pro
vendored
Normal file
21
LiveInteractive/live_barestream/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
26
LiveInteractive/live_barestream/src/main/AndroidManifest.xml
Normal file
26
LiveInteractive/live_barestream/src/main/AndroidManifest.xml
Normal file
@@ -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.barestream_interactive" >
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name=".InteractiveBareActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
<activity
|
||||
android:name=".InteractiveMultiBareActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
<activity
|
||||
android:name=".InteractiveInputURLActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.alivc.live.barestream_interactive;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.alivc.live.commonbiz.LocalStreamReader;
|
||||
import com.alivc.live.commonbiz.ResourcesConst;
|
||||
import com.alivc.live.interactive_common.InteractLiveBaseManager;
|
||||
import com.alivc.live.interactive_common.InteractiveMode;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
import com.alivc.live.interactive_common.listener.InteractLivePushPullListener;
|
||||
import com.alivc.live.interactive_common.utils.LivePushGlobalConfig;
|
||||
import com.alivc.live.pusher.AlivcResolutionEnum;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
class BareStreamController {
|
||||
|
||||
private final InteractLiveBaseManager mInteractLiveManager;
|
||||
private final Context mContext;
|
||||
private final LocalStreamReader mLocalStreamReader;
|
||||
//主播预览 View
|
||||
private FrameLayout mAnchorRenderView;
|
||||
//观众连麦预览 View
|
||||
private FrameLayout mViewerRenderView;
|
||||
|
||||
// 主播连麦推流信息
|
||||
private InteractiveUserData mPushUserData;
|
||||
// 观众连麦拉流信息
|
||||
private InteractiveUserData mPullUserData;
|
||||
|
||||
public BareStreamController(Context context) {
|
||||
this.mContext = context;
|
||||
AlivcResolutionEnum resolution = LivePushGlobalConfig.mAlivcLivePushConfig.getResolution();
|
||||
int width = AlivcResolutionEnum.getResolutionWidth(resolution, LivePushGlobalConfig.mAlivcLivePushConfig.getLivePushMode());
|
||||
int height = AlivcResolutionEnum.getResolutionHeight(resolution, LivePushGlobalConfig.mAlivcLivePushConfig.getLivePushMode());
|
||||
mLocalStreamReader = new LocalStreamReader.Builder()
|
||||
.setVideoWith(width)
|
||||
.setVideoHeight(height)
|
||||
.setVideoStride(width)
|
||||
.setVideoSize(height * width * 3 / 2)
|
||||
.setVideoRotation(0)
|
||||
.setAudioSampleRate(44100)
|
||||
.setAudioChannel(1)
|
||||
.setAudioBufferSize(2048)
|
||||
.build();
|
||||
mInteractLiveManager = new InteractLiveBaseManager();
|
||||
mInteractLiveManager.init(context, InteractiveMode.BARE_STREAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置主播预览 View
|
||||
*
|
||||
* @param frameLayout 主播预览 View
|
||||
*/
|
||||
public void setAnchorRenderView(FrameLayout frameLayout) {
|
||||
this.mAnchorRenderView = frameLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置观众预览 View
|
||||
*
|
||||
* @param frameLayout 观众预览 View
|
||||
*/
|
||||
public void setViewerRenderView(FrameLayout frameLayout) {
|
||||
this.mViewerRenderView = frameLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始直播
|
||||
*/
|
||||
public void startPush(InteractiveUserData userData) {
|
||||
mPushUserData = userData;
|
||||
externAV();
|
||||
mInteractLiveManager.startPreviewAndPush(mPushUserData, mAnchorRenderView, true);
|
||||
}
|
||||
|
||||
public void stopPreview() {
|
||||
mInteractLiveManager.stopPreview();
|
||||
}
|
||||
|
||||
public void stopPush() {
|
||||
mPushUserData = null;
|
||||
mInteractLiveManager.stopPush();
|
||||
}
|
||||
|
||||
public void stopCamera() {
|
||||
mInteractLiveManager.stopCamera();
|
||||
}
|
||||
|
||||
private void externAV() {
|
||||
if (LivePushGlobalConfig.mAlivcLivePushConfig.isExternMainStream()) {
|
||||
File yuvFile = ResourcesConst.localCaptureYUVFilePath(mContext);
|
||||
mLocalStreamReader.readYUVData(yuvFile, (buffer, pts, videoWidth, videoHeight, videoStride, videoSize, videoRotation) -> {
|
||||
mInteractLiveManager.inputStreamVideoData(buffer, videoWidth, videoHeight, videoStride, videoSize, pts, videoRotation);
|
||||
});
|
||||
File pcmFile = ResourcesConst.localCapturePCMFilePath(mContext);
|
||||
mLocalStreamReader.readPCMData(pcmFile, (buffer, length, pts, audioSampleRate, audioChannel) -> {
|
||||
mInteractLiveManager.inputStreamAudioData(buffer, length, audioSampleRate, audioChannel, pts);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 开始拉流
|
||||
public void startPull(InteractiveUserData userData) {
|
||||
mPullUserData = userData;
|
||||
mInteractLiveManager.setPullView(mPullUserData, mViewerRenderView, false);
|
||||
mInteractLiveManager.startPullRTCStream(mPullUserData);
|
||||
}
|
||||
|
||||
// 结束拉流
|
||||
public void stopPull() {
|
||||
mInteractLiveManager.stopPullRTCStream(mPullUserData);
|
||||
mPullUserData = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主播是否正在连麦
|
||||
*
|
||||
* @return true:正在连麦 false:没有连麦
|
||||
*/
|
||||
public boolean isPulling() {
|
||||
return mInteractLiveManager.isPulling(mPullUserData);
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mInteractLiveManager.release();
|
||||
mLocalStreamReader.stopYUV();
|
||||
mLocalStreamReader.stopPcm();
|
||||
}
|
||||
|
||||
public void setInteractLivePushPullListener(InteractLivePushPullListener listener) {
|
||||
mInteractLiveManager.setInteractLivePushPullListener(listener);
|
||||
}
|
||||
|
||||
public void switchCamera() {
|
||||
mInteractLiveManager.switchCamera();
|
||||
}
|
||||
|
||||
public void enableSpeakerPhone(boolean enable) {
|
||||
mInteractLiveManager.enableSpeakerPhone(enable);
|
||||
}
|
||||
|
||||
public void setMute(boolean b) {
|
||||
mInteractLiveManager.setMute(b);
|
||||
}
|
||||
|
||||
public void enableAudioCapture(boolean enable) {
|
||||
mInteractLiveManager.enableAudioCapture(enable);
|
||||
}
|
||||
|
||||
public void muteLocalCamera(boolean muteLocalCamera) {
|
||||
mInteractLiveManager.muteLocalCamera(muteLocalCamera);
|
||||
}
|
||||
|
||||
public void enableLocalCamera(boolean enable) {
|
||||
mInteractLiveManager.enableLocalCamera(enable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
package com.alivc.live.barestream_interactive;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.acker.simplezxing.activity.CaptureActivity;
|
||||
import com.alivc.live.commonui.utils.StatusBarUtil;
|
||||
import com.alivc.live.commonutils.ToastUtils;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
import com.alivc.live.interactive_common.listener.InteractLivePushPullListener;
|
||||
import com.alivc.live.interactive_common.listener.InteractLiveTipsViewListener;
|
||||
import com.alivc.live.interactive_common.utils.InteractLiveIntent;
|
||||
import com.alivc.live.commonui.avdialog.AUILiveDialog;
|
||||
import com.alivc.live.interactive_common.widget.ConnectionLostTipsView;
|
||||
import com.alivc.live.interactive_common.widget.InteractiveCommonInputView;
|
||||
import com.alivc.live.interactive_common.widget.InteractiveConnectView;
|
||||
import com.alivc.live.interactive_common.widget.InteractiveRoomControlView;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayError;
|
||||
|
||||
public class InteractiveBareActivity extends AppCompatActivity {
|
||||
|
||||
private static final int REQ_CODE_PERMISSION = 0x1111;
|
||||
private static final int REQ_CODE_PUSH_URL = 0x2222;
|
||||
private static final int REQ_CODE_PULL_URL = 0x3333;
|
||||
public static final String DATA_INTERACTIVE_PUSH_URL = "data_interactive_push_url";
|
||||
public static final String DATA_INTERACTIVE_PULL_URL = "data_interactive_pull_url";
|
||||
|
||||
private AUILiveDialog mAUILiveDialog;
|
||||
|
||||
//Dialog 弹窗的意图
|
||||
private InteractLiveIntent mCurrentIntent;
|
||||
private ImageView mCloseImageView;
|
||||
private TextView mShowConnectIdTextView;
|
||||
//大窗口
|
||||
private FrameLayout mBigFrameLayout;
|
||||
//小窗口
|
||||
private FrameLayout mSmallFrameLayout;
|
||||
private ConnectionLostTipsView mConnectionLostTipsView;
|
||||
|
||||
//输入 URL 方式连麦
|
||||
private InteractiveUserData mPushUserData;
|
||||
private InteractiveUserData mPullUserData;
|
||||
|
||||
private InteractiveCommonInputView commonInputView;
|
||||
private InteractiveConnectView mInteractiveConnectView;
|
||||
private InteractiveRoomControlView mInteractiveRoomControlView;
|
||||
private BareStreamController mBareStreamController;
|
||||
private EditText mInteractivePushUrlEditText;
|
||||
private ImageView mPushUrlQrImageView;
|
||||
private TextView mStartPushTextView;
|
||||
private boolean mIsPushing;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
StatusBarUtil.translucent(this, Color.TRANSPARENT);
|
||||
setContentView(R.layout.activity_interactive_bare);
|
||||
|
||||
InteractiveUserData pushUserData = new InteractiveUserData();
|
||||
pushUserData.url = getIntent().getStringExtra(DATA_INTERACTIVE_PUSH_URL);
|
||||
mPushUserData = pushUserData;
|
||||
|
||||
InteractiveUserData pullUserData = new InteractiveUserData();
|
||||
pullUserData.url = getIntent().getStringExtra(DATA_INTERACTIVE_PULL_URL);
|
||||
mPullUserData = pullUserData;
|
||||
|
||||
mBareStreamController = new BareStreamController(this);
|
||||
|
||||
initView();
|
||||
initListener();
|
||||
initData();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mInteractivePushUrlEditText.setText(mPushUserData != null ? mPushUserData.url : "");
|
||||
|
||||
mBareStreamController.setAnchorRenderView(mBigFrameLayout);
|
||||
mBareStreamController.setViewerRenderView(mSmallFrameLayout);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mAUILiveDialog = new AUILiveDialog(this);
|
||||
mInteractiveConnectView = findViewById(R.id.connect_view);
|
||||
mCloseImageView = findViewById(R.id.iv_close);
|
||||
mShowConnectIdTextView = findViewById(R.id.tv_show_connect);
|
||||
mBigFrameLayout = findViewById(R.id.big_fl);
|
||||
mSmallFrameLayout = findViewById(R.id.small_fl);
|
||||
mInteractiveRoomControlView = findViewById(R.id.interactive_setting_view);
|
||||
|
||||
mConnectionLostTipsView = new ConnectionLostTipsView(this);
|
||||
|
||||
mPushUrlQrImageView = findViewById(R.id.iv_qr_push_url);
|
||||
mStartPushTextView = findViewById(R.id.tv_start_push);
|
||||
mInteractivePushUrlEditText = findViewById(R.id.et_interactive_push_url);
|
||||
|
||||
mInteractiveConnectView.setDefaultText(getResources().getString(R.string.interactive_bare_stream_start_pull));
|
||||
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mPushUrlQrImageView.setOnClickListener(view -> {
|
||||
startQr(REQ_CODE_PUSH_URL);
|
||||
});
|
||||
|
||||
mStartPushTextView.setOnClickListener(view -> {
|
||||
if (mIsPushing) {
|
||||
mBareStreamController.stopPush();
|
||||
changePushState(false);
|
||||
} else {
|
||||
mPushUserData.url = mInteractivePushUrlEditText.getText().toString();
|
||||
mBareStreamController.startPush(mPushUserData);
|
||||
}
|
||||
});
|
||||
|
||||
mConnectionLostTipsView.setConnectionLostListener(() -> runOnUiThread(() -> finish()));
|
||||
|
||||
mBareStreamController.setInteractLivePushPullListener(new InteractLivePushPullListener() {
|
||||
@Override
|
||||
public void onPullSuccess(InteractiveUserData userData) {
|
||||
super.onPullSuccess(userData);
|
||||
changeSmallSurfaceViewVisible(true);
|
||||
updateConnectTextView(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPullError(InteractiveUserData userData, AlivcLivePlayError errorType, String errorMsg) {
|
||||
super.onPullError(userData, errorType, errorMsg);
|
||||
runOnUiThread(() -> {
|
||||
changeSmallSurfaceViewVisible(false);
|
||||
mBareStreamController.stopPull();
|
||||
updateConnectTextView(false);
|
||||
ToastUtils.show(getResources().getString(R.string.interact_live_viewer_left));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPullStop(InteractiveUserData userData) {
|
||||
super.onPullStop(userData);
|
||||
runOnUiThread(() -> {
|
||||
changeSmallSurfaceViewVisible(false);
|
||||
updateConnectTextView(false);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushSuccess() {
|
||||
super.onPushSuccess();
|
||||
changePushState(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushError() {
|
||||
super.onPushError();
|
||||
changePushState(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionLost() {
|
||||
super.onConnectionLost();
|
||||
runOnUiThread(() -> mConnectionLostTipsView.show());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveSEIMessage(int payload, byte[] data) {
|
||||
super.onReceiveSEIMessage(payload, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerSei(int payload, byte[] uuid, byte[] data) {
|
||||
super.onPlayerSei(payload, uuid, data);
|
||||
}
|
||||
});
|
||||
|
||||
//开始连麦
|
||||
mInteractiveConnectView.setConnectClickListener(() -> {
|
||||
if (mBareStreamController.isPulling()) {
|
||||
//主播端停止连麦
|
||||
mCurrentIntent = InteractLiveIntent.INTENT_STOP_PULL;
|
||||
showInteractLiveDialog(getResources().getString(R.string.interact_live_connect_finish_tips), false);
|
||||
} else {
|
||||
//主播端开始连麦,输入用户 id
|
||||
if (mPullUserData == null || TextUtils.isEmpty(mPullUserData.url)) {
|
||||
showInteractLiveDialog(getResources().getString(R.string.interact_live_url_connect_tips), true);
|
||||
return;
|
||||
}
|
||||
mBareStreamController.startPull(mPullUserData);
|
||||
}
|
||||
});
|
||||
|
||||
mCloseImageView.setOnClickListener(view -> {
|
||||
mCurrentIntent = InteractLiveIntent.INTENT_FINISH;
|
||||
showInteractLiveDialog(getResources().getString(R.string.interact_live_leave_room_tips), false);
|
||||
});
|
||||
|
||||
mInteractiveRoomControlView.setOnClickEventListener(new InteractiveRoomControlView.OnClickEventListener() {
|
||||
@Override
|
||||
public void onClickSwitchCamera() {
|
||||
mBareStreamController.switchCamera();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickSpeakerPhone(boolean enable) {
|
||||
mBareStreamController.enableSpeakerPhone(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickMuteAudio(boolean mute) {
|
||||
mBareStreamController.setMute(mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickMuteVideo(boolean mute) {
|
||||
mBareStreamController.setMute(mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickEnableAudio(boolean enable) {
|
||||
mBareStreamController.enableAudioCapture(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickEnableVideo(boolean enable) {
|
||||
mBareStreamController.enableLocalCamera(enable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void changeSmallSurfaceViewVisible(boolean isShowSurfaceView) {
|
||||
mSmallFrameLayout.setVisibility(isShowSurfaceView ? View.VISIBLE : View.INVISIBLE);
|
||||
mInteractiveConnectView.isShow(isShowSurfaceView);
|
||||
}
|
||||
|
||||
public void updateConnectTextView(boolean connecting) {
|
||||
if (connecting) {
|
||||
mShowConnectIdTextView.setVisibility(View.VISIBLE);
|
||||
mInteractiveConnectView.connected(getResources().getString(R.string.interactive_bare_stream_stop_pull));
|
||||
} else {
|
||||
mShowConnectIdTextView.setVisibility(View.GONE);
|
||||
mInteractiveConnectView.unConnected(getResources().getString(R.string.interactive_bare_stream_start_pull));
|
||||
}
|
||||
}
|
||||
|
||||
private void showInteractLiveDialog(String content, boolean showInputView) {
|
||||
commonInputView = new InteractiveCommonInputView(InteractiveBareActivity.this);
|
||||
commonInputView.setViewType(InteractiveCommonInputView.ViewType.BARE_STREAM);
|
||||
commonInputView.showInputView(content, showInputView);
|
||||
mAUILiveDialog.setContentView(commonInputView);
|
||||
mAUILiveDialog.show();
|
||||
|
||||
commonInputView.setOnInteractLiveTipsViewListener(new InteractLiveTipsViewListener() {
|
||||
@Override
|
||||
public void onCancel() {
|
||||
if (mAUILiveDialog.isShowing()) {
|
||||
mAUILiveDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
if (mCurrentIntent == InteractLiveIntent.INTENT_STOP_PULL) {
|
||||
//主播结束连麦
|
||||
mAUILiveDialog.dismiss();
|
||||
mBareStreamController.stopPull();
|
||||
updateConnectTextView(false);
|
||||
changeSmallSurfaceViewVisible(false);
|
||||
} else if (mCurrentIntent == InteractLiveIntent.INTENT_FINISH) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputConfirm(InteractiveUserData userData) {
|
||||
hideInputSoftFromWindowMethod(InteractiveBareActivity.this, commonInputView);
|
||||
if (userData == null || TextUtils.isEmpty(userData.url)) {
|
||||
ToastUtils.show(getResources().getString(R.string.interact_live_connect_input_error_tips));
|
||||
return;
|
||||
}
|
||||
mAUILiveDialog.dismiss();
|
||||
// 主播端,输入观众 id 后,开始连麦
|
||||
mPullUserData = userData;
|
||||
mBareStreamController.startPull(userData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQrClick() {
|
||||
startQr(REQ_CODE_PULL_URL);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mBareStreamController.release();
|
||||
}
|
||||
|
||||
public void hideInputSoftFromWindowMethod(Context context, View view) {
|
||||
try {
|
||||
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case REQ_CODE_PUSH_URL:
|
||||
case REQ_CODE_PULL_URL:
|
||||
switch (resultCode) {
|
||||
case RESULT_OK:
|
||||
if (requestCode == REQ_CODE_PUSH_URL) {
|
||||
if (mInteractivePushUrlEditText != null) {
|
||||
mInteractivePushUrlEditText.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
} else {
|
||||
if (commonInputView != null) {
|
||||
commonInputView.setQrResult(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case RESULT_CANCELED:
|
||||
if (data != null) {
|
||||
// for some reason camera is not working correctly
|
||||
ToastUtils.show(getString(R.string.live_push_switch_to_facing_back_camera));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void changePushState(boolean isSuccess) {
|
||||
this.mIsPushing = isSuccess;
|
||||
if (isSuccess) {
|
||||
mStartPushTextView.setText(getResources().getString(com.alivc.live.interactive_common.R.string.interact_stop_push));
|
||||
mStartPushTextView.setBackground(getResources().getDrawable(com.alivc.live.interactive_common.R.drawable.shape_interact_live_un_connect_btn_bg));
|
||||
} else {
|
||||
mStartPushTextView.setText(getResources().getString(com.alivc.live.interactive_common.R.string.interact_start_push));
|
||||
mStartPushTextView.setBackground(getResources().getDrawable(com.alivc.live.interactive_common.R.drawable.shape_pysh_btn_bg));
|
||||
}
|
||||
}
|
||||
|
||||
private void startQr(int requestCode) {
|
||||
if (ContextCompat.checkSelfPermission(InteractiveBareActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||
// Do not have the permission of camera, request it.
|
||||
ActivityCompat.requestPermissions(InteractiveBareActivity.this, new String[]{Manifest.permission.CAMERA}, REQ_CODE_PERMISSION);
|
||||
} else {
|
||||
// Have gotten the permission
|
||||
startCaptureActivityForResult(requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void startCaptureActivityForResult(int requestCode) {
|
||||
Intent intent = new Intent(InteractiveBareActivity.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, requestCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package com.alivc.live.barestream_interactive;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.acker.simplezxing.activity.CaptureActivity;
|
||||
import com.alivc.live.commonui.utils.StatusBarUtil;
|
||||
import com.alivc.live.interactive_common.InteractiveSettingActivity;
|
||||
import com.alivc.live.interactive_common.utils.LivePushGlobalConfig;
|
||||
import com.alivc.live.interactive_common.widget.InteractiveQrEditView;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class InteractiveInputURLActivity extends AppCompatActivity {
|
||||
|
||||
private static final int REQ_CODE_PERMISSION = 0x1111;
|
||||
private static final int REQ_CODE_PUSH_URL = 0x2222;
|
||||
private static final int REQ_CODE_PULL_URL = 0x3333;
|
||||
private static final int REQ_CODE_PULL_URL_1 = 0x4444;
|
||||
private static final int REQ_CODE_PULL_URL_2 = 0x5555;
|
||||
private static final int REQ_CODE_PULL_URL_3 = 0x6666;
|
||||
|
||||
private TextView mConfirmTextView;
|
||||
private TextView mSettingTextView;
|
||||
private ImageView mBackImageView;
|
||||
private InteractiveQrEditView mInteractivePushView;
|
||||
private InteractiveQrEditView mInteractivePullView;
|
||||
private InteractiveQrEditView mInteractivePullView1;
|
||||
private InteractiveQrEditView mInteractivePullView2;
|
||||
private InteractiveQrEditView mInteractivePullView3;
|
||||
private LinearLayout mMorePullViewRoot;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
StatusBarUtil.translucent(this, Color.TRANSPARENT);
|
||||
|
||||
setContentView(R.layout.activity_interactive_input_url);
|
||||
|
||||
initView();
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mBackImageView = findViewById(R.id.iv_back);
|
||||
mConfirmTextView = findViewById(R.id.tv_confirm);
|
||||
mSettingTextView = findViewById(R.id.tv_setting);
|
||||
|
||||
mMorePullViewRoot = findViewById(R.id.more_pull_view);
|
||||
mInteractivePushView = findViewById(R.id.push_view);
|
||||
mInteractivePullView = findViewById(R.id.pull_view);
|
||||
mInteractivePullView1 = findViewById(R.id.pull_view1);
|
||||
mInteractivePullView2 = findViewById(R.id.pull_view2);
|
||||
mInteractivePullView3 = findViewById(R.id.pull_view3);
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mInteractivePushView.setOnQrClickListener(() -> {
|
||||
startQr(REQ_CODE_PUSH_URL);
|
||||
});
|
||||
mInteractivePullView.setOnQrClickListener(() -> {
|
||||
startQr(REQ_CODE_PULL_URL);
|
||||
});
|
||||
|
||||
mInteractivePullView1.setOnQrClickListener(() -> {
|
||||
startQr(REQ_CODE_PULL_URL_1);
|
||||
});
|
||||
|
||||
mInteractivePullView2.setOnQrClickListener(() -> {
|
||||
startQr(REQ_CODE_PULL_URL_2);
|
||||
});
|
||||
|
||||
mInteractivePullView3.setOnQrClickListener(() -> {
|
||||
startQr(REQ_CODE_PULL_URL_3);
|
||||
});
|
||||
|
||||
mBackImageView.setOnClickListener(view -> finish());
|
||||
|
||||
mConfirmTextView.setOnClickListener(view -> {
|
||||
HashMap<String, String> extras = new HashMap<>();
|
||||
|
||||
String pushUrl = mInteractivePushView.getEditText();
|
||||
String pullUrl = mInteractivePullView.getEditText();
|
||||
extras.put(InteractiveBareActivity.DATA_INTERACTIVE_PUSH_URL, pushUrl);
|
||||
extras.put(InteractiveBareActivity.DATA_INTERACTIVE_PULL_URL, pullUrl);
|
||||
|
||||
Intent intent;
|
||||
if (LivePushGlobalConfig.IS_MULTI_INTERACT) {
|
||||
intent = new Intent(InteractiveInputURLActivity.this, InteractiveMultiBareActivity.class);
|
||||
|
||||
String pullUrl1 = mInteractivePullView1.getEditText();
|
||||
String pullUrl2 = mInteractivePullView2.getEditText();
|
||||
String pullUrl3 = mInteractivePullView3.getEditText();
|
||||
extras.put(InteractiveMultiBareActivity.DATA_INTERACTIVE_PULL_URL_1, pullUrl1);
|
||||
extras.put(InteractiveMultiBareActivity.DATA_INTERACTIVE_PULL_URL_2, pullUrl2);
|
||||
extras.put(InteractiveMultiBareActivity.DATA_INTERACTIVE_PULL_URL_3, pullUrl3);
|
||||
} else {
|
||||
intent = new Intent(InteractiveInputURLActivity.this, InteractiveBareActivity.class);
|
||||
}
|
||||
|
||||
for (HashMap.Entry<String, String> entry : extras.entrySet()) {
|
||||
intent.putExtra(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
mSettingTextView.setOnClickListener(view -> {
|
||||
Intent intent = new Intent(this, InteractiveSettingActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mMorePullViewRoot.setVisibility(LivePushGlobalConfig.IS_MULTI_INTERACT ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case REQ_CODE_PUSH_URL:
|
||||
case REQ_CODE_PULL_URL:
|
||||
case REQ_CODE_PULL_URL_1:
|
||||
case REQ_CODE_PULL_URL_2:
|
||||
case REQ_CODE_PULL_URL_3:
|
||||
switch (resultCode) {
|
||||
case RESULT_OK:
|
||||
if (requestCode == REQ_CODE_PUSH_URL) {
|
||||
if (mInteractivePushView != null) {
|
||||
mInteractivePushView.setEditText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
} else if (requestCode == REQ_CODE_PULL_URL) {
|
||||
if (mInteractivePullView != null) {
|
||||
mInteractivePullView.setEditText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
} else if (requestCode == REQ_CODE_PULL_URL_1) {
|
||||
if (mInteractivePullView1 != null) {
|
||||
mInteractivePullView1.setEditText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
} else if (requestCode == REQ_CODE_PULL_URL_2) {
|
||||
if (mInteractivePullView2 != null) {
|
||||
mInteractivePullView2.setEditText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
} else {
|
||||
if (mInteractivePullView3 != null) {
|
||||
mInteractivePullView3.setEditText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void startQr(int requestCode) {
|
||||
if (ContextCompat.checkSelfPermission(InteractiveInputURLActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||
// Do not have the permission of camera, request it.
|
||||
ActivityCompat.requestPermissions(InteractiveInputURLActivity.this, new String[]{Manifest.permission.CAMERA}, REQ_CODE_PERMISSION);
|
||||
} else {
|
||||
// Have gotten the permission
|
||||
startCaptureActivityForResult(requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void startCaptureActivityForResult(int requestCode) {
|
||||
Intent intent = new Intent(InteractiveInputURLActivity.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, requestCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
package com.alivc.live.barestream_interactive;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.acker.simplezxing.activity.CaptureActivity;
|
||||
import com.alivc.live.barestream_interactive.adapter.InteractiveMultiBareRecyclerViewAdapter;
|
||||
import com.alivc.live.barestream_interactive.bean.BareStreamBean;
|
||||
import com.alivc.live.commonui.utils.StatusBarUtil;
|
||||
import com.alivc.live.commonutils.ToastUtils;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
import com.alivc.live.interactive_common.listener.InteractLiveTipsViewListener;
|
||||
import com.alivc.live.interactive_common.listener.InteractLivePushPullListener;
|
||||
import com.alivc.live.interactive_common.utils.InteractLiveIntent;
|
||||
import com.alivc.live.commonui.avdialog.AUILiveDialog;
|
||||
import com.alivc.live.interactive_common.widget.ConnectionLostTipsView;
|
||||
import com.alivc.live.interactive_common.widget.InteractiveCommonInputView;
|
||||
import com.alivc.live.interactive_common.widget.InteractiveRoomControlView;
|
||||
import com.alivc.live.player.annotations.AlivcLivePlayError;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class InteractiveMultiBareActivity extends AppCompatActivity {
|
||||
|
||||
private static final int REQ_CODE_PERMISSION = 0x1111;
|
||||
private static final int REQ_CODE_PUSH_URL = 0x2222;
|
||||
private static final int REQ_CODE_PULL_URL = 0x3333;
|
||||
public static final String DATA_INTERACTIVE_PUSH_URL = "data_interactive_push_url";
|
||||
public static final String DATA_INTERACTIVE_PULL_URL = "data_interactive_pull_url";
|
||||
public static final String DATA_INTERACTIVE_PULL_URL_1 = "data_interactive_pull_url_1";
|
||||
public static final String DATA_INTERACTIVE_PULL_URL_2 = "data_interactive_pull_url_2";
|
||||
public static final String DATA_INTERACTIVE_PULL_URL_3 = "data_interactive_pull_url_3";
|
||||
|
||||
private AUILiveDialog mAUILiveDialog;
|
||||
|
||||
//Dialog 弹窗的意图
|
||||
private InteractLiveIntent mCurrentIntent;
|
||||
private ImageView mCloseImageView;
|
||||
private TextView mShowConnectIdTextView;
|
||||
//大窗口
|
||||
private FrameLayout mBigFrameLayout;
|
||||
//小窗口
|
||||
private ConnectionLostTipsView mConnectionLostTipsView;
|
||||
|
||||
//输入 URL 方式连麦
|
||||
private InteractiveUserData mPushUserData;
|
||||
private InteractiveUserData mPullUserData;
|
||||
private InteractiveUserData mPullUserData1;
|
||||
private InteractiveUserData mPullUserData2;
|
||||
private InteractiveUserData mPullUserData3;
|
||||
|
||||
private InteractiveCommonInputView commonInputView;
|
||||
private InteractiveRoomControlView mInteractiveRoomControlView;
|
||||
private MultiBareStreamController mBareStreamController;
|
||||
private EditText mInteractivePushUrlEditText;
|
||||
private ImageView mPushUrlQrImageView;
|
||||
private TextView mStartPushTextView;
|
||||
private InteractiveMultiBareRecyclerViewAdapter mAdapter;
|
||||
private final List<BareStreamBean> mFakeList = new ArrayList<>();
|
||||
private RecyclerView mRecyclerView;
|
||||
private BareStreamBean mCurrentBareStreamBean;
|
||||
private int mCurrentCheckedPosition;
|
||||
private boolean mIsPushing;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
StatusBarUtil.translucent(this, Color.TRANSPARENT);
|
||||
setContentView(R.layout.activity_interactive_multi_bare);
|
||||
|
||||
InteractiveUserData pushUserData = new InteractiveUserData();
|
||||
pushUserData.url = getIntent().getStringExtra(DATA_INTERACTIVE_PUSH_URL);
|
||||
mPushUserData = pushUserData;
|
||||
|
||||
InteractiveUserData pullUserData = new InteractiveUserData();
|
||||
pullUserData.url = getIntent().getStringExtra(DATA_INTERACTIVE_PULL_URL);
|
||||
mPullUserData = pullUserData;
|
||||
|
||||
InteractiveUserData pullUserData1 = new InteractiveUserData();
|
||||
pullUserData1.url = getIntent().getStringExtra(DATA_INTERACTIVE_PULL_URL_1);
|
||||
mPullUserData1 = pullUserData1;
|
||||
|
||||
InteractiveUserData pullUserData2 = new InteractiveUserData();
|
||||
pullUserData2.url = getIntent().getStringExtra(DATA_INTERACTIVE_PULL_URL_2);
|
||||
mPullUserData2 = pullUserData2;
|
||||
|
||||
InteractiveUserData pullUserData3 = new InteractiveUserData();
|
||||
pullUserData3.url = getIntent().getStringExtra(DATA_INTERACTIVE_PULL_URL_3);
|
||||
mPullUserData3 = pullUserData3;
|
||||
|
||||
mBareStreamController = new MultiBareStreamController(this);
|
||||
|
||||
initView();
|
||||
initListener();
|
||||
initData();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mInteractivePushUrlEditText.setText(mPushUserData != null ? mPushUserData.url : "");
|
||||
|
||||
mBareStreamController.setAnchorRenderView(mBigFrameLayout);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BareStreamBean bareStreamBean = new BareStreamBean();
|
||||
switch (i) {
|
||||
case 0:
|
||||
bareStreamBean.setUserData(mPullUserData);
|
||||
break;
|
||||
case 1:
|
||||
bareStreamBean.setUserData(mPullUserData1);
|
||||
break;
|
||||
case 2:
|
||||
bareStreamBean.setUserData(mPullUserData2);
|
||||
break;
|
||||
case 3:
|
||||
bareStreamBean.setUserData(mPullUserData3);
|
||||
break;
|
||||
}
|
||||
mFakeList.add(bareStreamBean);
|
||||
}
|
||||
mAdapter.setData(mFakeList);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mAUILiveDialog = new AUILiveDialog(this);
|
||||
mCloseImageView = findViewById(R.id.iv_close);
|
||||
mShowConnectIdTextView = findViewById(R.id.tv_show_connect);
|
||||
mBigFrameLayout = findViewById(R.id.big_fl);
|
||||
mInteractiveRoomControlView = findViewById(R.id.interactive_setting_view);
|
||||
|
||||
mConnectionLostTipsView = new ConnectionLostTipsView(this);
|
||||
|
||||
mPushUrlQrImageView = findViewById(R.id.iv_qr_push_url);
|
||||
mStartPushTextView = findViewById(R.id.tv_start_push);
|
||||
mInteractivePushUrlEditText = findViewById(R.id.et_interactive_push_url);
|
||||
|
||||
mRecyclerView = findViewById(R.id.recycler_view);
|
||||
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
|
||||
gridLayoutManager.setOrientation(GridLayoutManager.HORIZONTAL);
|
||||
mRecyclerView.setLayoutManager(gridLayoutManager);
|
||||
mAdapter = new InteractiveMultiBareRecyclerViewAdapter();
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mPushUrlQrImageView.setOnClickListener(view -> {
|
||||
startQr(REQ_CODE_PUSH_URL);
|
||||
});
|
||||
|
||||
mAdapter.setOnConnectClickListener(position -> {
|
||||
mCurrentCheckedPosition = position;
|
||||
mCurrentBareStreamBean = mFakeList.get(position);
|
||||
if (mCurrentBareStreamBean.isConnected()) {
|
||||
mCurrentIntent = InteractLiveIntent.INTENT_STOP_PULL;
|
||||
showInteractLiveDialog(getResources().getString(R.string.interact_live_connect_finish_tips), false);
|
||||
} else {
|
||||
if (TextUtils.isEmpty(mCurrentBareStreamBean.getUrl())) {
|
||||
showInteractLiveDialog(getResources().getString(R.string.interact_live_url_connect_tips), true);
|
||||
} else {
|
||||
FrameLayout renderViewByPosition = getRenderViewByPosition(position);
|
||||
if (renderViewByPosition != null) {
|
||||
mBareStreamController.startConnect(mCurrentBareStreamBean.getUserData(), renderViewByPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mStartPushTextView.setOnClickListener(view -> {
|
||||
if (mIsPushing) {
|
||||
mBareStreamController.stopPush();
|
||||
changePushState(false);
|
||||
} else {
|
||||
InteractiveUserData userData = new InteractiveUserData();
|
||||
userData.url = mInteractivePushUrlEditText.getText().toString().trim();
|
||||
mBareStreamController.setPushData(userData);
|
||||
mBareStreamController.startPush();
|
||||
}
|
||||
});
|
||||
|
||||
mConnectionLostTipsView.setConnectionLostListener(() -> runOnUiThread(() -> finish()));
|
||||
|
||||
mBareStreamController.setMultiInteractLivePushPullListener(new InteractLivePushPullListener() {
|
||||
|
||||
@Override
|
||||
public void onPushSuccess() {
|
||||
super.onPushSuccess();
|
||||
changePushState(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPushError() {
|
||||
super.onPushError();
|
||||
changePushState(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPullSuccess(InteractiveUserData userData) {
|
||||
BareStreamBean bean = mFakeList.get(Integer.parseInt(userData.getKey()));
|
||||
if (bean != null) {
|
||||
bean.setConnected(true);
|
||||
}
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPullError(InteractiveUserData userData, AlivcLivePlayError errorType, String errorMsg) {
|
||||
super.onPullError(userData, errorType, errorMsg);
|
||||
runOnUiThread(() -> {
|
||||
BareStreamBean bean = mFakeList.get(Integer.parseInt(userData.getKey()));
|
||||
if (bean != null) {
|
||||
bean.setConnected(false);
|
||||
}
|
||||
mAdapter.notifyDataSetChanged();
|
||||
mBareStreamController.stopConnect(userData);
|
||||
updateConnectTextView(false);
|
||||
ToastUtils.show(getResources().getString(R.string.interact_live_viewer_left));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPullStop(InteractiveUserData userData) {
|
||||
runOnUiThread(() -> {
|
||||
updateConnectTextView(false);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionLost() {
|
||||
runOnUiThread(() -> mConnectionLostTipsView.show());
|
||||
}
|
||||
});
|
||||
|
||||
mCloseImageView.setOnClickListener(view -> {
|
||||
mCurrentIntent = InteractLiveIntent.INTENT_FINISH;
|
||||
showInteractLiveDialog(getResources().getString(R.string.interact_live_leave_room_tips), false);
|
||||
});
|
||||
|
||||
mInteractiveRoomControlView.setOnClickEventListener(new InteractiveRoomControlView.OnClickEventListener() {
|
||||
@Override
|
||||
public void onClickSwitchCamera() {
|
||||
mBareStreamController.switchCamera();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickSpeakerPhone(boolean enable) {
|
||||
mBareStreamController.enableSpeakerPhone(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickMuteAudio(boolean mute) {
|
||||
mBareStreamController.setMute(mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickMuteVideo(boolean mute) {
|
||||
mBareStreamController.muteLocalCamera(mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickEnableAudio(boolean enable) {
|
||||
mBareStreamController.enableAudioCapture(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickEnableVideo(boolean enable) {
|
||||
mBareStreamController.enableLocalCamera(enable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateConnectTextView(boolean connecting) {
|
||||
mShowConnectIdTextView.setVisibility(connecting ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void showInteractLiveDialog(String content, boolean showInputView) {
|
||||
commonInputView = new InteractiveCommonInputView(InteractiveMultiBareActivity.this);
|
||||
commonInputView.setViewType(InteractiveCommonInputView.ViewType.BARE_STREAM);
|
||||
commonInputView.showInputView(content, showInputView);
|
||||
mAUILiveDialog.setContentView(commonInputView);
|
||||
mAUILiveDialog.show();
|
||||
|
||||
commonInputView.setOnInteractLiveTipsViewListener(new InteractLiveTipsViewListener() {
|
||||
@Override
|
||||
public void onCancel() {
|
||||
if (mAUILiveDialog.isShowing()) {
|
||||
mAUILiveDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
if (mCurrentIntent == InteractLiveIntent.INTENT_STOP_PULL) {
|
||||
//主播结束连麦
|
||||
mAUILiveDialog.dismiss();
|
||||
mBareStreamController.stopConnect(mCurrentBareStreamBean.getUserData());
|
||||
updateConnectTextView(false);
|
||||
mCurrentBareStreamBean.setConnected(false);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
} else if (mCurrentIntent == InteractLiveIntent.INTENT_FINISH) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputConfirm(InteractiveUserData userData) {
|
||||
hideInputSoftFromWindowMethod(InteractiveMultiBareActivity.this, commonInputView);
|
||||
if (userData == null || TextUtils.isEmpty(userData.url)) {
|
||||
ToastUtils.show(getResources().getString(R.string.interact_live_connect_input_error_tips));
|
||||
return;
|
||||
}
|
||||
mAUILiveDialog.dismiss();
|
||||
//主播端,输入观众 id 后,开始连麦
|
||||
mCurrentBareStreamBean.setUserData(userData);
|
||||
FrameLayout renderViewByPosition = getRenderViewByPosition(mCurrentCheckedPosition);
|
||||
mBareStreamController.startConnect(mCurrentBareStreamBean.getUserData(), renderViewByPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQrClick() {
|
||||
startQr(REQ_CODE_PULL_URL);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mBareStreamController.release();
|
||||
}
|
||||
|
||||
public void hideInputSoftFromWindowMethod(Context context, View view) {
|
||||
try {
|
||||
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case REQ_CODE_PUSH_URL:
|
||||
case REQ_CODE_PULL_URL:
|
||||
switch (resultCode) {
|
||||
case RESULT_OK:
|
||||
if (requestCode == REQ_CODE_PUSH_URL) {
|
||||
if (mInteractivePushUrlEditText != null) {
|
||||
mInteractivePushUrlEditText.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
} else {
|
||||
if (commonInputView != null) {
|
||||
commonInputView.setQrResult(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case RESULT_CANCELED:
|
||||
if (data != null) {
|
||||
// for some reason camera is not working correctly
|
||||
ToastUtils.show(getString(R.string.live_push_switch_to_facing_back_camera));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void changePushState(boolean isSuccess) {
|
||||
this.mIsPushing = isSuccess;
|
||||
if (isSuccess) {
|
||||
mStartPushTextView.setText(getResources().getString(com.alivc.live.interactive_common.R.string.interact_stop_push));
|
||||
mStartPushTextView.setBackground(getResources().getDrawable(com.alivc.live.interactive_common.R.drawable.shape_interact_live_un_connect_btn_bg));
|
||||
} else {
|
||||
mStartPushTextView.setText(getResources().getString(com.alivc.live.interactive_common.R.string.interact_start_push));
|
||||
mStartPushTextView.setBackground(getResources().getDrawable(com.alivc.live.interactive_common.R.drawable.shape_pysh_btn_bg));
|
||||
}
|
||||
}
|
||||
|
||||
private InteractiveMultiBareRecyclerViewAdapter.InteractiveMultiBareViewHolder getViewHolderByPosition(int position) {
|
||||
return (InteractiveMultiBareRecyclerViewAdapter.InteractiveMultiBareViewHolder) mRecyclerView.findViewHolderForAdapterPosition(position);
|
||||
}
|
||||
|
||||
private FrameLayout getRenderViewByPosition(int position) {
|
||||
InteractiveMultiBareRecyclerViewAdapter.InteractiveMultiBareViewHolder viewHolder = getViewHolderByPosition(position);
|
||||
if (viewHolder != null) {
|
||||
return viewHolder.getRenderFrameLayout();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private int getAdapterPositionFromByKey(String key) {
|
||||
for (int i = 0; i < mFakeList.size(); i++) {
|
||||
if (key.equals(mFakeList.get(i).getUrl())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void startQr(int requestCode) {
|
||||
if (ContextCompat.checkSelfPermission(InteractiveMultiBareActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||
// Do not have the permission of camera, request it.
|
||||
ActivityCompat.requestPermissions(InteractiveMultiBareActivity.this, new String[]{Manifest.permission.CAMERA}, REQ_CODE_PERMISSION);
|
||||
} else {
|
||||
// Have gotten the permission
|
||||
startCaptureActivityForResult(requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void startCaptureActivityForResult(int requestCode) {
|
||||
Intent intent = new Intent(InteractiveMultiBareActivity.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, requestCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.alivc.live.barestream_interactive;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.alivc.live.commonbiz.LocalStreamReader;
|
||||
import com.alivc.live.commonbiz.ResourcesConst;
|
||||
import com.alivc.live.interactive_common.InteractLiveBaseManager;
|
||||
import com.alivc.live.interactive_common.InteractiveMode;
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
import com.alivc.live.interactive_common.listener.InteractLivePushPullListener;
|
||||
import com.alivc.live.interactive_common.utils.LivePushGlobalConfig;
|
||||
import com.alivc.live.pusher.AlivcResolutionEnum;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
class MultiBareStreamController {
|
||||
|
||||
private final InteractLiveBaseManager mInteractLiveManager;
|
||||
private final Context mContext;
|
||||
private final LocalStreamReader mLocalStreamReader;
|
||||
//主播预览 View
|
||||
private FrameLayout mAnchorRenderView;
|
||||
//主播推流地址
|
||||
private InteractiveUserData mPushUserData;
|
||||
|
||||
public MultiBareStreamController(Context context) {
|
||||
this.mContext = context;
|
||||
AlivcResolutionEnum resolution = LivePushGlobalConfig.mAlivcLivePushConfig.getResolution();
|
||||
int width = AlivcResolutionEnum.getResolutionWidth(resolution, LivePushGlobalConfig.mAlivcLivePushConfig.getLivePushMode());
|
||||
int height = AlivcResolutionEnum.getResolutionHeight(resolution, LivePushGlobalConfig.mAlivcLivePushConfig.getLivePushMode());
|
||||
mLocalStreamReader = new LocalStreamReader.Builder()
|
||||
.setVideoWith(width)
|
||||
.setVideoHeight(height)
|
||||
.setVideoStride(width)
|
||||
.setVideoSize(height * width * 3 / 2)
|
||||
.setVideoRotation(0)
|
||||
.setAudioSampleRate(44100)
|
||||
.setAudioChannel(1)
|
||||
.setAudioBufferSize(2048)
|
||||
.build();
|
||||
mInteractLiveManager = new InteractLiveBaseManager();
|
||||
mInteractLiveManager.init(context, InteractiveMode.MULTI_BARE_STREAM);
|
||||
}
|
||||
|
||||
public void setPushData(InteractiveUserData userData) {
|
||||
mPushUserData = userData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置主播预览 View
|
||||
*
|
||||
* @param frameLayout 主播预览 View
|
||||
*/
|
||||
public void setAnchorRenderView(FrameLayout frameLayout) {
|
||||
this.mAnchorRenderView = frameLayout;
|
||||
}
|
||||
|
||||
public void stopPush() {
|
||||
mInteractLiveManager.stopPush();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始直播
|
||||
*/
|
||||
public void startPush() {
|
||||
externAV();
|
||||
mInteractLiveManager.startPreviewAndPush(mPushUserData, mAnchorRenderView, true);
|
||||
}
|
||||
|
||||
private void externAV() {
|
||||
if (LivePushGlobalConfig.mAlivcLivePushConfig.isExternMainStream()) {
|
||||
File yuvFile = ResourcesConst.localCaptureYUVFilePath(mContext);
|
||||
mLocalStreamReader.readYUVData(yuvFile, (buffer, pts, videoWidth, videoHeight, videoStride, videoSize, videoRotation) -> {
|
||||
mInteractLiveManager.inputStreamVideoData(buffer, videoWidth, videoHeight, videoStride, videoSize, pts, videoRotation);
|
||||
});
|
||||
File pcmFile = ResourcesConst.localCapturePCMFilePath(mContext);
|
||||
mLocalStreamReader.readPCMData(pcmFile, (buffer, length, pts, audioSampleRate, audioChannel) -> {
|
||||
mInteractLiveManager.inputStreamAudioData(buffer, length, audioSampleRate, audioChannel, pts);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始连麦
|
||||
*/
|
||||
public void startConnect(InteractiveUserData userData, FrameLayout mRenderView) {
|
||||
mInteractLiveManager.setPullView(userData, mRenderView, false);
|
||||
mInteractLiveManager.startPullRTCStream(userData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束连麦
|
||||
*/
|
||||
public void stopConnect(InteractiveUserData userData) {
|
||||
mInteractLiveManager.stopPullRTCStream(userData);
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mInteractLiveManager.release();
|
||||
mLocalStreamReader.stopYUV();
|
||||
mLocalStreamReader.stopPcm();
|
||||
}
|
||||
|
||||
public void setMultiInteractLivePushPullListener(InteractLivePushPullListener listener) {
|
||||
mInteractLiveManager.setInteractLivePushPullListener(listener);
|
||||
}
|
||||
|
||||
public void switchCamera() {
|
||||
mInteractLiveManager.switchCamera();
|
||||
}
|
||||
|
||||
public void enableSpeakerPhone(boolean enable) {
|
||||
mInteractLiveManager.enableSpeakerPhone(enable);
|
||||
}
|
||||
|
||||
public void setMute(boolean b) {
|
||||
mInteractLiveManager.setMute(b);
|
||||
}
|
||||
|
||||
public void enableAudioCapture(boolean enable) {
|
||||
mInteractLiveManager.enableAudioCapture(enable);
|
||||
}
|
||||
|
||||
public void muteLocalCamera(boolean muteLocalCamera) {
|
||||
mInteractLiveManager.muteLocalCamera(muteLocalCamera);
|
||||
}
|
||||
|
||||
public void enableLocalCamera(boolean enable) {
|
||||
mInteractLiveManager.enableLocalCamera(enable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.alivc.live.barestream_interactive.adapter;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.alivc.live.barestream_interactive.R;
|
||||
import com.alivc.live.barestream_interactive.bean.BareStreamBean;
|
||||
import com.alivc.live.interactive_common.widget.InteractiveConnectView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class InteractiveMultiBareRecyclerViewAdapter extends RecyclerView.Adapter<InteractiveMultiBareRecyclerViewAdapter.InteractiveMultiBareViewHolder> {
|
||||
|
||||
private Map<Integer, Integer> mFLayoutWithPositionMap = new HashMap<>();
|
||||
private OnItemClickListener mListener;
|
||||
private List<BareStreamBean> mData;
|
||||
private OnItemViewChangedListener mOnPKItemViewChangedListener;
|
||||
|
||||
public boolean reSetFrameLayout(int position, int frameLayoutHashCode) {
|
||||
if (mFLayoutWithPositionMap.containsKey(position)) {
|
||||
if (frameLayoutHashCode == mFLayoutWithPositionMap.get(position)) {
|
||||
return false;
|
||||
} else {
|
||||
mFLayoutWithPositionMap.put(position, frameLayoutHashCode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(InteractiveMultiBareViewHolder holder) {
|
||||
super.onViewAttachedToWindow(holder);
|
||||
if (mOnPKItemViewChangedListener != null) {
|
||||
mOnPKItemViewChangedListener.onItemViewAttachedToWindow(holder.getAdapterPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(InteractiveMultiBareViewHolder holder) {
|
||||
super.onViewDetachedFromWindow(holder);
|
||||
if (mOnPKItemViewChangedListener != null) {
|
||||
mOnPKItemViewChangedListener.onItemViewDetachedToWindow(holder.getAdapterPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InteractiveMultiBareViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_multi_interactive_bare_item, parent, false);
|
||||
return new InteractiveMultiBareViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull InteractiveMultiBareViewHolder holder, int position) {
|
||||
BareStreamBean bareStreamBean = mData.get(position);
|
||||
holder.isConnected(bareStreamBean.isConnected());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mData == null ? 0 : mData.size();
|
||||
}
|
||||
|
||||
public void setOnConnectClickListener(OnItemClickListener listener) {
|
||||
this.mListener = listener;
|
||||
}
|
||||
|
||||
public void setOnItemViewChangedListener(OnItemViewChangedListener listener) {
|
||||
this.mOnPKItemViewChangedListener = listener;
|
||||
}
|
||||
|
||||
public void setData(List<BareStreamBean> dataList) {
|
||||
this.mData = dataList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public class InteractiveMultiBareViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final InteractiveConnectView mConnectView;
|
||||
private final FrameLayout mRenderFrameLayout;
|
||||
|
||||
public InteractiveMultiBareViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
mConnectView = itemView.findViewById(R.id.connect_view);
|
||||
mRenderFrameLayout = itemView.findViewById(R.id.render_frame);
|
||||
|
||||
mConnectView.setDefaultText(mConnectView.getResources().getString(R.string.interactive_bare_stream_start_pull));
|
||||
mConnectView.setConnectClickListener(() -> {
|
||||
if (mListener != null) {
|
||||
mListener.onConnectClick(getAdapterPosition());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public FrameLayout getRenderFrameLayout() {
|
||||
return mRenderFrameLayout;
|
||||
}
|
||||
|
||||
public InteractiveConnectView getConnectView() {
|
||||
return mConnectView;
|
||||
}
|
||||
|
||||
public void isConnected(boolean isConnected) {
|
||||
if (isConnected) {
|
||||
mConnectView.connected(mConnectView.getResources().getString(R.string.interactive_bare_stream_stop_pull));
|
||||
} else {
|
||||
mConnectView.unConnected(mConnectView.getResources().getString(R.string.interactive_bare_stream_start_pull));
|
||||
}
|
||||
mConnectView.getConnectFrameLayout().setVisibility(isConnected ? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onConnectClick(int position);
|
||||
}
|
||||
|
||||
public interface OnItemViewChangedListener {
|
||||
void onItemViewAttachedToWindow(int position);
|
||||
|
||||
void onItemViewDetachedToWindow(int position);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.alivc.live.barestream_interactive.bean;
|
||||
|
||||
import com.alivc.live.interactive_common.bean.InteractiveUserData;
|
||||
|
||||
public class BareStreamBean {
|
||||
|
||||
private InteractiveUserData userData;
|
||||
private boolean isConnected;
|
||||
|
||||
public InteractiveUserData getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
public void setUserData(InteractiveUserData userData) {
|
||||
this.userData = userData;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return userData != null ? userData.url : null;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
public void setConnected(boolean connected) {
|
||||
isConnected = connected;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?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">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/big_fl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/wheel_black">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/small_fl"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="160dp"
|
||||
android:layout_gravity="right|bottom"
|
||||
android:layout_marginEnd="33dp"
|
||||
android:layout_marginBottom="110dp" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_close"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:src="@drawable/ic_close_white"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_home_id" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_home_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="44dp"
|
||||
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_show_connect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/interact_live_connecting"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="@id/tv_home_id"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_home_id"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_home_id" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_interactive_push_url"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="22dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:text="@string/interact_live_push_url"
|
||||
android:gravity="center"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_show_connect"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_interactive_push_url"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#E6E7EC"
|
||||
android:theme="@style/AUIEditText"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_start_push"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_interactive_push_url"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_interactive_push_url" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_qr_push_url"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:background="@color/transparent"
|
||||
android:layout_margin="5dp"
|
||||
android:src="@drawable/ic_scan_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_interactive_push_url"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_interactive_push_url"
|
||||
app:layout_constraintTop_toTopOf="@id/et_interactive_push_url" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_start_push"
|
||||
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_push"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintTop_toTopOf="@id/et_interactive_push_url"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_interactive_push_url"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveRoomControlView
|
||||
android:id="@+id/interactive_setting_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_interactive_push_url"/>
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveConnectView
|
||||
android:id="@+id/connect_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:layout_marginBottom="65dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,142 @@
|
||||
<?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_url_title"
|
||||
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" />
|
||||
|
||||
<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.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_title">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveQrEditView
|
||||
android:id="@+id/push_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="@string/interact_live_push_url" />
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveQrEditView
|
||||
android:id="@+id/pull_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/push_view"
|
||||
app:layout_constraintStart_toStartOf="@id/push_view"
|
||||
app:layout_constraintTop_toBottomOf="@id/push_view"
|
||||
app:title="@string/interact_live_pull_url" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/more_pull_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/pull_view">
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveQrEditView
|
||||
android:id="@+id/pull_view1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/push_view"
|
||||
app:layout_constraintStart_toStartOf="@id/push_view"
|
||||
app:layout_constraintTop_toBottomOf="@id/push_view"
|
||||
app:title="@string/interact_live_pull_url" />
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveQrEditView
|
||||
android:id="@+id/pull_view2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/push_view"
|
||||
app:layout_constraintStart_toStartOf="@id/push_view"
|
||||
app:layout_constraintTop_toBottomOf="@id/push_view"
|
||||
app:title="@string/interact_live_pull_url" />
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveQrEditView
|
||||
android:id="@+id/pull_view3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/push_view"
|
||||
app:layout_constraintStart_toStartOf="@id/push_view"
|
||||
app:layout_constraintTop_toBottomOf="@id/push_view"
|
||||
app:title="@string/interact_live_pull_url" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,117 @@
|
||||
<?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">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/big_fl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/wheel_black">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_close"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:src="@drawable/ic_close_white"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_home_id" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_home_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="44dp"
|
||||
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_show_connect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/interact_live_connecting"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="@id/tv_home_id"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_home_id"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_home_id" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_interactive_push_url"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="22dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/interact_live_push_url"
|
||||
android:textColor="#FCFCFD"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_show_connect" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_interactive_push_url"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="#E6E7EC"
|
||||
android:textColorHint="#E6E7EC"
|
||||
android:theme="@style/AUIEditText"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_start_push"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_interactive_push_url"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_interactive_push_url" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_qr_push_url"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="5dp"
|
||||
android:background="@color/transparent"
|
||||
android:src="@drawable/ic_scan_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_interactive_push_url"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_interactive_push_url"
|
||||
app:layout_constraintTop_toTopOf="@id/et_interactive_push_url" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_start_push"
|
||||
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_push"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_interactive_push_url"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/et_interactive_push_url" />
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveRoomControlView
|
||||
android:id="@+id/interactive_setting_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_interactive_push_url" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/render_frame"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintDimensionRatio="w,16:9"
|
||||
android:background="@color/alivc_color_black"
|
||||
app:layout_constraintStart_toStartOf="@id/connect_view"
|
||||
app:layout_constraintEnd_toEndOf="@id/connect_view"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<com.alivc.live.interactive_common.widget.InteractiveConnectView
|
||||
android:id="@+id/connect_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,4 @@
|
||||
<resources>
|
||||
<string name="interactive_bare_stream_start_pull">开始拉流</string>
|
||||
<string name="interactive_bare_stream_stop_pull">结束拉流</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user