集成完直播后提交代码

This commit is contained in:
xuhuixiang
2026-02-06 14:55:21 +08:00
commit ea9ffa06ff
960 changed files with 75063 additions and 0 deletions

1
LiveBasic/live_pull/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,46 @@
plugins {
id 'com.android.library'
}
android {
compileSdkVersion androidCompileSdkVersion
buildToolsVersion androidBuildToolsVersion
defaultConfig {
minSdkVersion androidMinSdkVersion
targetSdkVersion androidTargetSdkVersion
versionCode 1
versionName "1.0"
consumerProguardFiles "consumer-rules.pro"
}
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
implementation externalRtsSDK
// Add a downgraded version of the player sdk for the live project single build.
if ("true".equalsIgnoreCase(allInOne)) {
api externalPlayerFull
api externalARTC
} else {
api externalPlayerFullDowngrade
api externalARTCDowngrade
}
implementation project(':LiveCommon:live_commonbiz')
}

View File

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.alivc.live.baselive_pull">
<application>
<activity
android:name=".ui.PlayerActivity"
android:alwaysRetainTaskState="true"
android:screenOrientation="portrait"
android:theme="@style/AVLiveTheme" />
</application>
</manifest>

View File

@@ -0,0 +1,132 @@
package com.alivc.live.baselive_pull.adapter;
import android.annotation.SuppressLint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.alivc.live.baselive_pull.R;
import com.alivc.live.baselive_pull.bean.Constants;
import com.alivc.live.baselive_pull.listener.ButtonClickListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PlayButtonListAdapter extends RecyclerView.Adapter {
private ButtonClickListener clickListener;
private boolean isItemHide = false;
public void setClickListener(ButtonClickListener clickListener) {
this.clickListener = clickListener;
mButtonEnableMap = new HashMap<>();
}
private List<String> mListDatas = new ArrayList<>();
private Map<String,Boolean> mButtonEnableMap;
public void setData(List<String> data){
if(data == null){
return;
}
mListDatas.clear();
mListDatas.addAll(data);
notifyDataSetChanged();
}
public List<String> getData(){
return mListDatas;
}
public void hideItems(boolean isItemHide){
this.isItemHide = isItemHide;
notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.live_recycle_button_item_view, parent, false);
ButtonHolder buttonHolder = new ButtonHolder(view);
return buttonHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, @SuppressLint("RecyclerView") final int position) {
// position 从 0开始
ButtonHolder viewHolder= (ButtonHolder) holder;
viewHolder.textView.setText(mListDatas.get(position));
viewHolder.imageView.setImageResource(Constants.getLive_img_soure().get(mListDatas.get(position)));
viewHolder.imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(clickListener!=null){
clickListener.onButtonClick(mListDatas.get(position),position);
}
}
});
boolean enable = true;
if (mButtonEnableMap.containsKey(mListDatas.get(position))){
enable = mButtonEnableMap.get(mListDatas.get(position));
}
if(!enable){
if("开始推流".equalsIgnoreCase(mListDatas.get(position))){
viewHolder.imageView.setImageResource(R.drawable.live_push_gray);
}
if("数据指标".equalsIgnoreCase(mListDatas.get(position))){
viewHolder.imageView.setImageResource(R.drawable.live_data_gray);
}
if("麦克风".equalsIgnoreCase(mListDatas.get(position))){
viewHolder.imageView.setImageResource(R.drawable.live_microphone_gray);
}
if("调节参数".equalsIgnoreCase(mListDatas.get(position))){
viewHolder.imageView.setImageResource(R.drawable.live_adjust_gray);
}
}else {
if("开始推流".equalsIgnoreCase(mListDatas.get(position))){
viewHolder.imageView.setImageResource(R.drawable.live_push);
}
if("麦克风".equalsIgnoreCase(mListDatas.get(position))){
viewHolder.imageView.setImageResource(R.drawable.live_microphone);
}
if("数据指标".equalsIgnoreCase(mListDatas.get(position))){
viewHolder.imageView.setImageResource(R.drawable.live_data);
}
}
viewHolder.imageView.setEnabled(enable);
//针对数据指标做特殊处理
if("数据指标".equalsIgnoreCase(mListDatas.get(position))){
viewHolder.imageView.setEnabled(true);
}
}
@Override
public int getItemCount() {
return mListDatas.size();
}
private class ButtonHolder extends RecyclerView.ViewHolder {
private TextView textView;
private ImageView imageView;
public ButtonHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv_anchor_text);
imageView=itemView.findViewById(R.id.iv_anchor);
}
}
public void setButtonEnable(String buttonName,boolean enable){
mButtonEnableMap.put(buttonName,enable);
int position = -1;
for (int i = 0; i < mListDatas.size(); i++) {
if (mListDatas.get(i).equals(buttonName)){
position = i;
}
}
if (position>=0){
notifyItemChanged(position);
}
}
}

View File

@@ -0,0 +1,65 @@
package com.alivc.live.baselive_pull.bean;
import com.alivc.live.baselive_pull.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Constants {
private static List<String> live_push_button;
private static List<String> live_pull_button;
private static List<String> live_play_button;
private static HashMap<String,Integer> live_img_soure;
public static HashMap<String,Integer> getLive_img_soure() {
return live_img_soure;
}
static {
/**
* push页面的按钮
* */
live_push_button = new ArrayList<>();
live_img_soure=new HashMap<>();
live_img_soure.put("开始推流", R.drawable.live_push);
live_img_soure.put("美颜", R.drawable.live_beauty);
live_img_soure.put("音效",R.drawable.live_sound);
live_img_soure.put("摄像头",R.drawable.live_carmer);
live_img_soure.put("静音",R.drawable.mute_btn);
live_img_soure.put("调节参数",R.drawable.live_adjust_parm);
live_img_soure.put("数据指标",R.drawable.live_data);
live_push_button.add("开始推流");
live_push_button.add("美颜");
live_push_button.add("音效");
live_push_button.add("静音");
live_push_button.add("摄像头");
live_push_button.add("调节参数");
live_push_button.add("数据指标");
/**
* pull页面按钮
*/
live_pull_button = new ArrayList<>();
live_pull_button.add("暂停观看");
live_pull_button.add("静音");
live_pull_button.add("听筒切换");
live_img_soure.put("暂停观看",R.drawable.finish_play);
live_img_soure.put("听筒切换",R.drawable.telephone_change);
/**
* play页面按钮
*/
live_play_button = new ArrayList<>();
live_play_button.add("暂停观看");
}
public static List<String> getPushActivityButtonList(){
return live_push_button;
}
public static List<String> getPullActivityButtonList(){
return live_pull_button;
}
public static List<String> getPlayActivityButtonList(){
return live_play_button;
}
}

View File

@@ -0,0 +1,44 @@
package com.alivc.live.baselive_pull.bean.rmsbean;
/**
* Auto-generated: 2024-08-06 14:42:42
*/
public class RMSCanvas {
private int w;
private int h;
private int bgnd;
public void setW(int w) {
this.w = w;
}
public int getW() {
return w;
}
public void setH(int h) {
this.h = h;
}
public int getH() {
return h;
}
public void setBgnd(int bgnd) {
this.bgnd = bgnd;
}
public int getBgnd() {
return bgnd;
}
@Override
public String toString() {
return "Canvas{" +
"w=" + w +
", h=" + h +
", bgnd=" + bgnd +
'}';
}
}

View File

@@ -0,0 +1,66 @@
package com.alivc.live.baselive_pull.bean.rmsbean;
import java.util.List;
/**
* Auto-generated: 2024-08-06 14:42:42
*/
public class RMSPeriodicBean {
private RMSCanvas canvas;
private List<RMSStream> stream;
private String source;
private String ver;
private long ts;
public void setCanvas(RMSCanvas canvas) {
this.canvas = canvas;
}
public RMSCanvas getCanvas() {
return canvas;
}
public void setStream(List<RMSStream> stream) {
this.stream = stream;
}
public List<RMSStream> getStream() {
return stream;
}
public void setSource(String source) {
this.source = source;
}
public String getSource() {
return source;
}
public void setVer(String ver) {
this.ver = ver;
}
public String getVer() {
return ver;
}
public void setTs(long ts) {
this.ts = ts;
}
public long getTs() {
return ts;
}
@Override
public String toString() {
return "JsonRootBean{" +
"canvas=" + canvas +
", stream=" + stream +
", source='" + source + '\'' +
", ver='" + ver + '\'' +
", ts=" + ts +
'}';
}
}

View File

@@ -0,0 +1,154 @@
package com.alivc.live.baselive_pull.bean.rmsbean;
/**
* Auto-generated: 2024-08-06 14:42:42
*/
public class RMSStream {
private String uid;
private int paneid;
private int zorder;
private int x;
private int y;
private int w;
private int h;
private int type;
private int status;
private int cameraDisabled;
private int muted;
private int vol;
private int vad;
private int netQuality;
public void setUid(String uid) {
this.uid = uid;
}
public String getUid() {
return uid;
}
public void setPaneid(int paneid) {
this.paneid = paneid;
}
public int getPaneid() {
return paneid;
}
public void setZorder(int zorder) {
this.zorder = zorder;
}
public int getZorder() {
return zorder;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public void setW(int w) {
this.w = w;
}
public int getW() {
return w;
}
public void setH(int h) {
this.h = h;
}
public int getH() {
return h;
}
public void setType(int type) {
this.type = type;
}
public int getType() {
return type;
}
public void setStatus(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
public void setCameraDisabled(int cameraDisabled) {
this.cameraDisabled = cameraDisabled;
}
public int getCameraDisabled() {
return cameraDisabled;
}
public void setMuted(int muted) {
this.muted = muted;
}
public int getMuted() {
return muted;
}
public void setVol(int vol) {
this.vol = vol;
}
public int getVol() {
return vol;
}
public void setVad(int vad) {
this.vad = vad;
}
public int getVad() {
return vad;
}
public void setNetQuality(int netQuality) {
this.netQuality = netQuality;
}
public int getNetQuality() {
return netQuality;
}
@Override
public String toString() {
return "Stream{" +
"uid='" + uid + '\'' +
", paneid=" + paneid +
", zorder=" + zorder +
", x=" + x +
", y=" + y +
", w=" + w +
", h=" + h +
", type=" + type +
", status=" + status +
", cameraDisabled=" + cameraDisabled +
", muted=" + muted +
", vol=" + vol +
", vad=" + vad +
", netQuality=" + netQuality +
'}';
}
}

View File

@@ -0,0 +1,5 @@
package com.alivc.live.baselive_pull.listener;
public interface ButtonClickListener {
void onButtonClick(String message, int position);
}

View File

@@ -0,0 +1,379 @@
package com.alivc.live.baselive_pull.ui;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.acker.simplezxing.activity.CaptureActivity;
import com.alivc.live.baselive_pull.R;
import com.alivc.live.baselive_pull.bean.Constants;
import com.alivc.live.baselive_pull.listener.ButtonClickListener;
import com.alivc.live.baselive_pull.ui.widget.PlayButtonListView;
import com.alivc.live.commonbiz.BuildConfig;
import com.alivc.live.commonbiz.test.PushDemoTestConstants;
import com.alivc.live.commonui.dialog.CommonDialog;
import com.alivc.live.commonui.messageview.AutoScrollMessagesView;
import com.alivc.live.commonui.utils.StatusBarUtil;
import com.alivc.live.commonutils.TextFormatUtil;
import com.alivc.live.commonutils.ToastUtils;
import com.aliyun.player.AliPlayer;
import com.aliyun.player.AliPlayerFactory;
import com.aliyun.player.IPlayer;
import com.aliyun.player.bean.ErrorInfo;
import com.aliyun.player.nativeclass.PlayerConfig;
import com.aliyun.player.source.UrlSource;
import com.cicada.player.utils.Logger;
import java.util.ArrayList;
import java.util.List;
/**
* 直播拉流界面
*/
public class PlayerActivity extends AppCompatActivity implements SurfaceHolder.Callback, ButtonClickListener {
private static final String TAG = "PlayerActivity";
private PlayButtonListView mButtonListView;
private SurfaceView mSurfaceView;
private String mPullUrl = "";
private AliPlayer mAliPlayer;
private EditText mPullUrlET;//拉流地址
private Button mPullStartBtn;//开始拉流btn
private Button mScanBtn;//扫码
private boolean isStopPullFlag = false;//是否点击过停止播放
private boolean isPulling = false;
private StringBuilder mSeiStringBuilder = new StringBuilder();
private CommonDialog mDialog;
private AutoScrollMessagesView mSeiMessageView;
static {
try {
if (BuildConfig.MTL_BUILD_FOR_AIO) {
System.loadLibrary("all_in_one");
} else {
System.loadLibrary("RtsSDK");
}
} catch (Throwable ignore) {
}
}
private View mPageVg;
private ImageView mBackBtn;
private View mInputRl;
private TextView mTitleTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
StatusBarUtil.translucent(this, Color.TRANSPARENT);
setContentView(R.layout.activity_player);
initPlayer();
initView();
String initUrl = PushDemoTestConstants.getTestPullUrl();
if (!initUrl.isEmpty()) {
mPullUrlET.setText(initUrl);
mPullUrl = initUrl;
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// 当前屏幕为横屏
} else {
// 当前屏幕为竖屏
}
}
private void initPlayer() {
Logger.getInstance(this).enableConsoleLog(true);
Logger.getInstance(this).setLogLevel(Logger.LogLevel.AF_LOG_LEVEL_TRACE);
mAliPlayer = AliPlayerFactory.createAliPlayer(this.getApplicationContext());
mAliPlayer.setAutoPlay(true);
mAliPlayer.setOnRenderingStartListener(new IPlayer.OnRenderingStartListener() {
@Override
public void onRenderingStart() {
setViewState(true);
}
});
mAliPlayer.setOnErrorListener(new IPlayer.OnErrorListener() {
@Override
public void onError(ErrorInfo errorInfo) {
if (mAliPlayer != null) {
mAliPlayer.reload();
}
if (mDialog == null || !mDialog.isShowing()) {
mDialog = new CommonDialog(PlayerActivity.this);
mDialog.setDialogTitle("Error");
mDialog.setDialogContent(errorInfo.getMsg());
mDialog.setConfirmButton(TextFormatUtil.getTextFormat(PlayerActivity.this, R.string.pull_cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
mDialog.setCancelButton(TextFormatUtil.getTextFormat(PlayerActivity.this, R.string.pull_restart), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if (mAliPlayer == null) {
initPlayer();
mSurfaceView = new SurfaceView(PlayerActivity.this);
mSurfaceView.getHolder().addCallback(PlayerActivity.this);
}
UrlSource source = new UrlSource();
String url = mPullUrlET.getText().toString();
if (TextUtils.isEmpty(url)) {
return;
}
source.setUri(url);
if (mAliPlayer != null) {
PlayerConfig cfg = mAliPlayer.getConfig();
if (url.startsWith("artc://")) {
cfg.mMaxDelayTime = 1000;
cfg.mHighBufferDuration = 10;
cfg.mStartBufferDuration = 10;
}
mAliPlayer.setConfig(cfg);
mAliPlayer.setDataSource(source);
mAliPlayer.prepare();
}
}
});
mDialog.show();
}
}
});
// TODO keria: Remove the SEI function of the player first, as it will cause bytecode conflicts between the player SDK and the push SDK.
// mAliPlayer.setOnSeiDataListener((payload, uuid, data) -> {
// String msg = new String(data, StandardCharsets.UTF_8);
// String str = "[cdn]: [" + payload + "], " + msg;
// mSeiMessageView.appendMessage(str);
// Log.i(TAG, str);
//
// if (payload == 5) {
// // implementation externalGSON
// Gson gson = new Gson();
// RMSPeriodicBean rmsPeriodicBean = null;
// try {
// // The sei message may end with \0, if we want to parse the json, we need to trim the string
// rmsPeriodicBean = gson.fromJson(msg.trim(), RMSPeriodicBean.class);
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// Log.i(TAG, "rms periodic bean: " + rmsPeriodicBean);
// }
// }
// });
}
private void initView() {
mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
mPageVg = findViewById(R.id.page_bg);
mInputRl = findViewById(R.id.input_rl);
mTitleTv = findViewById(R.id.title);
mButtonListView = (PlayButtonListView) findViewById(R.id.live_buttonlistview);
mSeiMessageView = findViewById(R.id.sei_receive_view);
List<String> data = new ArrayList<>();
data.addAll(Constants.getPlayActivityButtonList());
mButtonListView.setData(data);
mButtonListView.setClickListener(this);
mButtonListView.setVisibility(View.GONE);
mSurfaceView.getHolder().addCallback(this);
mScanBtn = (Button) findViewById(R.id.player_scan_image);
mScanBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startCaptureActivityForResult();
}
});
mBackBtn = findViewById(R.id.pull_common_btn_close);
mBackBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mPageVg.getVisibility() == View.GONE) {
onButtonClick("暂停播放", 0);
} else {
finish();
}
}
});
mPullUrlET = (EditText) findViewById(R.id.pull_common_push_url);
mPullStartBtn = (Button) findViewById(R.id.pull_common_start_btn);
mPullStartBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isPulling = true;
startPull(mPullUrlET.getText().toString());
}
});
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (mAliPlayer != null) {
mAliPlayer.setSurface(holder.getSurface());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mAliPlayer != null) {
mAliPlayer.surfaceChanged();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mAliPlayer != null) {
mAliPlayer.setSurface(null);
}
}
private void stopPull() {
stopPlay();
}
private void startPull(String url) {
if (TextUtils.isEmpty(url)) {
ToastUtils.show(getBaseContext().getResources().getString(R.string.live_pull_addr_error));
} else {
ToastUtils.show("pulling...");
startPlay();
}
}
private void startCaptureActivityForResult() {
Intent intent = new Intent(PlayerActivity.this, CaptureActivity.class);
startActivityForResult(intent, CaptureActivity.REQ_CODE);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case CaptureActivity.REQ_CODE:
switch (resultCode) {
case RESULT_OK:
String pullUrl = data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT);
mPullUrlET.setText(pullUrl);
break;
case RESULT_CANCELED:
break;
default:
break;
}
default:
break;
}
}
public void startPlay() {
isPulling = true;
mSurfaceView.setVisibility(View.VISIBLE);
if (TextUtils.isEmpty(mPullUrl) && TextUtils.isEmpty(mPullUrlET.getText().toString())) {
Toast.makeText(this, "拉流地址为空", Toast.LENGTH_SHORT).show();
return;
}
if (!TextUtils.isEmpty(mPullUrlET.getText().toString())) {
mPullUrl = mPullUrlET.getText().toString();
}
UrlSource source = new UrlSource();
String pullUrl = mPullUrlET.getText().toString();
source.setUri(pullUrl);
if (mAliPlayer != null) {
PlayerConfig cfg = mAliPlayer.getConfig();
cfg.mEnableSEI = true;
if (pullUrl.startsWith("artc://")) {
cfg.mMaxDelayTime = 1000;
cfg.mHighBufferDuration = 10;
cfg.mStartBufferDuration = 10;
}
mAliPlayer.setConfig(cfg);
mAliPlayer.setDataSource(source);
mAliPlayer.prepare();
}
mButtonListView.setVisibility(View.VISIBLE);
}
/**
* 停止播放
*/
public void stopPlay() {
if (mAliPlayer != null) {
mAliPlayer.stop();
}
}
@Override
protected void onDestroy() {
if (mAliPlayer != null) {
stopPlay();
mAliPlayer.setSurface(null);
mAliPlayer.release();
mAliPlayer = null;
}
mSeiStringBuilder.delete(0, mSeiStringBuilder.length());
super.onDestroy();
}
@Override
public void onButtonClick(String message, int position) {
switch (position) {
case 0:
if (isPulling) {
stopPull();
isPulling = false;
setViewState(false);
} else {
startPull(mPullUrlET.getText().toString());
isPulling = true;
}
break;
default:
break;
}
}
private void setViewState(boolean isPlaying) {
if (isPlaying) {
mPageVg.setVisibility(View.GONE);
mButtonListView.setVisibility(View.VISIBLE);
mInputRl.setVisibility(View.GONE);
mTitleTv.setTextColor(Color.WHITE);
mBackBtn.setImageResource(R.drawable.ic_av_live_actionbar_close);
} else {
mPageVg.setVisibility(View.VISIBLE);
mButtonListView.setVisibility(View.GONE);
mInputRl.setVisibility(View.VISIBLE);
mTitleTv.setTextColor(ContextCompat.getColor(this, R.color.border_infrared));
mBackBtn.setImageResource(R.drawable.ic_av_live_action_bar_black_back);
}
}
}

View File

@@ -0,0 +1,71 @@
package com.alivc.live.baselive_pull.ui.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import com.alivc.live.baselive_pull.R;
import com.alivc.live.commonutils.DensityUtil;
/**
* 设置最大高度的Layout
*/
public class MaxHeightLayout extends LinearLayout {
private float mMaxRatio = 0.75f;
private float mMaxHeight;
private float mMinHeight;
public MaxHeightLayout(Context context) {
super(context);
init();
}
public MaxHeightLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAtts(context, attrs);
init();
}
public MaxHeightLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAtts(context, attrs);
init();
}
private void initAtts(Context context, AttributeSet attrs){
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.mMaxRatio);
if (attributes != null) {
mMaxRatio = attributes.getFloat(R.styleable.mMaxRatio_linear_max_ratio, 0.75f);
attributes.recycle();
}
}
private void init() {
mMaxHeight = mMaxRatio * DensityUtil.getDisplayMetrics(getContext()).heightPixels;
mMinHeight = DensityUtil.dip2px(getContext(), 125);
mMaxHeight = mMaxHeight < mMinHeight ? mMinHeight : mMaxHeight;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
heightSize = heightSize <= mMaxHeight ? heightSize : (int) mMaxHeight;
}
if (heightMode == MeasureSpec.UNSPECIFIED) {
heightSize = heightSize <= mMaxHeight ? heightSize : (int) mMaxHeight;
}
if (heightMode == MeasureSpec.AT_MOST) {
heightSize = heightSize <= mMaxHeight ? heightSize : (int) mMaxHeight;
}
int maxHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
super.onMeasure(widthMeasureSpec, maxHeightMeasureSpec);
}
}

View File

@@ -0,0 +1,105 @@
package com.alivc.live.baselive_pull.ui.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.alivc.live.baselive_pull.R;
import com.alivc.live.baselive_pull.adapter.PlayButtonListAdapter;
import com.alivc.live.baselive_pull.listener.ButtonClickListener;
import java.util.List;
/**
* 底部按钮
*
* @author xlx
*/
public class PlayButtonListView extends FrameLayout {
private RecyclerView mRecyclerView;
private PlayButtonListAdapter mButtonListAdapter;
private ButtonClickListener clickListener;
private boolean isItemsHide = false;
public void setClickListener(ButtonClickListener clickListener) {
this.clickListener = clickListener;
}
public PlayButtonListView(@NonNull Context context) {
this(context, null);
}
public PlayButtonListView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public PlayButtonListView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
public void setData(List<String> data) {
mButtonListAdapter.setData(data);
}
public void hideItems(boolean isItemHide) {
this.isItemsHide = isItemHide;
mButtonListAdapter.hideItems(isItemHide);
if (isItemHide) {
this.setVisibility(INVISIBLE);
} else {
this.setVisibility(VISIBLE);
}
}
public boolean isItemsHide() {
return isItemsHide;
}
private void initView(Context context) {
View view = LayoutInflater.from(context).inflate(R.layout.live_button_list, this, true);
initRecyclerView(view);
}
private void initRecyclerView(View view) {
mRecyclerView = view.findViewById(R.id.live_button_recycle);
mButtonListAdapter = new PlayButtonListAdapter();
LinearLayoutManager manager = new LinearLayoutManager(PlayButtonListView.this.getContext());
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setAdapter(mButtonListAdapter);
mRecyclerView.addItemDecoration(new SpaceItemDecortation(dip2px(getContext(), 28), getContext()));
mRecyclerView.setItemAnimator(null);
mRecyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
mButtonListAdapter.setClickListener(new ButtonClickListener() {
@Override
public void onButtonClick(String message, int position) {
if (clickListener != null) {
clickListener.onButtonClick(message, position);
}
}
});
}
/**
* 将dip或dp值转换为px值保证尺寸大小不变
*
* @param dipValue
* @param dipValue DisplayMetrics类中属性density
* @return
*/
private static int dip2px(Context context, float dipValue) {
if (context == null || context.getResources() == null)
return 1;
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}

View File

@@ -0,0 +1,41 @@
package com.alivc.live.baselive_pull.ui.widget;
import android.content.Context;
import android.graphics.Rect;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
class SpaceItemDecortation extends RecyclerView.ItemDecoration {
private int space;//声明间距 //使用构造函数定义间距
private Context mContext;
public SpaceItemDecortation(int space, Context context) {
this.space = space;
this.mContext = context;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
//获得当前item的位置
int position = parent.getChildAdapterPosition(view);
if (position == 0) {
outRect.left = dip2px(mContext, 28);
}
outRect.right = this.space;
}
/**
* 将dip或dp值转换为px值保证尺寸大小不变
*
* @param dipValue
* @param dipValue DisplayMetrics类中属性density
* @return
*/
private static int dip2px(Context context, float dipValue) {
if (context == null || context.getResources() == null)
return 1;
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp"/>
<stroke android:color="#4DCFE1"
android:width="1px"/>
<solid android:color="#4DCFE1"/>
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp"/>
<stroke android:color="@color/color_background_black_alpha_30"
android:width="1px"/>
<solid android:color="@color/color_background_black_alpha_30"/>
</shape>

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
<ImageView
android:id="@+id/page_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/colour_bg" />
<ImageView
android:id="@+id/pull_common_btn_close"
android:layout_width="26dp"
android:layout_height="44dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="33dp"
android:contentDescription="@null"
android:scaleType="centerInside"
android:src="@drawable/ic_av_live_action_bar_black_back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="33dp"
android:gravity="center"
android:text="@string/pull_rtc_enter_name_tv"
android:textColor="#23262F"
android:textSize="17sp"
android:textStyle="bold" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginTop="77dp"
android:background="#23262F" />
<RelativeLayout
android:id="@+id/input_rl"
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_36"
android:layout_marginLeft="20dp"
android:layout_marginTop="107dp"
android:layout_marginRight="20dp"
android:background="@drawable/shape_bg_search">
<Button
android:id="@+id/player_scan_image"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/view_margin_18"
android:background="@drawable/ic_live_scan" />
<View
android:id="@+id/pull_common_slipt_line"
android:layout_width="1px"
android:layout_height="19dp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_marginEnd="10dp"
android:layout_toRightOf="@id/player_scan_image"
android:background="#40ffffff" />
<EditText
android:id="@+id/pull_common_push_url"
android:layout_width="match_parent"
android:layout_height="@dimen/view_margin_22"
android:layout_centerVertical="true"
android:layout_marginEnd="80dp"
android:layout_toRightOf="@id/pull_common_slipt_line"
android:background="@null"
android:hint="@string/view_string_hint_pull_url"
android:singleLine="true"
android:textColor="@color/wheel_white"
android:textColorHint="@color/wheel_white"
android:textSize="@dimen/view_size_text_17" />
<Button
android:id="@+id/pull_common_start_btn"
android:layout_width="@dimen/view_width_size_64"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:background="@drawable/shape_bg_btn_green"
android:text="@string/live_pull"
android:textColor="@color/color_title_text_black"
android:textSize="@dimen/view_size_text_17" />
</RelativeLayout>
<com.alivc.live.baselive_pull.ui.widget.PlayButtonListView
android:id="@+id/live_buttonlistview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="36dp" />
<com.alivc.live.commonui.messageview.AutoScrollMessagesView
android:id="@+id/sei_receive_view"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="100dp"
android:padding="10dp" />
</FrameLayout>

View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:background="#80000000">
<com.alivc.live.baselive_pull.ui.widget.MaxHeightLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:layout_weight="1"
android:background="@drawable/live_dialog_bg"
android:minHeight="125dp"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="20dp" />
<TextView
android:id="@+id/dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:includeFontPadding="false"
android:singleLine="true"
android:textColor="#FCFCFD"
android:textSize="18sp"
android:visibility="gone"
tools:text="18dp大标题"
tools:visibility="visible" />
<LinearLayout
android:id="@+id/dialog_content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="9dp"
android:layout_marginRight="30dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<FrameLayout
android:id="@+id/dialog_content_container2"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/dialog_content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"
android:scrollbars="none">
<!-- 解决内部滑动问题 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/dialog_tip_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:includeFontPadding="false"
android:lineSpacingExtra="3dp"
android:textColor="#FCFCFD"
android:textSize="14sp"
tools:text="14dp提示内容" />
</LinearLayout>
</ScrollView>
</FrameLayout>
<FrameLayout
android:id="@+id/dialog_expand_content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
</LinearLayout>
<View
android:id="@+id/dialog_btn_top_line"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="30dp"
android:background="#3A3D48"
android:visibility="gone"
tools:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/dialog_cancel_btn"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:includeFontPadding="false"
android:singleLine="true"
android:text="取消"
android:textColor="#4DCFE1"
android:textSize="18sp"
android:visibility="gone"
tools:visibility="visible" />
<View
android:id="@+id/dialog_btn_line"
android:layout_width="0.5dp"
android:layout_height="52dp"
android:background="#3A3D48"
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:id="@+id/dialog_confirm_btn"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:includeFontPadding="false"
android:singleLine="true"
android:text="确定"
android:textColor="#4DCFE1"
android:textSize="18sp"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
</LinearLayout>
<!-- 解决弹窗中心点与屏幕高度45%的位置重合 -->
<View
android:id="@+id/dialog_bottom_space"
android:layout_width="match_parent"
android:layout_height="30dp" />
</com.alivc.live.baselive_pull.ui.widget.MaxHeightLayout>
</FrameLayout>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/live_button_recycle"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>

View File

@@ -0,0 +1,24 @@
<?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_anchor"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_gravity="center"
android:src="@drawable/live_carmer"/>
<TextView
android:id="@+id/tv_anchor_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:textColor="@color/color_text_white"
android:textSize="10sp"
android:layout_gravity="center"
android:text="1212"
android:gravity="center"
/>
</LinearLayout>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pull_rtc_enter_name_tv">Live Streaming</string>
<string name="view_string_hint_pull_url">Enter the source URL.</string>
<string name="pull_restart">Retry</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pull_rtc_enter_name_tv">拉流播放</string>
<string name="pull_rtc_enter_name_desc">支持常见协议如FLV、RTMP、HLS、RTS等</string>
<string name="view_string_hint_pull_url">请输入拉流url</string>
<string name="pull_restart">重试</string>
<string name="live_pull">拉流</string>
<string name="live_pull_addr_error">拉流地址错误,请检查后重新输入</string>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pull_rtc_enter_name_tv">Live Streaming</string>
<string name="pull_rtc_enter_name_desc">Common protocols are supported, such as FLV, RTMP, HLS, and RTS.</string>
<string name="view_string_hint_pull_url">Enter the source URL.</string>
<string name="pull_restart">Retry</string>
<string name="live_pull">Pull</string>
<string name="live_pull_addr_error"> Pull address error, please check and re-enter </string>
</resources>

1
LiveBasic/live_pull_rts/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,46 @@
plugins {
id 'com.android.library'
}
android {
compileSdkVersion androidCompileSdkVersion
buildToolsVersion androidBuildToolsVersion
defaultConfig {
minSdkVersion androidMinSdkVersion
targetSdkVersion androidTargetSdkVersion
versionCode 1
versionName "1.0"
consumerProguardFiles "consumer-rules.pro"
}
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
implementation externalRtsSDK
// Add a downgraded version of the player sdk for the live project single build.
if ("true".equalsIgnoreCase(allInOne)) {
implementation externalPlayerFull
implementation externalARTC
} else {
implementation externalPlayerFullDowngrade
implementation externalARTCDowngrade
}
implementation project(':LiveCommon:live_commonbiz')
}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.alivc.live.baselive_pull_rts">
<application>
<activity android:name=".InputRtsUrlActivity"
android:alwaysRetainTaskState="true"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/AVLiveTheme"/>
<activity
android:name=".RtsPlayActivity"
android:alwaysRetainTaskState="true"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/AVLiveTheme" />
</application>
</manifest>

View File

@@ -0,0 +1,146 @@
package com.alivc.live.baselive_pull_rts;
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 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;
/**
* URL 输入界面
*/
public class InputRtsUrlActivity extends AppCompatActivity {
private static final int REQ_CODE_PERMISSION = 0x1111;
private ImageView mBackImageView;
private EditText mUrlEditText;
private ImageView mIconImageView;
private TextView mStartPlayTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtil.translucent(this, Color.TRANSPARENT);
setContentView(R.layout.activity_input_rts_url);
initView();
initListener();
}
private void initView() {
mBackImageView = findViewById(R.id.iv_back);
mUrlEditText = findViewById(R.id.et_url);
mIconImageView = findViewById(R.id.iv_icon);
mStartPlayTextView = findViewById(R.id.tv_start_play);
}
private void initListener() {
mBackImageView.setOnClickListener(view -> finish());
mUrlEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable editable) {
changeState();
}
});
mStartPlayTextView.setOnClickListener(view -> {
String url = mUrlEditText.getText().toString();
if (!urlEditTextIsEmpty()) {
Intent intent = new Intent(InputRtsUrlActivity.this,RtsPlayActivity.class);
intent.putExtra("rts_url",url);
startActivity(intent);
}
});
//二维码扫描
mIconImageView.setOnClickListener(view -> {
if (urlEditTextIsEmpty()) {
if (ContextCompat.checkSelfPermission(InputRtsUrlActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// Do not have the permission of camera, request it.
ActivityCompat.requestPermissions(InputRtsUrlActivity.this, new String[]{Manifest.permission.CAMERA}, REQ_CODE_PERMISSION);
} else {
// Have gotten the permission
startCaptureActivityForResult();
}
} else {
mUrlEditText.setText("");
}
});
}
private void changeState() {
if (urlEditTextIsEmpty()) {
mIconImageView.setImageResource(R.drawable.scan_icon);
mStartPlayTextView.setTextColor(getResources().getColor(R.color.text_ultraweak));
mStartPlayTextView.setBackgroundResource(R.drawable.shape_rts_rect_enable_blue);
} else {
mIconImageView.setImageResource(R.drawable.ic_close);
mStartPlayTextView.setTextColor(getResources().getColor(R.color.text_strong));
mStartPlayTextView.setBackgroundResource(R.drawable.shape_rts_rect_unable_blue);
}
}
private boolean urlEditTextIsEmpty() {
return TextUtils.isEmpty(mUrlEditText.getText().toString());
}
private void startCaptureActivityForResult() {
Intent intent = new Intent(InputRtsUrlActivity.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);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CaptureActivity.REQ_CODE) {
switch (resultCode) {
case RESULT_OK:
if (mUrlEditText != null) {
mUrlEditText.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
}
break;
case RESULT_CANCELED:
if (data != null && mUrlEditText != null) {
// for some reason camera is not working correctly
mUrlEditText.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
}
break;
default:
break;
}
}
}
}

View File

@@ -0,0 +1,160 @@
package com.alivc.live.baselive_pull_rts;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.alivc.live.commonui.utils.StatusBarUtil;
import java.util.Locale;
/**
* 播放界面
*/
public class RtsPlayActivity extends AppCompatActivity {
private static final String TAG = "RtsPlayActivity";
private RtsPlayer mRtsPlayer;
private RadioGroup mRadioGroup;
private TextView mTraceIdTextView;
private ImageView mBackImageView;
private SurfaceView mSurfaceView;
private TextView mErrorTextView;
private LinearLayout mMaskLinearLayout;
private TextView mDemoteTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置屏幕常亮
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
StatusBarUtil.translucent(this, Color.TRANSPARENT);
setContentView(R.layout.activity_rts_play);
mRtsPlayer = new RtsPlayer(this);
String mRtsUrl = getIntent().getStringExtra("rts_url");
initView();
initListener();
mRtsPlayer.setDataSource(mRtsUrl);
mRtsPlayer.prepare();
setRadioGroupEnabled(false);
}
private void initView() {
mBackImageView = findViewById(R.id.iv_back);
mErrorTextView = findViewById(R.id.tv_error);
mRadioGroup = findViewById(R.id.radio_group);
mDemoteTextView = findViewById(R.id.tv_demote);
mMaskLinearLayout = findViewById(R.id.ll_mask);
mSurfaceView = findViewById(R.id.surface_view);
mTraceIdTextView = findViewById(R.id.tv_trace_id);
}
private void initListener() {
mBackImageView.setOnClickListener(view -> finish());
mRadioGroup.setOnCheckedChangeListener((radioGroup, checkedId) -> {
if (checkedId == R.id.rb_play) {
mRtsPlayer.prepare();
setRadioGroupEnabled(false);
} else {
mRtsPlayer.stop();
}
});
//show traceId
mTraceIdTextView.setOnClickListener(view -> showTraceIdInfo());
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
mRtsPlayer.setSurface(surfaceHolder);
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
mRtsPlayer.surfaceChanged();
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
mRtsPlayer.setSurface(null);
}
});
mRtsPlayer.setRtsPlayerListener(new RtsPlayer.RtsPlayerListener() {
@Override
public void onFirstFrameRender() {
mErrorTextView.setText("");
mMaskLinearLayout.setVisibility(View.GONE);
setRadioGroupEnabled(true);
}
@Override
public void onPlayerError(String msg, int code) {
Log.e(TAG, "onPlayerError: " + msg + " --- " + code);
setRadioGroupEnabled(true);
}
@Override
public void onRtsMsg(String msg, int code, boolean showDemoted) {
showRtsMsg(msg, code, showDemoted);
setRadioGroupEnabled(true);
}
});
}
private void showTraceIdInfo() {
RtsTraceIdInfoView rtsTraceIdInfoView = new RtsTraceIdInfoView(this);
if (mRtsPlayer != null) {
rtsTraceIdInfoView.setTraceId(mRtsPlayer.getTraceId());
rtsTraceIdInfoView.setUrl(mRtsPlayer.getUrl());
}
}
//Rts 事件通知
private void showRtsMsg(String msg, int code, boolean showDemoted) {
mRadioGroup.check(R.id.rb_stop);
if (mMaskLinearLayout.getVisibility() == View.GONE) {
mMaskLinearLayout.setVisibility(View.VISIBLE);
}
//降级文案显示、隐藏
mDemoteTextView.setVisibility(showDemoted ? View.VISIBLE : View.GONE);
mErrorTextView.setText(String.format(Locale.getDefault(), "%d,%s", code, msg));
}
private void setRadioGroupEnabled(boolean enable) {
for (int i = 0; i < mRadioGroup.getChildCount(); i++) {
mRadioGroup.getChildAt(i).setEnabled(enable);
}
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mRtsPlayer != null) {
mRtsPlayer.stop();
mRtsPlayer.release();
}
}
}

View File

@@ -0,0 +1,279 @@
package com.alivc.live.baselive_pull_rts;
import android.content.Context;
import android.view.SurfaceHolder;
import com.aliyun.player.AliPlayer;
import com.aliyun.player.AliPlayerFactory;
import com.aliyun.player.IPlayer;
import com.aliyun.player.bean.InfoCode;
import com.aliyun.player.nativeclass.PlayerConfig;
import com.aliyun.player.source.UrlSource;
import com.cicada.player.utils.Logger;
import com.alivc.live.commonbiz.BuildConfig;
/**
* RTS 播放
*/
public class RtsPlayer {
static {
if(BuildConfig.MTL_BUILD_FOR_AIO) {
System.loadLibrary("all_in_one");
} else {
System.loadLibrary("RtsSDK");
}
}
private static final int TRACE_ID_CODE = 104;
private final AliPlayer mRtsAliPlayer;
private String mUrl;
private String mTraceId;
private RtsPlayerListener mRtsPlayerListener;
private int mCurrentPlayerState;
private boolean mEnableRetry = true;
public RtsPlayer(Context context) {
//开启日志
Logger.getInstance(context).enableConsoleLog(true);
Logger.getInstance(context).setLogLevel(Logger.LogLevel.AF_LOG_LEVEL_TRACE);
mRtsAliPlayer = AliPlayerFactory.createAliPlayer(context);
//自动播放
mRtsAliPlayer.setAutoPlay(true);
mRtsAliPlayer.setOnInfoListener(infoBean -> {
if (infoBean.getCode() == InfoCode.DirectComponentMSG) {
String extraMsg = infoBean.getExtraMsg();
parseDirectComponentMSG(extraMsg);
}
});
mRtsAliPlayer.setOnStateChangedListener((newState) -> {
mCurrentPlayerState = newState;
});
mRtsAliPlayer.setOnRenderingStartListener(() -> {
if (mRtsPlayerListener != null) {
mRtsPlayerListener.onFirstFrameRender();
}
});
mRtsAliPlayer.setOnErrorListener(errorInfo -> {
if (mRtsPlayerListener != null) {
mRtsPlayerListener.onPlayerError(errorInfo.getMsg(), errorInfo.getCode().getValue());
}
});
}
/**
* 给播放器设置 Surface
*/
public void setSurface(SurfaceHolder surface) {
mRtsAliPlayer.setDisplay(surface);
}
/**
* 设置播放源
*/
public void setDataSource(String url) {
this.mUrl = url;
UrlSource urlSource = new UrlSource();
urlSource.setUri(mUrl);
PlayerConfig config = mRtsAliPlayer.getConfig();
//播放器配置
if (mUrl.startsWith("artc://")) {
config.mMaxDelayTime = 1000;
config.mHighBufferDuration = 10;
config.mStartBufferDuration = 10;
} else {
config.mMaxDelayTime = 10000;
config.mHighBufferDuration = 100;
config.mStartBufferDuration = 100;
}
mRtsAliPlayer.setConfig(config);
mRtsAliPlayer.setDataSource(urlSource);
}
/**
* 准备播放
*/
public void prepare() {
mRtsAliPlayer.prepare();
}
public void surfaceChanged() {
mRtsAliPlayer.surfaceChanged();
}
public void stop() {
mRtsAliPlayer.stop();
}
public void release() {
mUrl = null;
mRtsAliPlayer.release();
}
/**
* 解析 Rts 事件
*/
private void parseDirectComponentMSG(String msg) {
if (msg.contains("code=" + RtsError.E_DNS_FAIL.getCode()) || msg.contains("code=" + RtsError.E_AUTH_FAIL.getCode())
|| msg.contains("code=" + RtsError.E_CONN_TIMEOUT.getCode()) || msg.contains("code=" + RtsError.E_SUB_TIMEOUT.getCode())
|| msg.contains("code=" + RtsError.E_SUB_NO_STREAM.getCode()) || msg.contains("code=" + RtsError.E_STREAM_BROKEN.getCode())
|| msg.contains("code=" + RtsError.E_RECV_STOP_SIGNAL.getCode())) {
//不是播放状态,降级
if (mCurrentPlayerState != IPlayer.started) {
willBeDemoted();
} else {
//播放状态,收到 STREAM_BROKEN 事件并且未重试,则重试
if (msg.contains("code=" + RtsError.E_STREAM_BROKEN.getCode()) && mEnableRetry) {
retry();
} else {
parseError(msg);
//除 stop 信令以外的其他失败消息,才会降级
if (!msg.contains("code=" + RtsError.E_RECV_STOP_SIGNAL.getCode())) {
willBeDemoted();
}
}
}
} else if (msg.contains("code=" + TRACE_ID_CODE)) {
parseTraceId(msg);
}
}
/**
* 重试
*/
private void retry() {
prepare();
mEnableRetry = false;
}
/**
* 降级策略
*/
private void willBeDemoted() {
stop();
if (mUrl.startsWith("artc://")) {
setDataSource(mUrl.replace("artc://", "rtmp://"));
prepare();
}
}
/**
* 解析 Rts 事件,并通知上层监听
*/
private void parseError(String msg) {
if (mRtsPlayerListener != null) {
if (msg.contains("code=" + RtsError.E_DNS_FAIL.getCode())) {
mRtsPlayerListener.onRtsMsg(RtsError.E_DNS_FAIL.name(), RtsError.E_DNS_FAIL.getCode(), true);
} else if (msg.contains("code=" + RtsError.E_AUTH_FAIL.getCode())) {
mRtsPlayerListener.onRtsMsg(RtsError.E_AUTH_FAIL.name(), RtsError.E_AUTH_FAIL.getCode(), true);
} else if (msg.contains("code=" + RtsError.E_CONN_TIMEOUT.getCode())) {
mRtsPlayerListener.onRtsMsg(RtsError.E_CONN_TIMEOUT.name(), RtsError.E_CONN_TIMEOUT.getCode(), true);
} else if (msg.contains("code=" + RtsError.E_SUB_TIMEOUT.getCode())) {
mRtsPlayerListener.onRtsMsg(RtsError.E_SUB_TIMEOUT.name(), RtsError.E_SUB_TIMEOUT.getCode(), true);
} else if (msg.contains("code=" + RtsError.E_SUB_NO_STREAM.getCode())) {
mRtsPlayerListener.onRtsMsg(RtsError.E_SUB_NO_STREAM.name(), RtsError.E_SUB_NO_STREAM.getCode(), true);
} else if (msg.contains("code=" + RtsError.E_STREAM_BROKEN.getCode())) {
mRtsPlayerListener.onRtsMsg(RtsError.E_STREAM_BROKEN.name(), RtsError.E_STREAM_BROKEN.getCode(), true);
} else if (msg.contains("code=" + RtsError.E_RECV_STOP_SIGNAL.getCode())) {
mRtsPlayerListener.onRtsMsg(RtsError.E_RECV_STOP_SIGNAL.name(), RtsError.E_RECV_STOP_SIGNAL.getCode(), false);
}
}
}
/**
* 解析 TraceId
*/
private void parseTraceId(String msg) {
String[] split = msg.split("-sub-");
if (split.length >= 1) {
mTraceId = "RequestId:" + (split[1].substring(0, split[1].length() - 1));
mTraceId = mTraceId.replace("\"", "").replace("\\", "");
}
}
/**
* 获取 TraceId
*/
public String getTraceId() {
return mTraceId;
}
/**
* 获取 URL
*/
public String getUrl() {
return mUrl;
}
public void setRtsPlayerListener(RtsPlayerListener listener) {
this.mRtsPlayerListener = listener;
}
public interface RtsPlayerListener {
/**
* 首帧显示回调
*/
void onFirstFrameRender();
/**
* 播放器报错
*/
void onPlayerError(String msg, int code);
/**
* Rts 事件
*/
void onRtsMsg(String msg, int code, boolean showDemoted);
}
public enum RtsError {
/**
* DNS 解析失败
*/
E_DNS_FAIL(20001),
/**
* 鉴权失败
*/
E_AUTH_FAIL(20002),
/**
* 建联信令超时
*/
E_CONN_TIMEOUT(20011),
/**
* 订阅信令返回错误,或者超时。
*/
E_SUB_TIMEOUT(20012),
/**
* 订阅流不存在
*/
E_SUB_NO_STREAM(20013),
/**
* 媒体超时,没有收到音频包和视频包
*/
E_STREAM_BROKEN(20052),
/**
* 收到CDN的stop信令
*/
E_RECV_STOP_SIGNAL(20061);
private int code;
RtsError(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
}

View File

@@ -0,0 +1,89 @@
package com.alivc.live.baselive_pull_rts;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.text.TextUtils;
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 androidx.constraintlayout.widget.Group;
import com.alivc.live.commonui.avdialog.AUILiveDialog;
import com.alivc.live.commonutils.ToastUtils;
public class RtsTraceIdInfoView extends ConstraintLayout {
private final View inflate;
private Group mGroup;
private TextView mTipsTextView;
private TextView mTraceIdTextView;
private TextView mCopyTextView;
private TextView mCancelTextView;
private AUILiveDialog mAUILiveDialog;
private final ClipboardManager mClipboardManager;
private String mUrl;
private String mTraceId;
public RtsTraceIdInfoView(@NonNull Context context) {
this(context, null);
}
public RtsTraceIdInfoView(@NonNull Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public RtsTraceIdInfoView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate = LayoutInflater.from(context).inflate(R.layout.layout_rts_traceid_info, this, true);
mClipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
initView();
initListener();
}
private void initView() {
mAUILiveDialog = new AUILiveDialog(getContext());
mAUILiveDialog.setContentView(this);
mGroup = inflate.findViewById(R.id.group);
mTipsTextView = inflate.findViewById(R.id.tv_tips);
mTraceIdTextView = inflate.findViewById(R.id.tv_trace_id);
mCopyTextView = inflate.findViewById(R.id.tv_copy);
mCancelTextView = inflate.findViewById(R.id.tv_cancel);
}
private void initListener() {
mCancelTextView.setOnClickListener(view -> mAUILiveDialog.dismiss());
mCopyTextView.setOnClickListener(view -> {
mAUILiveDialog.dismiss();
//复制
ClipData mClipData = ClipData.newPlainText("Label", mTraceId + ";" + mUrl);
mClipboardManager.setPrimaryClip(mClipData);
ToastUtils.show(getContext().getString(R.string.pull_rts_trace_id_info_copy_success));
});
}
public void setTraceId(String traceId) {
if (TextUtils.isEmpty(traceId)) {
mGroup.setVisibility(View.GONE);
mTipsTextView.setText(R.string.pull_rts_trace_id_info_error);
mCancelTextView.setText(R.string.pull_rts_trace_id_info_confirm);
mTraceIdTextView.setText("");
} else {
mGroup.setVisibility(View.VISIBLE);
mTipsTextView.setText(R.string.pull_rts_trace_id_info_success);
mCancelTextView.setText(R.string.pull_rts_trace_id_info_confirm);
mTraceIdTextView.setText(traceId);
}
this.mTraceId = traceId;
mAUILiveDialog.show();
}
public void setUrl(String url) {
this.mUrl = url;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_rts_checked_blue" android:state_checked="true" />
<item android:drawable="@drawable/shape_rts_unchecked_white" android:state_checked="false" />
<item android:drawable="@drawable/shape_rts_unchecked_white"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#00BCD4" android:state_checked="true" />
<item android:color="#FCFCFD" android:state_checked="false" />
<item android:color="#FCFCFD"/>
</selector>

View File

@@ -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>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="1dp"
android:color="#00BCD4" />
<corners android:radius="16dp" />
<size android:width="48dp" android:height="24dp" />
</shape>

View File

@@ -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>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:shape="rectangle"
tools:ignore="MissingDefaultResource">
<solid android:color="#4D4DCFE1"/>
<corners android:radius="24dp" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#4DCFE1"/>
<corners android:radius="24dp" />
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#3A3D48" />
<corners android:radius="16dp" />
<size
android:width="92dp"
android:height="24dp" />
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="1dp"
android:color="#FCFCFD" />
<corners android:radius="16dp" />
<size android:width="48dp" android:height="24dp" />
</shape>

View File

@@ -0,0 +1,109 @@
<?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_title"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginTop="44dp"
android:gravity="center"
android:text="@string/pull_rts_enter_name"
android:textColor="#FCFCFD"
android:textSize="@dimen/alivc_common_font_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<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_url_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="20dp"
android:text="@string/pull_rts_url_title"
android:textColor="#FCFCFD"
android:textSize="@dimen/alivc_common_font_16"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<EditText
android:id="@+id/et_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="20dp"
android:background="@null"
android:hint="@string/pull_rts_input_hint"
android:textColor="#E6E7EC"
android:textColorHint="#747A8C"
android:textSize="@dimen/alivc_common_font_14"
app:layout_constraintEnd_toEndOf="@+id/iv_icon"
app:layout_constraintStart_toStartOf="parent"
android:theme="@style/AUIEditText"
app:layout_constraintTop_toBottomOf="@id/tv_url_title" />
<View
android:id="@+id/under_line"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:background="#3A3D48"
app:layout_constraintStart_toStartOf="@id/et_url"
app:layout_constraintEnd_toEndOf="@id/et_url"
app:layout_constraintTop_toBottomOf="@id/et_url"/>
<ImageView
android:id="@+id/iv_icon"
android:layout_width="18dp"
android:layout_height="18dp"
android:src="@drawable/scan_icon"
app:layout_constraintBottom_toBottomOf="@id/et_url"
app:layout_constraintEnd_toEndOf="@id/et_url"
app:layout_constraintTop_toTopOf="@id/et_url" />
<TextView
android:id="@+id/tv_tips"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="110dp"
android:text="@string/pull_rts_url_generate_tip"
android:textColor="#B2B7C4"
android:textSize="@dimen/alivc_common_font_12"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/under_line" />
<TextView
android:id="@+id/tv_start_play"
android:layout_width="272dp"
android:layout_height="48dp"
android:layout_marginTop="12dp"
android:background="@drawable/shape_rect_blue"
android:gravity="center"
android:text="@string/pull_rts_start_play"
android:textColor="#747A8C"
android:textSize="@dimen/alivc_common_font_18"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_tips" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -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="match_parent"
android:layout_height="match_parent"
android:background="#1C1D22">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginTop="44dp"
android:gravity="center"
android:text="@string/pull_rts_enter_name"
android:textColor="#FCFCFD"
android:textSize="@dimen/alivc_common_font_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<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" />
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="204dp"
android:layout_marginStart="20dp"
android:layout_marginTop="17dp"
android:layout_marginEnd="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<LinearLayout
android:id="@+id/ll_mask"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
android:gravity="center"
android:visibility="gone"
android:background="@color/color_background_black_alpha_30"
app:layout_constraintBottom_toBottomOf="@id/surface_view"
app:layout_constraintEnd_toEndOf="@id/surface_view"
app:layout_constraintStart_toStartOf="@id/surface_view"
app:layout_constraintTop_toTopOf="@id/surface_view">
<TextView
android:id="@+id/tv_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#F53F3F"
android:textSize="14sp"/>
<TextView
android:id="@+id/tv_demote"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#3BB346"
android:textSize="14sp"
android:layout_marginTop="10dp"
android:text="@string/pull_rts_error_demote"/>
</LinearLayout>
<RadioGroup
android:id="@+id/radio_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="13dp"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="@id/surface_view"
app:layout_constraintTop_toBottomOf="@id/surface_view">
<RadioButton
android:id="@+id/rb_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/selector_rts_play_state"
android:button="@null"
android:checked="true"
android:gravity="center"
android:text="@string/pull_rts_play"
android:textColor="@drawable/selector_rts_play_state_text"
android:textSize="@dimen/alivc_common_font_12" />
<RadioButton
android:id="@+id/rb_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:background="@drawable/selector_rts_play_state"
android:button="@null"
android:gravity="center"
android:text="@string/pull_rts_stop"
android:textColor="@drawable/selector_rts_play_state_text"
android:textSize="@dimen/alivc_common_font_12" />
</RadioGroup>
<TextView
android:id="@+id/tv_trace_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_rts_trace_id_bg"
android:gravity="center"
android:text="@string/pull_rts_trace_id"
android:textColor="#FCFCFD"
android:textSize="@dimen/alivc_common_font_12"
app:layout_constraintEnd_toEndOf="@id/surface_view"
app:layout_constraintTop_toTopOf="@id/radio_group" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="20dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="30dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/radio_group">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_question_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pull_rts_problem_title"
android:textColor="#FCFCFD"
android:textSize="@dimen/alivc_common_font_14"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/divider_1"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:background="#3A3D48"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_question_title" />
<View
android:id="@+id/divider_error"
android:layout_width="1dp"
android:layout_height="12dp"
android:layout_marginTop="15dp"
android:background="@color/colourful_ic_strong"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/divider_1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/pull_rts_problem_playback_failed"
android:textColor="#FCFCFD"
android:textSize="@dimen/alivc_common_font_12"
app:layout_constraintBottom_toBottomOf="@id/divider_error"
app:layout_constraintStart_toEndOf="@id/divider_error"
app:layout_constraintTop_toTopOf="@id/divider_error" />
<TextView
android:id="@+id/tv_error_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/pull_rts_problem_playback_failed_tip"
android:textColor="#B2B7C4"
android:textSize="@dimen/alivc_common_font_12"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/divider_error" />
<View
android:id="@+id/divider_lag"
android:layout_width="1dp"
android:layout_height="12dp"
android:layout_marginTop="27dp"
android:background="@color/colourful_ic_strong"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_error_msg" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/pull_rts_problem_stuck_delay"
android:textColor="#FCFCFD"
android:textSize="@dimen/alivc_common_font_12"
app:layout_constraintBottom_toBottomOf="@id/divider_lag"
app:layout_constraintStart_toEndOf="@id/divider_lag"
app:layout_constraintTop_toTopOf="@id/divider_lag" />
<TextView
android:id="@+id/tv_step_1_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/pull_rts_problem_stuck_delay_step1_title"
android:textColor="#E6E7EC"
android:textSize="@dimen/alivc_common_font_12"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/divider_lag" />
<TextView
android:id="@+id/tv_step_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/pull_rts_problem_stuck_delay_step1"
android:textColor="#B2B7C4"
android:textSize="@dimen/alivc_common_font_12"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_step_1_title" />
<TextView
android:id="@+id/tv_step_2_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/pull_rts_problem_stuck_delay_step2_title"
android:textColor="#E6E7EC"
android:textSize="@dimen/alivc_common_font_12"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_step_1" />
<TextView
android:id="@+id/tv_step_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/pull_rts_problem_stuck_delay_step2"
android:textColor="#B2B7C4"
android:textSize="@dimen/alivc_common_font_12"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_step_2_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,77 @@
<?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="wrap_content"
android:background="@drawable/shape_rts_live_dialog_bg">
<androidx.constraintlayout.widget.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tv_copy" />
<TextView
android:id="@+id/tv_tips"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="20dp"
android:gravity="center"
android:textColor="#FCFCFD"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/tv_trace_id"/>
<TextView
android:id="@+id/tv_trace_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginStart="20dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="20dp"
android:textColor="#B2B7C4"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_tips"
app:layout_constraintBottom_toTopOf="@id/tv_copy"/>
<TextView
android:id="@+id/tv_copy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="24dp"
android:text="@string/pull_rts_trace_id_copy"
android:textColor="#00BCD4"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/view_horizontal_line"
app:layout_constraintStart_toStartOf="@id/tv_tips"
app:layout_constraintTop_toBottomOf="@id/tv_trace_id" />
<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:textColor="#B2B7C4"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Rts -->
<string name="pull_rts_enter_name">Rts Live Streaming</string>
<string name="pull_rts_url_title">URL</string>
<string name="pull_rts_input_hint">Please enter RTS ultra-low delay playback address</string>
<string name="pull_rts_url_generate_tip">The playback address can be generated by the address generator in the live video console</string>
<string name="pull_rts_start_play">Start playing</string>
<string name="pull_rts_play">Play</string>
<string name="pull_rts_stop">Stop</string>
<string name="pull_rts_trace_id">TraceID acquisition</string>
<string name="pull_rts_problem_title">Common Problem</string>
<string name="pull_rts_problem_playback_failed">Playback Failed</string>
<string name="pull_rts_problem_playback_failed_tip">Please go to the live video console>Toolbox>Self service problem troubleshooting, and enter the URL to locate the problem of playback failure</string>
<string name="pull_rts_problem_stuck_delay">Play stuck / high delay</string>
<string name="pull_rts_problem_stuck_delay_step1_title">step1</string>
<string name="pull_rts_problem_stuck_delay_step1">Please go to Live Video Console>Stream Management>Stream Detection to analyze whether your current streaming network environment is good (whether the frame rate or timestamp is normal)</string>
<string name="pull_rts_problem_stuck_delay_step2_title">step2</string>
<string name="pull_rts_problem_stuck_delay_step2">If your streaming network is good, please click [TraceID Acquisition] to obtain relevant information and submit a work order for help</string>
<string name="pull_rts_trace_id_copy">Copy</string>
<string name="pull_rts_trace_id_info_confirm">Confirm</string>
<string name="pull_rts_trace_id_info_close">Close</string>
<string name="pull_rts_trace_id_info_error">The network connection is not successful, and the TraceID information is not currently available</string>
<string name="pull_rts_trace_id_info_success">If you encounter problems when experiencing Demo, please submit the following information to the after-sales service in the form of work order</string>
<string name="pull_rts_trace_id_info_copy_success">Information copied</string>
<string name="pull_rts_error_demote">Demote</string>
</resources>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Rts -->
<string name="pull_rts_enter_name">超低延时直播</string>
<string name="pull_rts_url_title">播放地址</string>
<string name="pull_rts_input_hint">请输入RTS超低延时播放地址</string>
<string name="pull_rts_url_generate_tip">播放地址可到视频直播控制台用地址生成器生成</string>
<string name="pull_rts_start_play">开始播放</string>
<string name="pull_rts_play">播放</string>
<string name="pull_rts_stop">停止</string>
<string name="pull_rts_trace_id">TraceID获取</string>
<string name="pull_rts_problem_title">常见问题</string>
<string name="pull_rts_problem_playback_failed">播放失败</string>
<string name="pull_rts_problem_playback_failed_tip">请前往 视频直播控制台 > 工具箱 > 自助问题排查输入URL自助定位播放失败问题</string>
<string name="pull_rts_problem_stuck_delay">播放卡顿/延时高</string>
<string name="pull_rts_problem_stuck_delay_step1_title">step1</string>
<string name="pull_rts_problem_stuck_delay_step1">请前往视频直播控制台 > 流管理 > 流检测,分析您当前的推流网络环境是否良好(帧率或时间戳是否正常)</string>
<string name="pull_rts_problem_stuck_delay_step2_title">step2</string>
<string name="pull_rts_problem_stuck_delay_step2">若您的推流网络良好请点击【TraceID获取】获取相关信息并提交工单寻求帮助</string>
<string name="pull_rts_trace_id_copy">复制</string>
<string name="pull_rts_trace_id_info_confirm">确认</string>
<string name="pull_rts_trace_id_info_close">关闭</string>
<string name="pull_rts_trace_id_info_error">网络建联不成功当前未获取到TraceID信息</string>
<string name="pull_rts_trace_id_info_success">若您在体验Demo时碰到问题请将以下信息通过工单的形式提交给售后</string>
<string name="pull_rts_trace_id_info_copy_success">信息已复制</string>
<string name="pull_rts_error_demote">降级</string>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="alivc_common_font_12">12sp</dimen>
<dimen name="alivc_common_font_14">14sp</dimen>
<dimen name="alivc_common_font_16">16sp</dimen>
<dimen name="alivc_common_font_18">18sp</dimen>
</resources>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Rts -->
<string name="pull_rts_enter_name">Rts Live Streaming</string>
<string name="pull_rts_url_title">URL</string>
<string name="pull_rts_input_hint">Please enter RTS ultra-low delay playback address</string>
<string name="pull_rts_url_generate_tip">The playback address can be generated by the address generator in the live video console</string>
<string name="pull_rts_start_play">Start playing</string>
<string name="pull_rts_play">Play</string>
<string name="pull_rts_stop">Stop</string>
<string name="pull_rts_trace_id">TraceID acquisition</string>
<string name="pull_rts_problem_title">Common Problem</string>
<string name="pull_rts_problem_playback_failed">Playback Failed</string>
<string name="pull_rts_problem_playback_failed_tip">Please go to the live video console>Toolbox>Self service problem troubleshooting, and enter the URL to locate the problem of playback failure</string>
<string name="pull_rts_problem_stuck_delay">Play stuck / high delay</string>
<string name="pull_rts_problem_stuck_delay_step1_title">step1</string>
<string name="pull_rts_problem_stuck_delay_step1">Please go to Live Video Console>Stream Management>Stream Detection to analyze whether your current streaming network environment is good (whether the frame rate or timestamp is normal)</string>
<string name="pull_rts_problem_stuck_delay_step2_title">step2</string>
<string name="pull_rts_problem_stuck_delay_step2">If your streaming network is good, please click [TraceID Acquisition] to obtain relevant information and submit a work order for help</string>
<string name="pull_rts_trace_id_copy">Copy</string>
<string name="pull_rts_trace_id_info_confirm">Confirm</string>
<string name="pull_rts_trace_id_info_close">Close</string>
<string name="pull_rts_trace_id_info_error">The network connection is not successful, and the TraceID information is not currently available</string>
<string name="pull_rts_trace_id_info_success">If you encounter problems when experiencing Demo, please submit the following information to the after-sales service in the form of work order</string>
<string name="pull_rts_trace_id_info_copy_success">Information copied</string>
<string name="pull_rts_error_demote">Demote</string>
</resources>

1
LiveBasic/live_push/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,40 @@
plugins {
id 'com.android.library'
}
android {
compileSdkVersion androidCompileSdkVersion
buildToolsVersion androidBuildToolsVersion
defaultConfig {
minSdkVersion androidMinSdkVersion
targetSdkVersion androidTargetSdkVersion
versionCode 1
versionName "1.0"
consumerProguardFiles "consumer-rules.pro"
}
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
// 音频智能降噪组件库如果需要使用pusher里面的音频智能降噪功能需集成此依赖库否则调用相关接口将会失效
implementation 'com.alivc.live.component:intelligentdenoise:1.0.0'
implementation project(':LiveCommon:live_commonbiz')
implementation project(':LiveBeauty:live_queenbeauty')
}

View File

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.alivc.live.baselive_push">
<application>
<activity
android:name=".ui.PushConfigActivity"
android:alwaysRetainTaskState="true"
android:configChanges="uiMode"
android:screenOrientation="portrait"
android:theme="@style/AppThemePlayer" />
<activity
android:name=".ui.LivePushActivity"
android:alwaysRetainTaskState="true"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode"
android:exported="false"
android:theme="@style/AppThemePlayer" />
</application>
</manifest>

View File

@@ -0,0 +1,12 @@
package com.alivc.live.baselive_push.adapter;
import android.view.SurfaceView;
import com.alivc.live.baselive_push.ui.LivePushActivity;
import com.alivc.live.pusher.AlivcLivePusher;
public interface IPushController {
public AlivcLivePusher getLivePusher();
public LivePushActivity.PauseState getPauseStateListener();
public SurfaceView getPreviewView();
}

View File

@@ -0,0 +1,120 @@
package com.alivc.live.baselive_push.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.alivc.live.commonui.bean.MusicInfo;
import com.alivc.live.baselive_push.R;
import java.io.File;
import java.util.ArrayList;
public class MusicSelectAdapter extends RecyclerView.Adapter<MusicSelectAdapter.MusicViewHolder> {
private static final String BGM_ASSETS_PATH = "alivc_resource/BGM/";
private static final String NETWORK_BGM_URL = "http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/51991/cn_zh/1511776743437/JUST%202017.mp3";
private final ArrayList<MusicInfo> sBGMList = new ArrayList<>();
private OnItemClick mOnItemClick = null;
private int mPosition = 0;
public MusicSelectAdapter(Context context) {
MusicInfo info = new MusicInfo(context.getResources().getString(R.string.no_music), "", "", "");
sBGMList.add(info);
ArrayList<MusicInfo> list = getMusicInfoResources(context);
sBGMList.addAll(list);
MusicInfo info1 = new MusicInfo(context.getResources().getString(R.string.internet_music), "", "", NETWORK_BGM_URL);
sBGMList.add(info1);
}
private static ArrayList<MusicInfo> getMusicInfoResources(Context context) {
ArrayList<MusicInfo> musicInfos = new ArrayList<>();
String bgmDirectoryPath = context.getFilesDir() + File.separator + BGM_ASSETS_PATH;
File bgmDirectory = new File(bgmDirectoryPath);
if (bgmDirectory.isDirectory()) {
File[] bgmFiles = bgmDirectory.listFiles((dir, name) -> name.endsWith(".mp3"));
if (bgmFiles != null) {
for (File file : bgmFiles) {
MusicInfo musicInfo = new MusicInfo();
musicInfo.setMusicName(file.getName());
musicInfo.setPath(file.getAbsolutePath());
musicInfos.add(musicInfo);
}
}
}
return musicInfos;
}
@Override
public MusicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.music_select_item_info, parent, false);
MusicViewHolder holder = new MusicViewHolder(itemView);
holder.tvMusicName = (TextView) itemView.findViewById(R.id.music_name);
holder.tvMusicCheck = (ImageView) itemView.findViewById(R.id.music_check);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnItemClick != null) {
mOnItemClick.onItemClick(sBGMList.get(holder.getAdapterPosition()), holder.getAdapterPosition());
}
int lastPosition = mPosition;
mPosition = holder.getAdapterPosition();
notifyItemChanged(lastPosition);
notifyItemChanged(mPosition);
}
});
return holder;
}
@Override
public void onBindViewHolder(final MusicViewHolder holder, final int position) {
MusicInfo musicInfo = sBGMList.get(position);
if (mPosition == position) {
holder.tvMusicCheck.setVisibility(View.VISIBLE);
} else {
holder.tvMusicCheck.setVisibility(View.GONE);
}
if (musicInfo != null) {
holder.tvMusicName.setText(musicInfo.getMusicName());
}
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return sBGMList.size();
}
static class MusicViewHolder extends RecyclerView.ViewHolder {
TextView tvMusicName;
ImageView tvMusicCheck;
public MusicViewHolder(View itemView) {
super(itemView);
}
}
public void setOnItemClick(OnItemClick onItemClick) {
mOnItemClick = onItemClick;
}
public interface OnItemClick {
void onItemClick(MusicInfo musicInfo, int position);
}
}

View File

@@ -0,0 +1,7 @@
package com.alivc.live.baselive_push.adapter;
public interface OnSoundEffectChangedListener {
void onSoundEffectChangeVoiceModeSelected(int position);
void onSoundEffectRevertBSelected(int position);
}

View File

@@ -0,0 +1,95 @@
package com.alivc.live.baselive_push.adapter;
import android.content.Context;
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.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import com.alivc.live.baselive_push.R;
import com.alivc.live.baselive_push.bean.SoundEffectBean;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class SoundEffectRecyclerViewAdapter extends RecyclerView.Adapter<SoundEffectRecyclerViewAdapter.SoundEffectViewHolder> {
private final Map<Integer, SoundEffectBean> mDataMap;
private int mSelectIndex = 0;
private OnSoundEffectItemClickListener mOnSoundEffectItemClickListener;
private final int mNormalColor;
private final int mSelectColor;
public SoundEffectRecyclerViewAdapter(Context context, Map<Integer, SoundEffectBean> data) {
this.mDataMap = data;
mNormalColor = context.getResources().getColor(R.color.camera_panel_content);
mSelectColor = context.getResources().getColor(R.color.colorBaseStyle);
}
@NonNull
@NotNull
@Override
public SoundEffectViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_sound_effect_recycler_view, parent, false);
return new SoundEffectViewHolder(inflate);
}
@Override
public void onBindViewHolder(@NonNull @NotNull SoundEffectViewHolder holder, int position) {
SoundEffectBean soundEffectBean = mDataMap.get(position);
if (soundEffectBean != null) {
holder.mSoundEffectTitle.setText(soundEffectBean.getDescriptionId());
holder.mIconImageView.setImageResource(soundEffectBean.getIconId());
if (mSelectIndex == position) {
holder.mIconImageView.setColorFilter(mSelectColor);
holder.mSoundEffectTitle.setTextColor(mSelectColor);
} else {
holder.mIconImageView.setColorFilter(mNormalColor);
holder.mSoundEffectTitle.setTextColor(mNormalColor);
}
}
}
@Override
public int getItemCount() {
return mDataMap == null ? 0 : mDataMap.keySet().size();
}
public void setSelectIndex(int index) {
this.mSelectIndex = index;
notifyDataSetChanged();
}
public class SoundEffectViewHolder extends RecyclerView.ViewHolder {
private final TextView mSoundEffectTitle;
private final ImageView mIconImageView;
public SoundEffectViewHolder(@NonNull @NotNull View itemView) {
super(itemView);
ConstraintLayout mRootView = itemView.findViewById(R.id.item_root);
mSoundEffectTitle = itemView.findViewById(R.id.item_sound_effect_title);
mIconImageView = itemView.findViewById(R.id.iv_icon);
mRootView.setOnClickListener(view -> {
if (mOnSoundEffectItemClickListener != null && mSelectIndex != getAdapterPosition()) {
mOnSoundEffectItemClickListener.onSoundEffectItemClick(getAdapterPosition());
}
});
}
}
public interface OnSoundEffectItemClickListener {
void onSoundEffectItemClick(int position);
}
public void setOnSoundEffectItemClickListener(OnSoundEffectItemClickListener listener) {
this.mOnSoundEffectItemClickListener = listener;
}
}

View File

@@ -0,0 +1,90 @@
package com.alivc.live.baselive_push.bean;
import android.text.TextUtils;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* json解析工具类 其实对于数组解析有一些问题
* @author
*/
public class GsonUtils {
public static Gson gson = new Gson();
/**
* 返回List对象
* @param str
* @param type new TypeToken<ArrayList<T>>(){}.getType()
* @param <T>
* @return
*/
public static <T> T getListFromJSON(String str, Type type) {
if (!TextUtils.isEmpty(str)) {
return gson.fromJson(str, type);
}
return null;
}
/**
* 返回List对象
* @param str
* @param cls
* @param <T>
* @return
*/
public static <T> List<T> getListFromJSON(String str, Class<T> cls)
{
Type type = new TypeToken<ArrayList<JsonObject>>()
{}.getType();
ArrayList<JsonObject> jsonObjects = gson.fromJson(str, type);
ArrayList<T> arrayList = new ArrayList<>();
for (JsonObject jsonObject : jsonObjects)
{
arrayList.add(gson.fromJson(jsonObject, cls));
}
return arrayList;
}
/**
* 返回对象
* @param str
* @param cls
* @param <T>
* @return
*/
public static <T> T getObjFromJSON(String str, Class<T> cls) {
// try {
if (!TextUtils.isEmpty(str)) {
return gson.fromJson(str, cls);
}
return null;
// }catch (Exception e) {
// return null;
// }
}
/**
* 返回JsonString
* @return
*/
public static String beanToJSONString(Object bean) {
return new Gson().toJson(bean);
}
public static String JSONTokener(String in) {
// consume an optional byte order mark (BOM) if it exists
if (in != null && in.startsWith("\ufeff")) {
in = in.substring(1);
}
return in;
}
}

View File

@@ -0,0 +1,106 @@
package com.alivc.live.baselive_push.bean;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.StringRes;
import com.alivc.live.baselive_push.R;
import com.alivc.live.pusher.AlivcLivePushAudioEffectReverbMode;
import com.alivc.live.pusher.AlivcLivePushAudioEffectVoiceChangeMode;
import java.io.Serializable;
import java.util.HashMap;
public class SoundEffectBean implements Serializable {
//icon drawable resId
private int iconId;
//description string resId
private int descriptionId;
private String name;
public SoundEffectBean() {
}
public SoundEffectBean(@StringRes int descriptionId, String name) {
this.descriptionId = descriptionId;
this.name = name;
}
public SoundEffectBean(@DrawableRes int iconId, @StringRes int descriptionId, String name) {
this.iconId = iconId;
this.descriptionId = descriptionId;
this.name = name;
}
public int getIconId() {
return iconId;
}
public void setIconId(@IdRes int iconId) {
this.iconId = iconId;
}
public int getDescriptionId() {
return descriptionId;
}
public void setDescriptionId(@StringRes int descriptionId) {
this.descriptionId = descriptionId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 音效
*/
public static class SoundEffectChangeVoiceBean {
private static final HashMap<Integer, SoundEffectBean> mLivePushSoundEffectChangeVoice = new HashMap<>();
static {
mLivePushSoundEffectChangeVoice.put(0, new SoundEffectBean(R.drawable.ic_live_push_sound_effect_off, R.string.sound_effect_changevoice_off, AlivcLivePushAudioEffectVoiceChangeMode.SOUND_EFFECT_OFF.name()));
mLivePushSoundEffectChangeVoice.put(1, new SoundEffectBean(R.drawable.ic_live_push_sound_effect_oldman, R.string.sound_effect_changevoice_oldman, AlivcLivePushAudioEffectVoiceChangeMode.SOUND_EFFECT_OLD_MAN.name()));
mLivePushSoundEffectChangeVoice.put(2, new SoundEffectBean(R.drawable.ic_live_push_sound_effect_babyboy, R.string.sound_effect_changevoice_babyboy, AlivcLivePushAudioEffectVoiceChangeMode.SOUND_EFFECT_BABY_BOY.name()));
mLivePushSoundEffectChangeVoice.put(3, new SoundEffectBean(R.drawable.ic_live_push_sound_effect_babygirl, R.string.sound_effect_changevoice_babygirl, AlivcLivePushAudioEffectVoiceChangeMode.SOUND_EFFECT_BABY_GIRL.name()));
mLivePushSoundEffectChangeVoice.put(4, new SoundEffectBean(R.drawable.ic_live_push_sound_effect_robot, R.string.sound_effect_changevoice_robot, AlivcLivePushAudioEffectVoiceChangeMode.SOUND_EFFECT_ROBOT.name()));
mLivePushSoundEffectChangeVoice.put(5, new SoundEffectBean(R.drawable.ic_live_push_sound_effect_daimo, R.string.sound_effect_changevoice_daimo, AlivcLivePushAudioEffectVoiceChangeMode.SOUND_EFFECT_DEMON.name()));
mLivePushSoundEffectChangeVoice.put(6, new SoundEffectBean(R.drawable.ic_live_push_sound_effect_ktv, R.string.sound_effect_changevoice_ktv, AlivcLivePushAudioEffectVoiceChangeMode.SOUND_EFFECT_KTV.name()));
mLivePushSoundEffectChangeVoice.put(7, new SoundEffectBean(R.drawable.ic_live_push_sound_effect_echo, R.string.sound_effect_changevoice_echo, AlivcLivePushAudioEffectVoiceChangeMode.SOUND_EFFECT_ECHO.name()));
}
public static HashMap<Integer, SoundEffectBean> getLivePushSoundEffectChangeVoice() {
return mLivePushSoundEffectChangeVoice;
}
}
/**
* 混响
*/
public static class SoundEffectReverb {
private static final HashMap<Integer, SoundEffectBean> mLivePushSoundEffectReverb = new HashMap<>();
static {
mLivePushSoundEffectReverb.put(0, new SoundEffectBean(R.string.sound_effect_reverb_off, AlivcLivePushAudioEffectReverbMode.REVERB_OFF.name()));
mLivePushSoundEffectReverb.put(1, new SoundEffectBean(R.string.sound_effect_reverb_vocal1, AlivcLivePushAudioEffectReverbMode.REVERB_VOCAL_I.name()));
mLivePushSoundEffectReverb.put(2, new SoundEffectBean(R.string.sound_effect_reverb_vocal2, AlivcLivePushAudioEffectReverbMode.REVERB_VOCAL_II.name()));
mLivePushSoundEffectReverb.put(3, new SoundEffectBean(R.string.sound_effect_reverb_bathroom, AlivcLivePushAudioEffectReverbMode.REVERB_BATHROOM.name()));
mLivePushSoundEffectReverb.put(4, new SoundEffectBean(R.string.sound_effect_reverb_smallroom_bright, AlivcLivePushAudioEffectReverbMode.REVERB_SMALL_ROOM_BRIGHT.name()));
mLivePushSoundEffectReverb.put(5, new SoundEffectBean(R.string.sound_effect_reverb_smallroom_dark, AlivcLivePushAudioEffectReverbMode.REVERB_SMALL_ROOM_DARK.name()));
mLivePushSoundEffectReverb.put(6, new SoundEffectBean(R.string.sound_effect_reverb_mediumroom, AlivcLivePushAudioEffectReverbMode.REVERB_MEDIUM_ROOM.name()));
mLivePushSoundEffectReverb.put(7, new SoundEffectBean(R.string.sound_effect_reverb_largeroom, AlivcLivePushAudioEffectReverbMode.REVERB_LARGE_ROOM.name()));
mLivePushSoundEffectReverb.put(8, new SoundEffectBean(R.string.sound_effect_reverb_churchhall, AlivcLivePushAudioEffectReverbMode.REVERB_CHURCH_HALL.name()));
}
public static HashMap<Integer, SoundEffectBean> getLivePushSoundEffectReverb() {
return mLivePushSoundEffectReverb;
}
}
}

View File

@@ -0,0 +1,534 @@
package com.alivc.live.baselive_push.ui;
import static com.alivc.live.pusher.AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_LEFT;
import static com.alivc.live.pusher.AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_RIGHT;
import static com.alivc.live.pusher.AlivcPreviewOrientationEnum.ORIENTATION_PORTRAIT;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Color;
import android.hardware.Camera;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.lifecycle.ViewModelProvider;
import androidx.viewpager.widget.ViewPager;
import com.alivc.live.annotations.AlivcLiveMode;
import com.alivc.live.baselive_push.R;
import com.alivc.live.baselive_push.adapter.IPushController;
import com.alivc.live.commonutils.NetWorkUtils;
import com.alivc.live.commonui.utils.StatusBarUtil;
import com.alivc.live.pusher.AlivcLivePushConfig;
import com.alivc.live.pusher.AlivcLivePushStatsInfo;
import com.alivc.live.pusher.AlivcLivePusher;
import com.alivc.live.pusher.AlivcPreviewOrientationEnum;
import com.alivc.live.pusher.SurfaceStatus;
import com.alivc.live.pusher.WaterMarkInfo;
import java.util.ArrayList;
import java.util.List;
public class LivePushActivity extends AppCompatActivity implements IPushController {
private static final String TAG = "LivePushActivity";
private static final int FLING_MIN_DISTANCE = 50;
private static final int FLING_MIN_VELOCITY = 0;
private final long REFRESH_INTERVAL = 1000;
private static final String URL_KEY = "url_key";
private static final String ASYNC_KEY = "async_key";
private static final String AUDIO_ONLY_KEY = "audio_only_key";
private static final String VIDEO_ONLY_KEY = "video_only_key";
private static final String ORIENTATION_KEY = "orientation_key";
private static final String CAMERA_ID = "camera_id";
private static final String FLASH_ON = "flash_on";
private static final String AUTH_TIME = "auth_time";
private static final String PRIVACY_KEY = "privacy_key";
private static final String MIX_EXTERN = "mix_extern";
private static final String MIX_MAIN = "mix_main";
private static final String BEAUTY_CHECKED = "beauty_checked";
private static final String FPS = "fps";
private static final String WATER_MARK_INFOS = "water_mark";
public static final int REQ_CODE_PUSH = 0x1112;
public static final int CAPTURE_PERMISSION_REQUEST_CODE = 0x1123;
// 互动模式下的预览view
private FrameLayout mPreviewContainer;
// 普通模式默认下的预览view
private SurfaceView mPreviewView;
private ViewPager mViewPager;
private List<Fragment> mFragmentList = new ArrayList<>();
private FragmentAdapter mFragmentAdapter;
private GestureDetector mDetector;
private ScaleGestureDetector mScaleDetector;
private LivePushFragment mLivePushFragment;
private AlivcLivePushConfig mAlivcLivePushConfig;
private static AlivcLivePusher mAlivcLivePusher = null;
private String mPushUrl = null;
private boolean mAsync = false;
private boolean mAudioOnly = false;
private boolean mVideoOnly = false;
private int mOrientation = ORIENTATION_PORTRAIT.ordinal();
private SurfaceStatus mSurfaceStatus = SurfaceStatus.UNINITED;
// private Handler mHandler = new Handler();
private boolean isPause = false;
private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
private boolean mFlash = false;
private boolean mMixExtern = false;
private boolean mMixMain = false;
private boolean mBeautyOn = true;
AlivcLivePushStatsInfo alivcLivePushStatsInfo = null;
private String mAuthTime = "";
private String mPrivacyKey = "";
// private ConnectivityChangedReceiver mChangedReceiver = new ConnectivityChangedReceiver();
private static int mNetWork = 0;
private int mFps;
private LivePushViewModel mLivePushViewModel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
StatusBarUtil.translucent(this, Color.TRANSPARENT);
mLivePushViewModel = new ViewModelProvider(this).get(LivePushViewModel.class);
mPushUrl = getIntent().getStringExtra(URL_KEY);
mAsync = getIntent().getBooleanExtra(ASYNC_KEY, false);
mAudioOnly = getIntent().getBooleanExtra(AUDIO_ONLY_KEY, false);
mVideoOnly = getIntent().getBooleanExtra(VIDEO_ONLY_KEY, false);
mOrientation = getIntent().getIntExtra(ORIENTATION_KEY, ORIENTATION_PORTRAIT.ordinal());
mCameraId = getIntent().getIntExtra(CAMERA_ID, Camera.CameraInfo.CAMERA_FACING_FRONT);
mFlash = getIntent().getBooleanExtra(FLASH_ON, false);
mAuthTime = getIntent().getStringExtra(AUTH_TIME);
mPrivacyKey = getIntent().getStringExtra(PRIVACY_KEY);
mMixExtern = getIntent().getBooleanExtra(MIX_EXTERN, false);
mMixMain = getIntent().getBooleanExtra(MIX_MAIN, false);
mBeautyOn = getIntent().getBooleanExtra(BEAUTY_CHECKED, true);
mFps = getIntent().getIntExtra(FPS, 0);
mAlivcLivePushConfig = (AlivcLivePushConfig) getIntent().getSerializableExtra(AlivcLivePushConfig.CONFIG);
ArrayList<WaterMarkInfo> waterMarkInfos = (ArrayList<WaterMarkInfo>) getIntent().getSerializableExtra(WATER_MARK_INFOS);
mLivePushViewModel.initReadFile(mAlivcLivePushConfig);
setOrientation(mOrientation);
setContentView(R.layout.activity_push);
initView();
if (mAlivcLivePushConfig.getLivePushMode() == AlivcLiveMode.AlivcLiveInteractiveMode) {
// 同一进程下,只能设置一次;如需修改,需要杀进程再设置
mAlivcLivePushConfig.setH5CompatibleMode(true);
}
mAlivcLivePusher = new AlivcLivePusher();
try {
mAlivcLivePusher.init(getApplicationContext(), mAlivcLivePushConfig);
} catch (IllegalArgumentException e) {
e.printStackTrace();
showDialog(this, e.getMessage());
} catch (IllegalStateException e) {
e.printStackTrace();
showDialog(this, e.getMessage());
}
if (mAlivcLivePushConfig.getLivePushMode() == AlivcLiveMode.AlivcLiveInteractiveMode) {
mAlivcLivePusher.startPreview(this, mPreviewContainer, true);
}
mLivePushFragment = LivePushFragment.newInstance(mAlivcLivePushConfig, mPushUrl, mAsync, mAudioOnly, mVideoOnly, mCameraId, mFlash, mAlivcLivePushConfig.getQualityMode().getQualityMode(),
mAuthTime, mPrivacyKey, mMixExtern, mMixMain, mBeautyOn, mFps, mOrientation, waterMarkInfos);
initViewPager();
mScaleDetector = new ScaleGestureDetector(getApplicationContext(), mScaleGestureDetector);
mDetector = new GestureDetector(getApplicationContext(), mGestureDetector);
mNetWork = NetWorkUtils.getAPNType(this);
}
public void initView() {
if (mAlivcLivePushConfig.getLivePushMode() == AlivcLiveMode.AlivcLiveInteractiveMode) {
//互动模式需要 FrameLayout
mPreviewContainer = findViewById(R.id.preview_container);
mPreviewContainer.setVisibility(View.VISIBLE);
} else {
mPreviewView = (SurfaceView) findViewById(R.id.preview_view);
mPreviewView.getHolder().addCallback(mCallback);
mPreviewView.setVisibility(View.VISIBLE);
}
}
private void initViewPager() {
mViewPager = (ViewPager) findViewById(R.id.tv_pager);
mFragmentList.add(mLivePushFragment);
mFragmentAdapter = new FragmentAdapter(this.getSupportFragmentManager(), mFragmentList);
mViewPager.setAdapter(mFragmentAdapter);
mViewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getPointerCount() >= 2 && mScaleDetector != null) {
mScaleDetector.onTouchEvent(motionEvent);
} else if (motionEvent.getPointerCount() == 1 && mDetector != null) {
mDetector.onTouchEvent(motionEvent);
}
// }
return false;
}
});
}
private void setOrientation(int orientation) {
if (orientation == ORIENTATION_PORTRAIT.ordinal()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (orientation == ORIENTATION_LANDSCAPE_HOME_RIGHT.ordinal()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if (orientation == ORIENTATION_LANDSCAPE_HOME_LEFT.ordinal()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
}
private GestureDetector.OnGestureListener mGestureDetector = new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent motionEvent) {
return false;
}
@Override
public void onShowPress(MotionEvent motionEvent) {
}
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
float x = 0f;
float y = 0f;
if (mAlivcLivePushConfig.getLivePushMode() == AlivcLiveMode.AlivcLiveInteractiveMode) {
if (mPreviewContainer.getWidth() > 0 && mPreviewContainer.getHeight() > 0) {
x = motionEvent.getX() / mPreviewContainer.getWidth();
y = motionEvent.getY() / mPreviewContainer.getHeight();
}
} else {
if (mPreviewView.getWidth() > 0 && mPreviewView.getHeight() > 0) {
x = motionEvent.getX() / mPreviewView.getWidth();
y = motionEvent.getY() / mPreviewView.getHeight();
}
}
try {
mAlivcLivePusher.focusCameraAtAdjustedPoint(x, y, true);
} catch (IllegalStateException e) {
}
return true;
}
@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
return false;
}
@Override
public void onLongPress(MotionEvent motionEvent) {
}
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
if (motionEvent == null || motionEvent1 == null) {
return false;
}
if (motionEvent.getX() - motionEvent1.getX() > FLING_MIN_DISTANCE
&& Math.abs(v) > FLING_MIN_VELOCITY) {
// Fling left
} else if (motionEvent1.getX() - motionEvent.getX() > FLING_MIN_DISTANCE
&& Math.abs(v) > FLING_MIN_VELOCITY) {
// Fling right
}
return false;
}
};
private float scaleFactor = 1.0f;
private ScaleGestureDetector.OnScaleGestureListener mScaleGestureDetector = new ScaleGestureDetector.OnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
if (scaleGestureDetector.getScaleFactor() > 1) {
scaleFactor += 0.5;
} else {
scaleFactor -= 2;
}
if (scaleFactor <= 1) {
scaleFactor = 1;
}
try {
if (scaleFactor >= mAlivcLivePusher.getMaxZoom()) {
scaleFactor = mAlivcLivePusher.getMaxZoom();
}
mAlivcLivePusher.setZoom((int) scaleFactor);
} catch (IllegalStateException e) {
}
return false;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
}
};
SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (mSurfaceStatus == SurfaceStatus.UNINITED) {
mSurfaceStatus = SurfaceStatus.CREATED;
mLivePushViewModel.onSurfaceCreated(mAsync, mPreviewView, mAlivcLivePusher);
} else if (mSurfaceStatus == SurfaceStatus.DESTROYED) {
mSurfaceStatus = SurfaceStatus.RECREATED;
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
mSurfaceStatus = SurfaceStatus.CHANGED;
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
mSurfaceStatus = SurfaceStatus.DESTROYED;
}
};
public static void startActivity(Activity activity, AlivcLivePushConfig alivcLivePushConfig, String url, boolean async,
boolean audioOnly, boolean videoOnly, AlivcPreviewOrientationEnum orientation, int cameraId, boolean isFlash,
String authTime, String privacyKey, boolean mixExtern, boolean mixMain, boolean ischecked, int fps,
ArrayList<WaterMarkInfo> waterMarkInfos) {
Intent intent = new Intent(activity, LivePushActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable(AlivcLivePushConfig.CONFIG, alivcLivePushConfig);
bundle.putString(URL_KEY, url);
bundle.putBoolean(ASYNC_KEY, async);
bundle.putBoolean(AUDIO_ONLY_KEY, audioOnly);
bundle.putBoolean(VIDEO_ONLY_KEY, videoOnly);
bundle.putInt(ORIENTATION_KEY, orientation.ordinal());
bundle.putInt(CAMERA_ID, cameraId);
bundle.putBoolean(FLASH_ON, isFlash);
bundle.putString(AUTH_TIME, authTime);
bundle.putString(PRIVACY_KEY, privacyKey);
bundle.putBoolean(MIX_EXTERN, mixExtern);
bundle.putBoolean(MIX_MAIN, mixMain);
bundle.putBoolean(BEAUTY_CHECKED, ischecked);
bundle.putInt(FPS, fps);
bundle.putSerializable(WATER_MARK_INFOS, waterMarkInfos);
intent.putExtras(bundle);
activity.startActivityForResult(intent, REQ_CODE_PUSH);
}
@Override
protected void onResume() {
super.onResume();
if (mAlivcLivePusher != null) {
try {
if (isPause) {
if (mAsync) {
mAlivcLivePusher.resumeAsync();
} else {
mAlivcLivePusher.resume();
}
mLivePushFragment.updateOperaButtonState(true);
isPause = false;
mAlivcLivePusher.resumeBGM();
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
@Override
protected void onPause() {
super.onPause();
if (mAlivcLivePusher != null) {
try {
if (!isPause) {
mAlivcLivePusher.pause();
isPause = true;
}
if (mLivePushFragment.isBGMPlaying()) {
mAlivcLivePusher.pauseBGM();
}
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
@Override
protected void onDestroy() {
mLivePushViewModel.stopYUV();
mLivePushViewModel.stopPcm();
if (mAlivcLivePusher != null) {
try {
mAlivcLivePusher.destroy();
mAlivcLivePusher = null;
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
mFragmentList = null;
mPreviewView = null;
mViewPager = null;
mFragmentAdapter = null;
mDetector = null;
mScaleDetector = null;
mLivePushFragment = null;
mAlivcLivePushConfig = null;
mAlivcLivePusher = null;
alivcLivePushStatsInfo = null;
super.onDestroy();
}
public class FragmentAdapter extends FragmentPagerAdapter {
List<Fragment> fragmentList = new ArrayList<>();
public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
super(fm);
this.fragmentList = fragmentList;
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
AlivcPreviewOrientationEnum orientationEnum;
if (mAlivcLivePusher != null) {
switch (rotation) {
case Surface.ROTATION_0:
orientationEnum = ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_90:
orientationEnum = ORIENTATION_LANDSCAPE_HOME_RIGHT;
break;
case Surface.ROTATION_270:
orientationEnum = ORIENTATION_LANDSCAPE_HOME_LEFT;
break;
default:
orientationEnum = ORIENTATION_PORTRAIT;
break;
}
try {
mAlivcLivePusher.setPreviewOrientation(orientationEnum);
} catch (IllegalStateException e) {
}
}
}
@Override
public AlivcLivePusher getLivePusher() {
return this.mAlivcLivePusher;
}
@Override
public PauseState getPauseStateListener() {
return this.mStateListener;
}
@Override
public SurfaceView getPreviewView() {
return this.mPreviewView;
}
private void showDialog(Context context, String message) {
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle(getString(R.string.dialog_title));
dialog.setMessage(message);
dialog.setNegativeButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
});
dialog.show();
}
public interface PauseState {
void updatePause(boolean state);
}
private PauseState mStateListener = new PauseState() {
@Override
public void updatePause(boolean state) {
isPause = state;
}
};
public static class ConnectivityChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
if (mNetWork != NetWorkUtils.getAPNType(context)) {
mNetWork = NetWorkUtils.getAPNType(context);
if (mAlivcLivePusher != null) {
if (mAlivcLivePusher.isPushing()) {
try {
mAlivcLivePusher.reconnectPushAsync(null);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,1416 @@
package com.alivc.live.baselive_push.ui;
import static com.alivc.live.pusher.AlivcLivePushCameraTypeEnum.CAMERA_TYPE_BACK;
import static com.alivc.live.pusher.AlivcLivePushCameraTypeEnum.CAMERA_TYPE_FRONT;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.alivc.component.custom.AlivcLivePushCustomFilter;
import com.alivc.live.annotations.AlivcLiveConnectionStatus;
import com.alivc.live.annotations.AlivcLiveConnectionStatusChangeReason;
import com.alivc.live.annotations.AlivcLiveMode;
import com.alivc.live.annotations.AlivcLiveNetworkQuality;
import com.alivc.live.annotations.AlivcLivePushKickedOutType;
import com.alivc.live.annotations.AlivcLiveRecordAudioQuality;
import com.alivc.live.annotations.AlivcLiveRecordMediaEvent;
import com.alivc.live.annotations.AlivcLiveRecordMediaFormat;
import com.alivc.live.annotations.AlivcLiveRecordStreamType;
import com.alivc.live.commonbiz.testapi.EGLContextTest;
import com.alivc.live.commonui.dialog.CommonDialog;
import com.alivc.live.commonui.messageview.AutoScrollMessagesView;
import com.alivc.live.commonui.seiview.LivePusherSEIView;
import com.alivc.live.commonui.widgets.LivePushTextSwitch;
import com.alivc.live.baselive_push.R;
import com.alivc.live.baselive_push.adapter.IPushController;
import com.alivc.live.baselive_push.adapter.OnSoundEffectChangedListener;
import com.alivc.live.baselive_push.ui.widget.PushMoreConfigBottomSheetLive;
import com.alivc.live.baselive_push.ui.widget.PushMusicBottomSheetLive;
import com.alivc.live.baselive_push.ui.widget.SoundEffectView;
import com.alivc.live.beauty.BeautyFactory;
import com.alivc.live.beauty.BeautyInterface;
import com.alivc.live.beauty.constant.BeautySDKType;
import com.alivc.live.commonbiz.SharedPreferenceUtils;
import com.alivc.live.commonutils.FastClickUtil;
import com.alivc.live.commonutils.FileUtil;
import com.alivc.live.commonutils.TextFormatUtil;
import com.alivc.live.commonutils.ToastUtils;
import com.alivc.live.player.annotations.AlivcLivePlayVideoStreamType;
import com.alivc.live.pusher.AlivcLiveLocalRecordConfig;
import com.alivc.live.pusher.AlivcLiveNetworkQualityProbeConfig;
import com.alivc.live.pusher.AlivcLiveNetworkQualityProbeResult;
import com.alivc.live.pusher.AlivcLivePublishState;
import com.alivc.live.pusher.AlivcLivePushAudioEffectReverbMode;
import com.alivc.live.pusher.AlivcLivePushAudioEffectVoiceChangeMode;
import com.alivc.live.pusher.AlivcLivePushBGMListener;
import com.alivc.live.pusher.AlivcLivePushConfig;
import com.alivc.live.pusher.AlivcLivePushError;
import com.alivc.live.pusher.AlivcLivePushErrorListener;
import com.alivc.live.pusher.AlivcLivePushInfoListener;
import com.alivc.live.pusher.AlivcLivePushNetworkListener;
import com.alivc.live.pusher.AlivcLivePushStatsInfo;
import com.alivc.live.pusher.AlivcLivePusher;
import com.alivc.live.pusher.AlivcPreviewDisplayMode;
import com.alivc.live.pusher.AlivcResolutionEnum;
import com.alivc.live.pusher.AlivcSnapshotListener;
import com.alivc.live.pusher.WaterMarkInfo;
import com.aliyunsdk.queen.menu.QueenBeautyMenu;
import com.aliyunsdk.queen.menu.QueenMenuPanel;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Vector;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
public class LivePushFragment extends Fragment {
public static final String TAG = "LivePushFragment";
private static final String PUSH_CONFIG = "push_config";
private static final String URL_KEY = "url_key";
private static final String ASYNC_KEY = "async_key";
private static final String AUDIO_ONLY_KEY = "audio_only_key";
private static final String VIDEO_ONLY_KEY = "video_only_key";
private static final String QUALITY_MODE_KEY = "quality_mode_key";
private static final String CAMERA_ID = "camera_id";
private static final String FLASH_ON = "flash_on";
private static final String AUTH_TIME = "auth_time";
private static final String PRIVACY_KEY = "privacy_key";
private static final String MIX_EXTERN = "mix_extern";
private static final String MIX_MAIN = "mix_main";
private static final String BEAUTY_CHECKED = "beauty_checked";
private static final String FPS = "fps";
private static final String PREVIEW_ORIENTATION = "preview_orientation";
private static final String WATER_MARK_INFOS = "water_mark";
private ImageView mExit;
private View mMusic;
private View mFlash;
private View mCamera;
private View mSnapshot;
private View mBeautyButton;
private View mSoundEffectButton;
private TextView mPreviewButton;
private TextView mPushButton;
private TextView mOperaButton;
private TextView mMore;
private TextView mRestartButton;
private TextView mDataButton;
private TextView mNetworkDetectButton;
private AlivcLivePushConfig mAlivcLivePushConfig = null;
private String mPushUrl = null;
private boolean mAsync = false;
private boolean mAudio = false;
private boolean mVideoOnly = false;
private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
private boolean isFlash = false;
private boolean mMixExtern = false;
private boolean mMixMain = false;
private boolean flashState = true;
private int snapshotCount = 0;
private int mQualityMode = 0;
ScheduledExecutorService mExecutorService = new ScheduledThreadPoolExecutor(5);
private boolean mIsStartAsnycPushing = false;
private PushMusicBottomSheetLive mMusicDialog = null;
private String mAuthString = "?auth_key=%1$d-%2$d-%3$d-%4$s";
private String mMd5String = "%1$s-%2$d-%3$d-%4$d-%5$s";
private String mTempUrl = null;
private String mAuthTime = "";
private String mPrivacyKey = "";
private TextView mStatusTV;
private LinearLayout mActionBar;
Vector<Integer> mDynamicals = new Vector<>();
// 高级美颜管理类
private BeautyInterface mBeautyManager;
private boolean isBeautyEnable = true;
private int mCurBr;
private int mTargetBr;
private boolean mBeautyOn = true;
private int mFps;
private int mPreviewOrientation;
private CommonDialog mDialog;
private boolean isConnectResult = false;//是否正在链接中
private QueenBeautyMenu mBeautyBeautyContainerView;
private QueenMenuPanel mQueenMenuPanel;
private IPushController mPushController = null;
private ArrayList<WaterMarkInfo> waterMarkInfos = null;
//音效
private SoundEffectView mSoundEffectView;
private LivePushViewModel mLivePushViewModel;
private LivePusherSEIView mSeiView;
private LivePushTextSwitch mShowCustomMessageView;
private LivePushTextSwitch mLocalRecordView;
private AlivcResolutionEnum mCurrentResolution;
private AutoScrollMessagesView mMessagesView;
private boolean isShowStatistics = false;
private TextView mManualCreateEGLContextTv;
private boolean mIsBGMPlaying = false;
public static LivePushFragment newInstance(AlivcLivePushConfig livePushConfig, String url, boolean async, boolean mAudio, boolean mVideoOnly, int cameraId,
boolean isFlash, int mode, String authTime, String privacyKey, boolean mixExtern,
boolean mixMain, boolean beautyOn, int fps, int previewOrientation,
ArrayList<WaterMarkInfo> waterMarkInfos) {
LivePushFragment livePushFragment = new LivePushFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(PUSH_CONFIG, livePushConfig);
bundle.putString(URL_KEY, url);
bundle.putBoolean(ASYNC_KEY, async);
bundle.putBoolean(AUDIO_ONLY_KEY, mAudio);
bundle.putBoolean(VIDEO_ONLY_KEY, mVideoOnly);
bundle.putInt(QUALITY_MODE_KEY, mode);
bundle.putInt(CAMERA_ID, cameraId);
bundle.putBoolean(FLASH_ON, isFlash);
bundle.putString(AUTH_TIME, authTime);
bundle.putString(PRIVACY_KEY, privacyKey);
bundle.putBoolean(MIX_EXTERN, mixExtern);
bundle.putBoolean(MIX_MAIN, mixMain);
bundle.putBoolean(BEAUTY_CHECKED, beautyOn);
bundle.putInt(FPS, fps);
bundle.putInt(PREVIEW_ORIENTATION, previewOrientation);
bundle.putSerializable(WATER_MARK_INFOS, waterMarkInfos);
livePushFragment.setArguments(bundle);
return livePushFragment;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof IPushController) {
mPushController = (IPushController) context;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Fragment may be recreated, so move all init logic to onActivityCreated
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mLivePushViewModel = new ViewModelProvider(getActivity()).get(LivePushViewModel.class);
AlivcLivePusher pusher = mPushController.getLivePusher();
if (getArguments() != null) {
mAlivcLivePushConfig = (AlivcLivePushConfig) getArguments().getSerializable(PUSH_CONFIG);
mPushUrl = getArguments().getString(URL_KEY);
mAsync = getArguments().getBoolean(ASYNC_KEY, false);
mAudio = getArguments().getBoolean(AUDIO_ONLY_KEY, false);
mVideoOnly = getArguments().getBoolean(VIDEO_ONLY_KEY, false);
mCameraId = getArguments().getInt(CAMERA_ID);
isFlash = getArguments().getBoolean(FLASH_ON, false);
mMixExtern = getArguments().getBoolean(MIX_EXTERN, false);
mMixMain = getArguments().getBoolean(MIX_MAIN, false);
mQualityMode = getArguments().getInt(QUALITY_MODE_KEY);
mBeautyOn = getArguments().getBoolean(BEAUTY_CHECKED);
mFps = getArguments().getInt(FPS);
mPreviewOrientation = getArguments().getInt(PREVIEW_ORIENTATION);
waterMarkInfos = (ArrayList<WaterMarkInfo>) getArguments().getSerializable(WATER_MARK_INFOS);
flashState = isFlash;
}
if (pusher != null) {
pusher.setLivePushInfoListener(mPushInfoListener);
pusher.setLivePushErrorListener(mPushErrorListener);
pusher.setLivePushNetworkListener(mPushNetworkListener);
pusher.setLivePushBGMListener(mPushBGMListener);
}
if (mAlivcLivePushConfig.isExternMainStream()) {
mLivePushViewModel.startPCM(pusher);
mLivePushViewModel.startYUV(pusher);
}
if (pusher != null && (mBeautyOn)) {
pusher.setCustomFilter(new AlivcLivePushCustomFilter() {
@Override
public void customFilterCreate() {
sendLogToMessageView("[CBK][CustomFilter] customFilterCreate: [" + Thread.currentThread().getId() + "]");
sendLogToMessageView("推流地址:"+mPushUrl);
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();
sendLogToMessageView("[CBK][CustomFilter] customFilterDestroy: [" + Thread.currentThread().getId() + "]");
}
});
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.push_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mQueenMenuPanel = QueenBeautyMenu.getPanel(this.getContext());
mQueenMenuPanel.onHideMenu();
mQueenMenuPanel.onHideValidFeatures();
mQueenMenuPanel.onHideCopyright();
mMessagesView = view.findViewById(R.id.v_messages);
sendLogToMessageView("----------statistics info----------");
mBeautyBeautyContainerView = view.findViewById(R.id.beauty_beauty_menuPanel);
mBeautyBeautyContainerView.addView(mQueenMenuPanel);
mSoundEffectView = view.findViewById(R.id.sound_effect_view);
// 发送SEI
mSeiView = view.findViewById(R.id.sei_view);
mSeiView.setSendSeiViewListener((payload, text) -> mPushController.getLivePusher().sendMessage(text, 0, 0, true));
mShowCustomMessageView = view.findViewById(R.id.btn_show_custom_message);
mShowCustomMessageView.setTextViewText(getString(R.string.sei_send_custom_message_tv));
mShowCustomMessageView.setOnSwitchToggleListener(isChecked -> {
int visibility = isChecked ? View.VISIBLE : View.GONE;
mSeiView.setVisibility(visibility);
});
// 本地录制
mLocalRecordView = view.findViewById(R.id.btn_local_record);
mLocalRecordView.setTextViewText(getString(R.string.local_record_tv));
mLocalRecordView.setOnSwitchToggleListener(isChecked -> {
AlivcLivePusher livePusher = mPushController.getLivePusher();
if (livePusher == null) {
return;
}
if (isChecked) {
AlivcLiveLocalRecordConfig recordConfig = new AlivcLiveLocalRecordConfig();
String dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
recordConfig.storagePath = FileUtil.getExternalCacheFolder(getContext()) + "/" + dateFormat + ".mp4";
recordConfig.streamType = AlivcLiveRecordStreamType.AUDIO_VIDEO;
recordConfig.audioQuality = AlivcLiveRecordAudioQuality.MEDIUM;
recordConfig.mediaFormat = AlivcLiveRecordMediaFormat.MP4;
livePusher.startLocalRecord(recordConfig);
} else {
livePusher.stopLocalRecord();
}
});
mManualCreateEGLContextTv = view.findViewById(R.id.tv_manual_create_egl_context);
mManualCreateEGLContextTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread thread = new Thread(() -> EGLContextTest.testGLContext());
sendLogToMessageView("Manual Create EGLContext: " + thread.getName());
thread.start();
}
});
mSoundEffectView.setOnSoundEffectChangedListener(new OnSoundEffectChangedListener() {
@Override
public void onSoundEffectChangeVoiceModeSelected(int position) {
if (position >= 0 && position < AlivcLivePushAudioEffectVoiceChangeMode.values().length) {
AlivcLivePusher livePusher = mPushController.getLivePusher();
Log.d(TAG, "onSoundEffectChangeVoiceModeSelected: " + position + " --- " + AlivcLivePushAudioEffectVoiceChangeMode.values()[position]);
livePusher.setAudioEffectVoiceChangeMode(AlivcLivePushAudioEffectVoiceChangeMode.values()[position]);
}
}
@Override
public void onSoundEffectRevertBSelected(int position) {
if (position >= 0 && position < AlivcLivePushAudioEffectReverbMode.values().length) {
AlivcLivePusher livePusher = mPushController.getLivePusher();
Log.d(TAG, "onSoundEffectRevertBSelected: " + position + " --- " + AlivcLivePushAudioEffectReverbMode.values()[position]);
livePusher.setAudioEffectReverbMode(AlivcLivePushAudioEffectReverbMode.values()[position]);
}
}
});
mDataButton = (TextView) view.findViewById(R.id.data);
mNetworkDetectButton = (TextView) view.findViewById(R.id.network_detect);
mStatusTV = (TextView) view.findViewById(R.id.tv_status);
mExit = (ImageView) view.findViewById(R.id.exit);
mMusic = view.findViewById(R.id.music);
mFlash = view.findViewById(R.id.flash);
mFlash.setSelected(isFlash);
mCamera = view.findViewById(R.id.camera);
mSnapshot = view.findViewById(R.id.snapshot);
mActionBar = (LinearLayout) view.findViewById(R.id.action_bar);
mCamera.setSelected(true);
mSnapshot.setSelected(true);
mPreviewButton = view.findViewById(R.id.preview_button);
mPreviewButton.setSelected(true);
mPushButton = view.findViewById(R.id.push_button);
mPushButton.setSelected(false);
mOperaButton = view.findViewById(R.id.opera_button);
mOperaButton.setSelected(false);
mMore = (TextView) view.findViewById(R.id.more);
mBeautyButton = view.findViewById(R.id.beauty_button);
mBeautyButton.setSelected(SharedPreferenceUtils.isBeautyOn(getActivity().getApplicationContext()));
mSoundEffectButton = view.findViewById(R.id.sound_effect_button);
mRestartButton = (TextView) view.findViewById(R.id.restart_button);
mExit.setOnClickListener(onClickListener);
mMusic.setOnClickListener(onClickListener);
mFlash.setOnClickListener(onClickListener);
mCamera.setOnClickListener(onClickListener);
mSnapshot.setOnClickListener(onClickListener);
mPreviewButton.setOnClickListener(onClickListener);
mSoundEffectButton.setOnClickListener(onClickListener);
mPushButton.setOnClickListener(onClickListener);
mOperaButton.setOnClickListener(onClickListener);
mBeautyButton.setOnClickListener(onClickListener);
mRestartButton.setOnClickListener(onClickListener);
mMore.setOnClickListener(onClickListener);
mDataButton.setOnClickListener(onClickListener);
mNetworkDetectButton.setOnClickListener(onClickListener);
if (mVideoOnly) {
mMusic.setVisibility(View.GONE);
}
if (mAudio) {
mPreviewButton.setVisibility(View.GONE);
}
if (mMixMain) {
mBeautyButton.setVisibility(View.GONE);
mMusic.setVisibility(View.GONE);
mFlash.setVisibility(View.GONE);
mCamera.setVisibility(View.GONE);
}
mMore.setVisibility(mAudio ? View.GONE : View.VISIBLE);
mBeautyButton.setVisibility(mAudio ? View.GONE : View.VISIBLE);
mFlash.setVisibility(mAudio ? View.GONE : View.VISIBLE);
mCamera.setVisibility(mAudio ? View.GONE : View.VISIBLE);
mFlash.setClickable(mCameraId != CAMERA_TYPE_FRONT.getCameraId());
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (mPushButton.isSelected() && !isConnectResult) {
showDialog(getSafeString(R.string.connecting_dialog_tips));
} else {
getActivity().finish();
}
return true;
}
return false;
}
});
}
View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
final int id = view.getId();
AlivcLivePusher pusher = mPushController.getLivePusher();
if (pusher == null) {
return;
}
if (id == R.id.music) {
if (!mAlivcLivePushConfig.isVideoOnly()) {
if (mMusicDialog == null) {
mMusicDialog = new PushMusicBottomSheetLive(getContext());
mMusicDialog.setOnMusicSelectListener(new PushMusicBottomSheetLive.OnMusicSelectListener() {
@Override
public void onBGMEarsBack(boolean state) {
pusher.setBGMEarsBack(state);
}
@Override
public void onAudioNoise(boolean state) {
pusher.setAudioDenoise(state);
}
@Override
public void onEarphone(boolean state) {
pusher.enableSpeakerphone(!state);
}
/**
* 开启音频智能降噪(使用智能降噪须知)
* <p>
* 1、使用智能降噪请关闭普通降噪两者功能互斥使用
* 2、智能降噪功能以插件形式提供调用该接口前请确保已集成了libpluginAliDenoise.so插件获取方式请参考官网文档
* 3、此接口可以通话过程中控制打开智能降噪功能通话过程中可以支持开启和关闭智能降噪
* 4、默认关闭开启后可能导致功耗增加智能降噪适合于会议教育等语音通讯为主的场景不适合有背景音乐的场景
* <p>
* 注意事项!!!
* 如遇libMNN相关的so冲突请检查当前工程中是否使用到了视频云的其它产品如美颜SDK/Animoji SDK
* 美颜SDK/Animoji SDK中包含libMNN相关的so因此外部无需再导入一份只保留libpluginAliDenoise.so
* 全局MNN相关的库统一留一份即可
* 具体请查看官网文档或API文档或者您可以咨询技术同学协助解决问题
*
* @see <a href="https://help.aliyun.com/zh/live/developer-reference/push-sdk/">推流SDK新版官网文档</a>
*/
@Override
public void onAudioIntelligentNoise(boolean state) {
int result = 0;
if (state) {
result = pusher.startIntelligentDenoise();
} else {
result = pusher.stopIntelligentDenoise();
}
ToastUtils.show(result == 0 ? getSafeString(R.string.success) : getSafeString(R.string.failed));
}
@Override
public void onBGPlay(boolean state) {
if (state) {
pusher.resumeBGM();
} else {
pusher.pauseBGM();
}
}
@Override
public void onBgResource(String path) {
if (!TextUtils.isEmpty(path)) {
pusher.startBGMAsync(path);
if (mAlivcLivePushConfig.getLivePushMode() == AlivcLiveMode.AlivcLiveInteractiveMode) {
//互动模式,开启 bgm 后,需要设置音量,否则没有声音
pusher.setBGMVolume(50);
}
} else {
try {
pusher.stopBGMAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
@Override
public void onBGLoop(boolean state) {
pusher.setBGMLoop(state);
}
@Override
public void onMute(boolean state) {
pusher.setMute(state);
}
@Override
public void onCaptureVolume(int progress) {
pusher.setCaptureVolume(progress);
}
@Override
public void onBGMVolume(int progress) {
pusher.setBGMVolume(progress);
}
});
}
mMusicDialog.show();
}
return;
}
mExecutorService.execute(new Runnable() {
@Override
public void run() {
LivePushActivity.PauseState stateListener = mPushController.getPauseStateListener();
try {
if (id == R.id.exit) {
if (mPushButton.isSelected() && !isConnectResult) {
showDialog(getSafeString(R.string.connecting_dialog_tips));
return;
}
getActivity().finish();
} else if (id == R.id.flash) {
pusher.setFlash(!mFlash.isSelected());
flashState = !mFlash.isSelected();
mFlash.post(new Runnable() {
@Override
public void run() {
mFlash.setSelected(!mFlash.isSelected());
}
});
} else if (id == R.id.camera) {
if (FastClickUtil.isProcessing()) {
return;
}
if (mCameraId == CAMERA_TYPE_FRONT.getCameraId()) {
mCameraId = CAMERA_TYPE_BACK.getCameraId();
} else {
mCameraId = CAMERA_TYPE_FRONT.getCameraId();
}
pusher.switchCamera();
if (mBeautyManager != null) {
mBeautyManager.switchCameraId(mCameraId);
}
mFlash.post(new Runnable() {
@Override
public void run() {
mFlash.setClickable(mCameraId != CAMERA_TYPE_FRONT.getCameraId());
if (mCameraId == CAMERA_TYPE_FRONT.getCameraId()) {
mFlash.setSelected(false);
} else {
mFlash.setSelected(flashState);
}
}
});
} else if (id == R.id.preview_button) {
if (FastClickUtil.isProcessing()) {
return;
}
final boolean isPreview = mPreviewButton.isSelected();
if (isPreview) {
pusher.stopPreview();
} else {
SurfaceView previewView = mPushController.getPreviewView();
if (mAsync) {
pusher.startPreviewAsync(previewView);
} else {
pusher.startPreview(previewView);
}
}
mPreviewButton.post(new Runnable() {
@Override
public void run() {
mPreviewButton.setText(isPreview ? getSafeString(R.string.start_preview_button) : getSafeString(R.string.stop_preview_button));
mPreviewButton.setSelected(!isPreview);
}
});
} else if (id == R.id.push_button) {
final boolean isPush = mPushButton.isSelected();
if (!isPush) {
if (mAsync) {
pusher.startPushAsync(mPushUrl);
} else {
pusher.startPush(mPushUrl);
}
} else {
pusher.stopPush();
mOperaButton.post(new Runnable() {
@Override
public void run() {
mOperaButton.setText(getSafeString(R.string.pause_button));
mOperaButton.setSelected(false);
}
});
if (stateListener != null) {
stateListener.updatePause(false);
}
}
mPushButton.post(new Runnable() {
@Override
public void run() {
mStatusTV.setText(isPush ? getSafeString(R.string.wating_push) : getSafeString(R.string.pushing));
mPushButton.setText(isPush ? getSafeString(R.string.start_push) : getSafeString(R.string.stop_button));
mPushButton.setSelected(!isPush);
}
});
} else if (id == R.id.opera_button) {
final boolean isPause = mOperaButton.isSelected();
if (!isPause) {
pusher.pause();
} else {
if (mAsync) {
pusher.resumeAsync();
} else {
pusher.resume();
}
}
if (stateListener != null) {
stateListener.updatePause(!isPause);
}
updateOperaButtonState(isPause);
} else if (id == R.id.sound_effect_button) {
if (!mAlivcLivePushConfig.isVideoOnly()) {
mSoundEffectView.post(() -> {
if (mBeautyBeautyContainerView.getVisibility() == View.VISIBLE) {
changeBeautyContainerVisibility();
}
changeSoundEffectVisibility();
});
}
} else if (id == R.id.beauty_button) {
if (!mBeautyOn) {
ToastUtils.show(getSafeString(R.string.beauty_off_tips));
return;
}
if (!mAlivcLivePushConfig.isAudioOnly()) {
mBeautyButton.post(() -> {
if (mSoundEffectView.getVisibility() == View.VISIBLE) {
changeSoundEffectVisibility();
}
changeBeautyContainerVisibility();
});
}
} else if (id == R.id.restart_button) {
if (mAsync) {
if (!mIsStartAsnycPushing) {
mIsStartAsnycPushing = true;
pusher.restartPushAsync();
}
} else {
pusher.restartPush();
}
} else if (id == R.id.more) {
mMore.post(new Runnable() {
@Override
public void run() {
PushMoreConfigBottomSheetLive pushMoreDialog = new PushMoreConfigBottomSheetLive(getActivity(), R.style.Live_BottomSheetDialog);
pushMoreDialog.setOnMoreConfigListener(new PushMoreConfigBottomSheetLive.OnMoreConfigListener() {
@Override
public void onDisplayModeChanged(AlivcPreviewDisplayMode mode) {
pusher.setPreviewMode(mode);
}
@Override
public void onPushMirror(boolean state) {
pusher.setPushMirror(state);
}
@Override
public void onPreviewMirror(boolean state) {
pusher.setPreviewMirror(state);
}
@Override
public void onAutoFocus(boolean state) {
pusher.setAutoFocus(state);
}
@Override
public void onAddDynamic() {
if (mDynamicals.size() < 5) {
float startX = 0.1f + mDynamicals.size() * 0.2f;
float startY = 0.1f + mDynamicals.size() * 0.2f;
int id = pusher.addDynamicsAddons(getActivity().getFilesDir().getPath() + File.separator + "alivc_resource/qizi/", startX, startY, 0.2f, 0.2f);
if (id > 0) {
mDynamicals.add(id);
} else {
ToastUtils.show(getSafeString(R.string.add_dynamic_failed) + id);
}
}
}
@Override
public void onRemoveDynamic() {
if (mDynamicals.size() > 0) {
int index = mDynamicals.size() - 1;
int id = mDynamicals.get(index);
pusher.removeDynamicsAddons(id);
mDynamicals.remove(index);
}
}
@Override
public void onResolutionChanged(AlivcResolutionEnum resolutionEnum) {
mCurrentResolution = resolutionEnum;
if (resolutionEnum != AlivcResolutionEnum.RESOLUTION_SELF_DEFINE) {
pusher.changeResolution(resolutionEnum);
}
}
});
pushMoreDialog.setOnDismissListener(dialogInterface -> {
if (mCurrentResolution == AlivcResolutionEnum.RESOLUTION_SELF_DEFINE) {
AlivcResolutionEnum.RESOLUTION_SELF_DEFINE.setSelfDefineResolution(pushMoreDialog.getResolutionWidth(), pushMoreDialog.getResolutionHeight());
pusher.changeResolution(AlivcResolutionEnum.RESOLUTION_SELF_DEFINE);
}
});
pushMoreDialog.setQualityMode(mQualityMode);
pushMoreDialog.show();
}
});
// PushMoreDialog pushMoreDialog = new PushMoreDialog();
// pushMoreDialog.setAlivcLivePusher(pusher, new DynamicListener() {
// @Override
// public void onAddDynamic() {
// if (mDynamicals.size() < 5) {
// float startX = 0.1f + mDynamicals.size() * 0.2f;
// float startY = 0.1f + mDynamicals.size() * 0.2f;
// int id = pusher.addDynamicsAddons(getActivity().getFilesDir().getPath() + File.separator + "alivc_resource/qizi/", startX, startY, 0.2f, 0.2f);
// if (id > 0) {
// mDynamicals.add(id);
// } else {
// ToastUtils.show(getSafeString(R.string.add_dynamic_failed) + id);
// }
// }
// }
//
// @Override
// public void onRemoveDynamic() {
// if (mDynamicals.size() > 0) {
// int index = mDynamicals.size() - 1;
// int id = mDynamicals.get(index);
// pusher.removeDynamicsAddons(id);
// mDynamicals.remove(index);
// }
// }
// });
// pushMoreDialog.setQualityMode(mQualityMode);
// pushMoreDialog.setPushUrl(mPushUrl);
// pushMoreDialog.show(getFragmentManager(), "moreDialog");
} else if (id == R.id.snapshot) {
pusher.snapshot(1, 0, new AlivcSnapshotListener() {
@Override
public void onSnapshot(Bitmap bmp) {
String dateFormat = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss-SS").format(new Date());
File f = new File(getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES), "snapshot-" + dateFormat + ".png");
if (f.exists()) {
f.delete();
}
try {
FileOutputStream out = new FileOutputStream(f);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
showDialog("截图已保存:" + getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES).getPath() + "/snapshot-" + dateFormat + ".png");
}
});
} else if (id == R.id.data) {
isShowStatistics = !isShowStatistics;
ToastUtils.show((isShowStatistics ? "open" : "close") + " statistics info");
} else if (id == R.id.network_detect) {
if (pusher != null) {
boolean isSelect = mNetworkDetectButton.isSelected();
if (isSelect) {
int result = pusher.stopLastMileDetect();
sendLogToMessageView("[API] stopLastMileDetect: [end][" + result + "]");
} else {
AlivcLiveNetworkQualityProbeConfig probeConfig = new AlivcLiveNetworkQualityProbeConfig();
probeConfig.probeUpLink = true;
probeConfig.probeDownLink = true;
int result = pusher.startLastMileDetect(probeConfig);
sendLogToMessageView("[API] startLastMileDetect: [end][" + result + "][" + probeConfig + "]");
}
mNetworkDetectButton.setSelected(!isSelect);
}
}
} catch (IllegalArgumentException e) {
showDialog(e.getMessage());
e.printStackTrace();
} catch (IllegalStateException e) {
showDialog(e.getMessage());
e.printStackTrace();
}
}
});
}
};
AlivcLivePushInfoListener mPushInfoListener = new AlivcLivePushInfoListener() {
@Override
public void onPreviewStarted(AlivcLivePusher pusher) {
//AlivcLivePusher pusher = mPushController.getLivePusher();
// 添加水印
for (int i = 0; i < waterMarkInfos.size(); i++) {
pusher.addWaterMark(waterMarkInfos.get(i).mWaterMarkPath, waterMarkInfos.get(i).mWaterMarkCoordX, waterMarkInfos.get(i).mWaterMarkCoordY, waterMarkInfos.get(i).mWaterMarkWidth);
}
ToastUtils.show(getSafeString(R.string.start_preview));
sendLogToMessageView("[CBK][INFO] onPreviewStarted");
}
@Override
public void onPreviewStopped(AlivcLivePusher pusher) {
if (isAdded()) {
ToastUtils.show(getSafeString(R.string.stop_preview));
}
sendLogToMessageView("[CBK][INFO] onPreviewStopped");
}
@Override
public void onPushStarted(AlivcLivePusher pusher) {
isConnectResult = true;
mIsStartAsnycPushing = false;
if (isAdded()) {
ToastUtils.show(getSafeString(R.string.start_push));
}
sendLogToMessageView("[CBK][INFO] onPushStarted");
}
@Override
public void onFirstFramePushed(AlivcLivePusher pusher) {
sendLogToMessageView("[CBK][INFO] onFirstFramePushed");
}
@Override
public void onPushPaused(AlivcLivePusher pusher) {
ToastUtils.show(getSafeString(R.string.pause_push));
sendLogToMessageView("[CBK][INFO] onPushPaused");
}
@Override
public void onPushResumed(AlivcLivePusher pusher) {
ToastUtils.show(getSafeString(R.string.resume_push));
sendLogToMessageView("[CBK][INFO] onPushResumed");
}
@Override
public void onPushStopped(AlivcLivePusher pusher) {
ToastUtils.show(getSafeString(R.string.stop_push));
sendLogToMessageView("[CBK][INFO] onPushStopped");
}
/**
* 推流重启通知
*
* @param pusher AlivcLivePusher实例
*/
@Override
public void onPushRestarted(AlivcLivePusher pusher) {
mIsStartAsnycPushing = false;
ToastUtils.show(getSafeString(R.string.restart_success));
sendLogToMessageView("[CBK][INFO] onPushRestarted");
}
@Override
public void onFirstFramePreviewed(AlivcLivePusher pusher) {
sendLogToMessageView("[CBK][INFO] onFirstFramePreviewed");
}
@Override
public void onDropFrame(AlivcLivePusher pusher, int countBef, int countAft) {
sendLogToMessageView("[CBK][INFO] onDropFrame: [" + countBef + "->" + countAft + "]");
}
@Override
public void onAdjustBitrate(AlivcLivePusher pusher, int currentBitrate, int targetBitrate) {
sendLogToMessageView("[CBK][INFO] onAdjustBitrate: [" + currentBitrate + "->" + targetBitrate + "]");
}
@Override
public void onAdjustFps(AlivcLivePusher pusher, int currentFps, int targetFps) {
sendLogToMessageView("[CBK][INFO] onAdjustFps: [" + currentFps + "->" + targetFps + "]");
}
@Override
public void onPushStatistics(AlivcLivePusher pusher, AlivcLivePushStatsInfo statistics) {
if (isShowStatistics) {
sendLogToMessageView("[CBK][INFO] onPushStatistics: " + statistics);
}
}
@Override
public void onLocalRecordEvent(AlivcLiveRecordMediaEvent mediaEvent, String storagePath) {
sendLogToMessageView("[CBK][INFO] onLocalRecordEvent: [" + mediaEvent + "][" + storagePath + "]");
}
@Override
public void onRemoteUserEnterRoom(AlivcLivePusher pusher, String userId, boolean isOnline) {
sendLogToMessageView("[CBK][INFO] onRemoteUserEnterRoom: [" + userId + "][" + isOnline + "]");
}
@Override
public void onRemoteUserAudioStream(AlivcLivePusher pusher, String userId, boolean isPushing) {
sendLogToMessageView("[CBK][INFO] onRemoteUserAudioStream: [" + userId + "][" + isPushing + "]");
}
@Override
public void onRemoteUserVideoStream(AlivcLivePusher pusher, String userId, AlivcLivePlayVideoStreamType videoStreamType, boolean isPushing) {
sendLogToMessageView("[CBK][INFO] onRemoteUserVideoStream: [" + userId + "][" + videoStreamType + "][" + isPushing + "]");
}
@Override
public void onSetLiveMixTranscodingConfig(AlivcLivePusher pusher, boolean isSuccess, String msg) {
sendLogToMessageView("[CBK][INFO] onSetLiveMixTranscodingConfig: [" + isSuccess + "][" + msg + "]");
}
@Override
public void onKickedOutByServer(AlivcLivePusher pusher, AlivcLivePushKickedOutType kickedOutType) {
sendLogToMessageView("[CBK][INFO] onKickedOutByServer: [" + kickedOutType + "]");
}
@Override
public void onMicrophoneVolumeUpdate(AlivcLivePusher pusher, int volume) {
super.onMicrophoneVolumeUpdate(pusher, volume);
}
@Override
public void onAudioPublishStateChanged(AlivcLivePublishState oldState, AlivcLivePublishState newState) {
sendLogToMessageView("[CBK][INFO] onAudioPublishStateChanged: [" + oldState + "->" + newState + "]");
}
@Override
public void onVideoPublishStateChanged(AlivcLivePublishState oldState, AlivcLivePublishState newState) {
sendLogToMessageView("[CBK][INFO] onVideoPublishStateChanged: [" + oldState + "->" + newState + "]");
}
@Override
public void onScreenSharePublishStateChanged(AlivcLivePublishState oldState, AlivcLivePublishState newState) {
sendLogToMessageView("[CBK][INFO] onScreenSharePublishStateChanged: [" + oldState + "->" + newState + "]");
}
@Override
public void onLocalDualAudioStreamPushState(AlivcLivePusher pusher, boolean isPushing) {
sendLogToMessageView("[CBK][INFO] onLocalDualAudioStreamPushState: [" + isPushing + "]");
}
};
AlivcLivePushErrorListener mPushErrorListener = new AlivcLivePushErrorListener() {
@Override
public void onSystemError(AlivcLivePusher livePusher, AlivcLivePushError error) {
mIsStartAsnycPushing = false;
showDialog(getSafeString(R.string.system_error) + error.toString());
sendLogToMessageView("[CBK][ERROR] onSystemError: [" + error + "]");
}
@Override
public void onSDKError(AlivcLivePusher livePusher, AlivcLivePushError error) {
mIsStartAsnycPushing = false;
showDialog(getSafeString(R.string.sdk_error) + error.toString());
sendLogToMessageView("[CBK][ERROR] onSDKError: [" + error + "]");
}
};
AlivcLivePushNetworkListener mPushNetworkListener = new AlivcLivePushNetworkListener() {
@Override
public void onNetworkPoor(AlivcLivePusher pusher) {
showNetWorkDialog(getSafeString(R.string.network_poor));
sendLogToMessageView("[CBK][NETWORK] onNetworkPoor");
}
@Override
public void onNetworkRecovery(AlivcLivePusher pusher) {
ToastUtils.show(getSafeString(R.string.network_recovery));
sendLogToMessageView("[CBK][NETWORK] onNetworkRecovery");
}
@Override
public void onReconnectStart(AlivcLivePusher pusher) {
ToastUtils.show(getSafeString(R.string.reconnect_start));
sendLogToMessageView("[CBK][NETWORK] onReconnectStart");
}
@Override
public void onReconnectFail(AlivcLivePusher pusher) {
mIsStartAsnycPushing = false;
showDialog(getSafeString(R.string.reconnect_fail));
sendLogToMessageView("[CBK][NETWORK] onReconnectFail");
}
@Override
public void onReconnectSucceed(AlivcLivePusher pusher) {
ToastUtils.show(getSafeString(R.string.reconnect_success));
sendLogToMessageView("[CBK][NETWORK] onReconnectSucceed");
}
@Override
public void onSendDataTimeout(AlivcLivePusher pusher) {
mIsStartAsnycPushing = false;
showDialog(getSafeString(R.string.senddata_timeout));
sendLogToMessageView("[CBK][NETWORK] onSendDataTimeout");
}
@Override
public void onConnectFail(AlivcLivePusher pusher) {
isConnectResult = true;
mIsStartAsnycPushing = false;
showDialog(getSafeString(R.string.connect_fail));
sendLogToMessageView("[CBK][NETWORK] onConnectFail");
}
@Override
public void onNetworkQualityChanged(AlivcLiveNetworkQuality upQuality, AlivcLiveNetworkQuality downQuality) {
sendLogToMessageView("[CBK][NETWORK] onNetworkQualityChanged: [" + upQuality + "][" + downQuality + "]");
}
@Override
public void onConnectionLost(AlivcLivePusher pusher) {
mIsStartAsnycPushing = false;
// 断网后停止本地录制
AlivcLivePusher livePusher = mPushController.getLivePusher();
if (livePusher != null) {
livePusher.stopLocalRecord();
}
ToastUtils.show(getSafeString(R.string.connection_lost));
sendLogToMessageView("[CBK][NETWORK] onConnectionLost");
}
@Override
public String onPushURLAuthenticationOverdue(AlivcLivePusher pusher) {
sendLogToMessageView("[CBK][NETWORK] onPushURLAuthenticationOverdue");
return "";
}
@Override
public void onSendMessage(AlivcLivePusher pusher) {
sendLogToMessageView("[CBK][NETWORK] onSendMessage: " + getSafeString(R.string.send_message));
}
@Override
public void onPacketsLost(AlivcLivePusher pusher) {
ToastUtils.show(getSafeString(R.string.packet_lost));
sendLogToMessageView("[CBK][NETWORK] onPacketsLost");
}
@Override
public void onLastMileDetectResultWithQuality(AlivcLivePusher pusher, AlivcLiveNetworkQuality networkQuality) {
super.onLastMileDetectResultWithQuality(pusher, networkQuality);
sendLogToMessageView("[CBK][NETWORK] onLastMileDetectResultWithQuality: [" + networkQuality + "]");
}
@Override
public void onLastMileDetectResultWithBandWidth(AlivcLivePusher pusher, int code, AlivcLiveNetworkQualityProbeResult networkQualityProbeResult) {
super.onLastMileDetectResultWithBandWidth(pusher, code, networkQualityProbeResult);
sendLogToMessageView("[CBK][NETWORK] onLastMileDetectResultWithBandWidth: [" + code + "][" + networkQualityProbeResult + "]");
}
@Override
public void onPushURLTokenWillExpire(AlivcLivePusher pusher) {
super.onPushURLTokenWillExpire(pusher);
sendLogToMessageView("[CBK][NETWORK] onPushURLTokenWillExpire");
}
@Override
public void onPushURLTokenExpired(AlivcLivePusher pusher) {
super.onPushURLTokenExpired(pusher);
sendLogToMessageView("[CBK][NETWORK] onPushURLTokenExpired");
}
@Override
public void onConnectionStatusChange(AlivcLivePusher pusher, AlivcLiveConnectionStatus connectionStatus, AlivcLiveConnectionStatusChangeReason connectionStatusChangeReason) {
super.onConnectionStatusChange(pusher, connectionStatus, connectionStatusChangeReason);
sendLogToMessageView("[CBK][NETWORK] onConnectionStatusChange: [" + connectionStatus + "][" + connectionStatusChangeReason + "]");
}
};
private AlivcLivePushBGMListener mPushBGMListener = new AlivcLivePushBGMListener() {
@Override
public void onStarted() {
sendLogToMessageView("[CBK][BGM] onStarted");
mIsBGMPlaying = true;
}
@Override
public void onStopped() {
sendLogToMessageView("[CBK][BGM] onStopped");
mIsBGMPlaying = false;
}
@Override
public void onPaused() {
sendLogToMessageView("[CBK][BGM] onPaused");
mIsBGMPlaying = false;
}
@Override
public void onResumed() {
sendLogToMessageView("[CBK][BGM] onResumed");
mIsBGMPlaying = true;
}
@Override
public void onProgress(final long progress, final long duration) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (mMusicDialog != null) {
mMusicDialog.updateProgress(progress, duration);
}
}
});
}
@Override
public void onCompleted() {
sendLogToMessageView("[CBK][BGM] onCompleted");
mIsBGMPlaying = false;
}
@Override
public void onDownloadTimeout() {
sendLogToMessageView("[CBK][BGM] onDownloadTimeout");
mIsBGMPlaying = false;
}
@Override
public void onOpenFailed() {
sendLogToMessageView("[CBK][BGM] onOpenFailed");
showDialog(getSafeString(R.string.bgm_open_failed));
mIsBGMPlaying = false;
}
};
@Override
public void onDestroy() {
super.onDestroy();
if (mMusicDialog != null && mMusicDialog.isShowing()) {
mMusicDialog.dismiss();
mMusicDialog = null;
}
if (mExecutorService != null && !mExecutorService.isShutdown()) {
mExecutorService.shutdown();
}
destroyBeautyManager();
}
private void showDialog(final String message) {
if (getActivity() == null || message == null) {
return;
}
if (mDialog == null || !mDialog.isShowing()) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
if (getActivity() != null) {
mDialog = new CommonDialog(getActivity());
mDialog.setDialogTitle(getSafeString(R.string.dialog_title));
mDialog.setDialogContent(message);
mDialog.setConfirmButton(TextFormatUtil.getTextFormat(getActivity(), R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
mDialog.show();
}
}
});
}
}
private void showNetWorkDialog(final String message) {
if (getActivity() == null || message == null) {
return;
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
if (getActivity() != null) {
final AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
dialog.setTitle(getSafeString(R.string.dialog_title));
dialog.setMessage(message);
dialog.setNegativeButton(getSafeString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
dialog.setNeutralButton(getSafeString(R.string.reconnect), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
AlivcLivePusher pusher = mPushController.getLivePusher();
try {
pusher.reconnectPushAsync(null);
} catch (IllegalStateException e) {
}
}
});
dialog.show();
}
}
});
}
private String getMD5(String string) {
byte[] hash;
try {
hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
StringBuilder hex = new StringBuilder(hash.length * 2);
for (byte b : hash) {
if ((b & 0xFF) < 0x10) {
hex.append("0");
}
hex.append(Integer.toHexString(b & 0xFF));
}
return hex.toString();
}
private String getUri(String url) {
String result = "";
String temp = url.substring(7);
if (temp != null && !temp.isEmpty()) {
result = temp.substring(temp.indexOf("/"));
}
return result;
}
public final String getSafeString(@StringRes int resId) {
Context context = getContext();
if (context != null) {
return getResources().getString(resId);
} else {
return "";
}
}
private String getAuthString(String time) {
if (!time.isEmpty() && !mPrivacyKey.isEmpty()) {
long tempTime = (System.currentTimeMillis() + Integer.valueOf(time)) / 1000;
String tempprivacyKey = String.format(mMd5String, getUri(mPushUrl), tempTime, 0, 0, mPrivacyKey);
String auth = String.format(mAuthString, tempTime, 0, 0, getMD5(tempprivacyKey));
mTempUrl = mPushUrl + auth;
} else {
mTempUrl = mPushUrl;
}
return mTempUrl;
}
public boolean isBGMPlaying() {
return mIsBGMPlaying;
}
// 初始化美颜
private void initBeautyManager() {
if (mBeautyManager == null) {
Log.d(TAG, "initBeautyManager start");
// v4.4.4版本-v6.1.0版本互动模式下的美颜处理逻辑参考BeautySDKType.INTERACT_QUEENInteractQueenBeautyImpl
// v6.1.0以后的版本从v6.2.0开始基础模式下的美颜和互动模式下的美颜处理逻辑保持一致QueenBeautyImpl
mBeautyManager = BeautyFactory.createBeauty(BeautySDKType.QUEEN, LivePushFragment.this.getActivity());
// initialize in texture thread.
mBeautyManager.init();
mBeautyManager.setBeautyEnable(isBeautyEnable);
mBeautyManager.switchCameraId(mCameraId);
Log.d(TAG, "initBeautyManager end");
}
}
// 销毁美颜
private void destroyBeautyManager() {
if (mBeautyManager != null) {
mBeautyManager.release();
mBeautyManager = null;
}
}
private void changeBeautyContainerVisibility() {
if (mBeautyBeautyContainerView.getVisibility() == View.VISIBLE) {
mActionBar.setVisibility(View.VISIBLE);
mQueenMenuPanel.onHideMenu();
mBeautyBeautyContainerView.setVisibility(View.GONE);
} else {
mActionBar.setVisibility(View.GONE);
mQueenMenuPanel.onShowMenu();
mBeautyBeautyContainerView.setVisibility(View.VISIBLE);
}
}
private void changeSoundEffectVisibility() {
if (mSoundEffectView.getVisibility() == View.VISIBLE) {
mActionBar.setVisibility(View.VISIBLE);
mSoundEffectView.setVisibility(View.GONE);
} else {
mActionBar.setVisibility(View.GONE);
mSoundEffectView.setVisibility(View.VISIBLE);
}
}
public void updateOperaButtonState(boolean value) {
if (mOperaButton != null) {
mOperaButton.post(new Runnable() {
@Override
public void run() {
if (mOperaButton != null) {
mOperaButton.setText(value ? getSafeString(R.string.pause_button) : getSafeString(R.string.resume_button));
mOperaButton.setSelected(!value);
}
}
});
}
if (mPreviewButton != null) {
mPreviewButton.post(new Runnable() {
@Override
public void run() {
if (mPreviewButton != null) {
mPreviewButton.setText(value ? getSafeString(R.string.stop_preview_button) : getSafeString(R.string.start_preview_button));
mPreviewButton.setSelected(value);
}
}
});
}
}
// 发送日志到消息视图
private void sendLogToMessageView(String message) {
if (mMessagesView != null) {
mMessagesView.post(new Runnable() {
@Override
public void run() {
if (mMessagesView != null) {
mMessagesView.appendMessage(message);
}
}
});
}
}
}

View File

@@ -0,0 +1,83 @@
package com.alivc.live.baselive_push.ui;
import android.app.Application;
import android.content.Context;
import android.view.SurfaceView;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import com.alivc.live.commonbiz.LocalStreamReader;
import com.alivc.live.commonbiz.ResourcesConst;
import com.alivc.live.pusher.AlivcLivePushConfig;
import com.alivc.live.pusher.AlivcLivePusher;
import com.alivc.live.pusher.AlivcResolutionEnum;
import java.io.File;
public class LivePushViewModel extends AndroidViewModel {
private final Context mApplicationContext;
private LocalStreamReader mLocalStreamReader;
public LivePushViewModel(@NonNull Application application) {
super(application);
mApplicationContext = application;
}
public void initReadFile(AlivcLivePushConfig config) {
AlivcResolutionEnum resolution = config.getResolution();
int width = AlivcResolutionEnum.getResolutionWidth(resolution, config.getLivePushMode());
int height = AlivcResolutionEnum.getResolutionHeight(resolution, config.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();
}
private void startYUV(final Context context, AlivcLivePusher mAlivcLivePusher) {
File f = ResourcesConst.localCaptureYUVFilePath(context);
mLocalStreamReader.readYUVData(f, (buffer, pts, videoWidth, videoHeight, videoStride, videoSize, videoRotation) -> {
mAlivcLivePusher.inputStreamVideoData(buffer, videoWidth, videoHeight, videoStride, videoSize, pts, videoRotation);
});
}
public void stopYUV() {
mLocalStreamReader.stopYUV();
}
public void stopPcm() {
mLocalStreamReader.stopPcm();
}
private void startPCM(final Context context, AlivcLivePusher mAlivcLivePusher) {
File f = ResourcesConst.localCapturePCMFilePath(context);
mLocalStreamReader.readPCMData(f, (buffer, length, pts, audioSampleRate, audioChannel) -> {
mAlivcLivePusher.inputStreamAudioData(buffer, length, audioSampleRate, audioChannel, pts);
});
}
public void onSurfaceCreated(boolean mAsync, SurfaceView mPreviewView, AlivcLivePusher mAlivcLivePusher) {
if (mAlivcLivePusher != null) {
if (mAsync) {
mAlivcLivePusher.startPreviewAsync(mPreviewView);
} else {
mAlivcLivePusher.startPreview(mPreviewView);
}
}
}
public void startYUV(AlivcLivePusher mAlivcLivePusher) {
startYUV(mApplicationContext, mAlivcLivePusher);
}
public void startPCM(AlivcLivePusher mAlivcLivePusher) {
startPCM(mApplicationContext, mAlivcLivePusher);
}
}

View File

@@ -0,0 +1,714 @@
package com.alivc.live.baselive_push.ui;
import static com.alivc.live.pusher.AlivcLivePushConstants.DEFAULT_VALUE_AUTO_FOCUS;
import static com.alivc.live.pusher.AlivcLivePushConstants.DEFAULT_VALUE_PREVIEW_MIRROR;
import static com.alivc.live.pusher.AlivcLivePushConstants.DEFAULT_VALUE_PUSH_MIRROR;
import static com.alivc.live.pusher.AlivcPreviewOrientationEnum.ORIENTATION_PORTRAIT;
import android.Manifest;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
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.annotations.AlivcLiveMode;
import com.alivc.live.baselive_push.R;
import com.alivc.live.baselive_push.bean.GsonUtils;
import com.alivc.live.commonbiz.ResourcesDownload;
import com.alivc.live.commonbiz.SharedPreferenceUtils;
import com.alivc.live.commonbiz.backdoor.BackDoorActivity;
import com.alivc.live.commonbiz.backdoor.BackDoorInstance;
import com.alivc.live.commonbiz.test.PushDemoTestConstants;
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.commonui.widgets.PushWaterMarkDialog;
import com.alivc.live.commonutils.DownloadUtil;
import com.alivc.live.commonutils.FastClickUtil;
import com.alivc.live.commonutils.FileUtil;
import com.alivc.live.commonutils.LogcatHelper;
import com.alivc.live.commonutils.ToastUtils;
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.AlivcLiveBase;
import com.alivc.live.pusher.AlivcLivePushCameraTypeEnum;
import com.alivc.live.pusher.AlivcLivePushConfig;
import com.alivc.live.pusher.AlivcLivePushConstants;
import com.alivc.live.pusher.AlivcPreviewDisplayMode;
import com.alivc.live.pusher.AlivcPreviewOrientationEnum;
import com.alivc.live.pusher.AlivcResolutionEnum;
import com.alivc.live.pusher.AlivcSoundFormat;
import com.alivc.live.pusher.WaterMarkInfo;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
public class PushConfigActivity extends AppCompatActivity {
private RelativeLayout mInteractionRelativeLayout;
private RadioGroup mLivePushModeRadioGroup;
private LivePushSettingView mLivePushSettingView;
private AlivcResolutionEnum mCurrentResolution = AlivcResolutionEnum.RESOLUTION_540P;
private AlivcResolutionEnum mDefinition = AlivcResolutionEnum.RESOLUTION_540P;
private static final int REQ_CODE_PERMISSION = 0x1111;
private InputMethodManager manager;
private View mPublish;
private TextView mLocalLogTv;
private EditText mUrl;
private ImageView mQr;
private ImageView mBack;
private AlivcLivePushConfig mAlivcLivePushConfig;
private boolean mAsyncValue = true;
private boolean mAudioOnlyPush = false;
private boolean mVideoOnlyPush = false;
private AlivcPreviewOrientationEnum mOrientationEnum = ORIENTATION_PORTRAIT;
private ArrayList<WaterMarkInfo> mWaterMarkInfos = new ArrayList<>();
private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
private boolean isFlash = false;
private String mAuthTimeStr = "";
private String mPrivacyKeyStr = "";
private boolean mMixStream = false;
private View mTabArgsLayout;
private View mTabActionLayout;
private View mTabArgsView;
private View mTabActionView;
private int mFpsConfig = 25;//默认帧率
@Nullable
private AVLiveLoadingDialog mLoadingDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtil.translucent(this, getColor(R.color.main_color));
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.push_setting);
mAlivcLivePushConfig = new AlivcLivePushConfig();
//设置音乐模式
//mAlivcLivePushConfig.setAudioSceneMode(AlivcAudioSceneModeEnum.AUDIO_SCENE_MUSIC_MODE);
// 设置编码器类型
// mAlivcLivePushConfig.setVideoEncodeType(Encode_TYPE_H265);
// 设置b帧个数
// mAlivcLivePushConfig.setBFrames(1);
if (mAlivcLivePushConfig.getPreviewOrientation() == AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_RIGHT.getOrientation() || mAlivcLivePushConfig.getPreviewOrientation() == AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_LEFT.getOrientation()) {
mAlivcLivePushConfig.setNetworkPoorPushImage(getFilesDir().getPath() + File.separator + "alivc_resource/poor_network_land.png");
mAlivcLivePushConfig.setPausePushImage(getFilesDir().getPath() + File.separator + "alivc_resource/background_push_land.png");
} else {
mAlivcLivePushConfig.setNetworkPoorPushImage(getFilesDir().getPath() + File.separator + "alivc_resource/poor_network.png");
mAlivcLivePushConfig.setPausePushImage(getFilesDir().getPath() + File.separator + "alivc_resource/background_push.png");
}
mAlivcLivePushConfig.setMediaProjectionPermissionResultData(null);
initView();
setClick();
addWaterMarkInfo();
if (mAlivcLivePushConfig != null) {
mAlivcLivePushConfig.setPreviewDisplayMode(AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FILL);
SharedPreferenceUtils.setDisplayFit(getApplicationContext(), AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FILL
.getPreviewDisplayMode());
}
Intent intent = getIntent();
String url = intent.getStringExtra("pushUrl");
if (!TextUtils.isEmpty(url)) {
mUrl.setText(url);
}
// 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);
// }
}
private void initView() {
mUrl = (EditText) findViewById(R.id.url_editor);
mPublish = findViewById(R.id.beginPublish);
mQr = (ImageView) findViewById(R.id.qr_code);
mBack = (ImageView) findViewById(R.id.iv_back);
SharedPreferenceUtils.setHintTargetBit(getApplicationContext(), AlivcLivePushConstants.BITRATE_540P_RESOLUTION_FIRST.DEFAULT_VALUE_INT_TARGET_BITRATE.getBitrate());
SharedPreferenceUtils.setHintMinBit(getApplicationContext(), AlivcLivePushConstants.BITRATE_540P_RESOLUTION_FIRST.DEFAULT_VALUE_INT_MIN_BITRATE.getBitrate());
mTabArgsLayout = findViewById(R.id.tab_args_layout);
// 测试用长按推流参数四个字自动填写rtmp://
mTabArgsLayout.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
String filledUrl = mUrl.getText().toString();
if (TextUtils.isEmpty(filledUrl) || !(filledUrl.startsWith("rtmp://") || filledUrl.startsWith("artc://"))) {
mUrl.setText("rtmp://");
}
return false;
}
});
mTabActionLayout = findViewById(R.id.tab_action_layout);
mTabArgsView = (View) findViewById(R.id.tab_args_view);
mTabActionView = (View) findViewById(R.id.tab_action_view);
mLocalLogTv = findViewById(R.id.local_log);
// mVideoEncoder.check(R.id.h264_encoder);
// mBFrames.check(R.id.b_frame_no);
mInteractionRelativeLayout = findViewById(R.id.rl_interaction);
mLivePushModeRadioGroup = findViewById(R.id.live_push_mode);
mLivePushSettingView = findViewById(R.id.push_setting_view);
mInteractionRelativeLayout.setVisibility(AlivcLiveBase.isSupportLiveMode(AlivcLiveMode.AlivcLiveInteractiveMode) ? View.VISIBLE : View.GONE);
String initUrl = PushDemoTestConstants.getTestPushUrl();
if (!initUrl.isEmpty()) {
mUrl.setText(initUrl);
}
mLivePushSettingView.showArgsContent(true);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
toLive();
}
},3000);
}
private void setClick() {
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 -> {
mFpsConfig = fps.getFps();
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);
SharedPreferenceUtils.setPushMirror(getApplicationContext(), isChecked);
});
mLivePushSettingView.previewMirror.observe(this, isChecked -> {
mAlivcLivePushConfig.setPreviewMirror(isChecked);
SharedPreferenceUtils.setPreviewMirror(getApplicationContext(), 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.resolution.observe(this, resolution -> {
mCurrentResolution = resolution;
});
mLivePushSettingView.autoFocus.observe(this, isChecked -> {
mAlivcLivePushConfig.setAutoFocus(isChecked);
SharedPreferenceUtils.setAutofocus(getApplicationContext(), isChecked);
});
mLivePushSettingView.enableBeauty.observe(this, isChecked -> {
SharedPreferenceUtils.setBeautyOn(getApplicationContext(), isChecked);
});
mLivePushSettingView.videoOnly.observe(this, isChecked -> {
mVideoOnlyPush = isChecked;
mAlivcLivePushConfig.setVideoOnly(mVideoOnlyPush);
});
mLivePushSettingView.audioOnly.observe(this, isChecked -> {
mAudioOnlyPush = isChecked;
mAlivcLivePushConfig.setAudioOnly(mAudioOnlyPush);
});
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.async.observe(this, isChecked -> {
mAsyncValue = isChecked;
});
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 -> {
if (isChecked) {
LogcatHelper.getInstance(getApplicationContext()).start();
} else {
LogcatHelper.getInstance(getApplicationContext()).stop();
}
});
mLivePushSettingView.previewDisplayMode.observe(this, previewDisplayMode -> {
mAlivcLivePushConfig.setPreviewDisplayMode(previewDisplayMode);
SharedPreferenceUtils.setDisplayFit(getApplicationContext(), previewDisplayMode.getPreviewDisplayMode());
});
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);
mOrientationEnum = 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.showWaterMark.observe(this, isShown -> {
if (isShown) {
PushWaterMarkDialog pushWaterMarkDialog = new PushWaterMarkDialog();
pushWaterMarkDialog.setWaterMarkInfo(mWaterMarkInfos);
pushWaterMarkDialog.show(getSupportFragmentManager(), "waterDialog");
}
});
mPublish.setOnClickListener(onClickListener);
mTabArgsLayout.setOnClickListener(onClickListener);
mTabActionLayout.setOnClickListener(onClickListener);
mQr.setOnClickListener(onClickListener);
mBack.setOnClickListener(onClickListener);
mLocalLogTv.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
jump2BackdoorActivity();
return true;
}
});
mLivePushModeRadioGroup.setOnCheckedChangeListener((radioGroup, i) -> {
if (i == R.id.push_mode_interaction) {
//互动模式
mAlivcLivePushConfig.setEnableRTSForInteractiveMode(false);
mAlivcLivePushConfig.setLivePushMode(AlivcLiveMode.AlivcLiveInteractiveMode);
} else if (i == R.id.push_mode_raw_stream) {
//推拉裸流
mAlivcLivePushConfig.setEnableRTSForInteractiveMode(true);
mAlivcLivePushConfig.setLivePushMode(AlivcLiveMode.AlivcLiveInteractiveMode);
} else {
//标准模式
mAlivcLivePushConfig.setEnableRTSForInteractiveMode(false);
mAlivcLivePushConfig.setLivePushMode(AlivcLiveMode.AlivcLiveBasicMode);
}
});
}
private View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.beginPublish) {
toLive();
} else if (id == R.id.qr_code) {
if (ContextCompat.checkSelfPermission(PushConfigActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// Do not have the permission of camera, request it.
ActivityCompat.requestPermissions(PushConfigActivity.this, new String[]{Manifest.permission.CAMERA}, REQ_CODE_PERMISSION);
} else {
// Have gotten the permission
startCaptureActivityForResult();
}
} else if (id == R.id.iv_back) {
finish();
} else if (id == R.id.tab_args_layout) {
mTabArgsView.setVisibility(View.VISIBLE);
mTabActionView.setVisibility(View.INVISIBLE);
mLivePushSettingView.showArgsContent(true);
mInteractionRelativeLayout.setVisibility(AlivcLiveBase.isSupportLiveMode(AlivcLiveMode.AlivcLiveInteractiveMode) ? View.VISIBLE : View.GONE);
} else if (id == R.id.tab_action_layout) {
mTabActionView.setVisibility(View.VISIBLE);
mTabArgsView.setVisibility(View.INVISIBLE);
mLivePushSettingView.showArgsContent(false);
mInteractionRelativeLayout.setVisibility(View.GONE);
}
}
};
private void toLive() {
if (FastClickUtil.isProcessing()) {
return;
}
if (getPushConfig() != null) {
ArrayList<WaterMarkInfo> waterMarkInfos = new ArrayList<>();
if (mLivePushSettingView.enableWaterMark()) {
waterMarkInfos.addAll(mWaterMarkInfos);
}
if (mCurrentResolution == AlivcResolutionEnum.RESOLUTION_SELF_DEFINE) {
AlivcResolutionEnum.RESOLUTION_SELF_DEFINE.setSelfDefineResolution(mLivePushSettingView.getSelfDefineResolutionWidth(), mLivePushSettingView.getSelfDefineResolutionHeight());
mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_SELF_DEFINE);
Log.i("LIVE","LIVECONFIGRESOLUTION_SELF_DEFINE1:"+ mLivePushSettingView.getSelfDefineResolutionWidth());
Log.i("LIVE","LIVECONFIGRESOLUTION_SELF_DEFINE2:"+ mLivePushSettingView.getSelfDefineResolutionHeight());
} else {
mAlivcLivePushConfig.setResolution(mCurrentResolution);
Log.i("LIVE","LIVECONFIGRESOLUTION_SELF_DEFINE3:"+ mCurrentResolution);
}
if (mUrl.getText().toString().contains("rtmp://") || mUrl.getText().toString().contains("artc://")) {
checkModelAndRun(new Runnable() {
@Override
public void run() {
LivePushActivity.startActivity(PushConfigActivity.this, mAlivcLivePushConfig, mUrl.getText().toString(),
mAsyncValue, mAudioOnlyPush, mVideoOnlyPush, mOrientationEnum, mCameraId, isFlash, mAuthTimeStr,
mPrivacyKeyStr, mMixStream, mAlivcLivePushConfig.isExternMainStream(), mLivePushSettingView.enableBeauty(), mFpsConfig,
waterMarkInfos);
Log.i("LIVE","LIVECONFIGmAlivcLivePushConfig:"+ GsonUtils.beanToJSONString(mAlivcLivePushConfig));
Log.i("LIVE","LIVECONFIGmUrl:"+ mUrl.getText().toString());
Log.i("LIVE","LIVECONFIGmAsyncValue:"+ mAsyncValue);
Log.i("LIVE","LIVECONFIGmAudioOnlyPush:"+mAudioOnlyPush );
Log.i("LIVE","LIVECONFIGmVideoOnlyPush:"+ mVideoOnlyPush);
Log.i("LIVE","LIVECONFIGmOrientationEnum:"+mOrientationEnum );
Log.i("LIVE","LIVECONFIGmCameraId:"+ mCameraId);
Log.i("LIVE","LIVECONFIGisFlash:"+ isFlash);
Log.i("LIVE","LIVECONFIGmAuthTimeStr:"+ mAuthTimeStr);
Log.i("LIVE","LIVECONFIGmPrivacyKeyStr:"+ mPrivacyKeyStr);
Log.i("LIVE","LIVECONFIGmMixStream:"+mMixStream );
Log.i("LIVE","LIVECONFIGmAlivcLivePushConfig:"+ mAlivcLivePushConfig.isExternMainStream());
Log.i("LIVE","LIVECONFIGenableBeauty:"+ mLivePushSettingView.enableBeauty());
Log.i("LIVE","LIVECONFIGmFpsConfig:"+mFpsConfig );
Log.i("LIVE","LIVECONFIGwaterMarkInfos:"+GsonUtils.beanToJSONString(waterMarkInfos) );
finish();
}
});
} else {
ToastUtils.show("url format unsupported");
}
}
}
@Override
protected void onResume() {
super.onResume();
mLivePushSettingView.setPushMirror(SharedPreferenceUtils.isPushMirror(getApplicationContext(), DEFAULT_VALUE_PUSH_MIRROR));
mLivePushSettingView.setPreviewMirror(SharedPreferenceUtils.isPreviewMirror(getApplicationContext(), DEFAULT_VALUE_PREVIEW_MIRROR));
mLivePushSettingView.setAutoFocus(SharedPreferenceUtils.isAutoFocus(getApplicationContext(), DEFAULT_VALUE_AUTO_FOCUS));
mLivePushSettingView.setBeautyOn(SharedPreferenceUtils.isBeautyOn(getApplicationContext()));
}
private void startCaptureActivityForResult() {
Intent intent = new Intent(PushConfigActivity.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);
}
@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
ToastUtils.show("You must agree the camera permission request before you use the code scan function");
}
}
break;
default:
break;
}
}
private AlivcLivePushConfig getPushConfig() {
if (mUrl.getText().toString().isEmpty()) {
ToastUtils.show(getString(R.string.url_empty));
return null;
}
mAlivcLivePushConfig.setResolution(mDefinition);
mAlivcLivePushConfig.setInitialVideoBitrate(Integer.parseInt(mLivePushSettingView.getInitVideoBitrate()));
mAlivcLivePushConfig.setAudioBitRate(1000 * Integer.parseInt(mLivePushSettingView.getAudioBitrate()));
mAlivcLivePushConfig.setMinVideoBitrate(Integer.parseInt(mLivePushSettingView.getMinVideoBitrate()));
SharedPreferenceUtils.setMinBit(getApplicationContext(), Integer.parseInt(mLivePushSettingView.getMinVideoBitrate()));
mAlivcLivePushConfig.setTargetVideoBitrate(Integer.parseInt(mLivePushSettingView.getTargetVideoBitrate()));
SharedPreferenceUtils.setTargetBit(getApplicationContext(), Integer.parseInt(mLivePushSettingView.getTargetVideoBitrate()));
mAlivcLivePushConfig.setConnectRetryCount(mLivePushSettingView.getRetryCount());
mAlivcLivePushConfig.setConnectRetryInterval(mLivePushSettingView.getRetryInterval());
mAuthTimeStr = mLivePushSettingView.getAuthTime();
mPrivacyKeyStr = mLivePushSettingView.getPrivacyKey();
Uri uri = Uri.parse(mUrl.getText().toString().trim());
String keys = uri.getQueryParameter("auth_key");
mPrivacyKeyStr =keys;
Log.i("BIKAOVIDEO","BIKAOVIDEO:"+mPrivacyKeyStr);
return mAlivcLivePushConfig;
}
private void addWaterMarkInfo() {
//添加三个水印,位置坐标不同
WaterMarkInfo waterMarkInfo = new WaterMarkInfo();
waterMarkInfo.mWaterMarkPath = FileUtil.combinePaths(FileUtil.getInternalFilesFolder(getBaseContext()), "alivc_resource/watermark.png");
WaterMarkInfo waterMarkInfo1 = new WaterMarkInfo();
waterMarkInfo1.mWaterMarkPath = FileUtil.combinePaths(FileUtil.getInternalFilesFolder(getBaseContext()), "alivc_resource/watermark.png");
waterMarkInfo.mWaterMarkCoordY += 0.2;
WaterMarkInfo waterMarkInfo2 = new WaterMarkInfo();
waterMarkInfo2.mWaterMarkPath = FileUtil.combinePaths(FileUtil.getInternalFilesFolder(getBaseContext()), "alivc_resource/watermark.png");
waterMarkInfo2.mWaterMarkCoordY += 0.4;
mWaterMarkInfos.add(waterMarkInfo);
mWaterMarkInfos.add(waterMarkInfo1);
mWaterMarkInfos.add(waterMarkInfo2);
}
@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:
mUrl.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT)); //or do sth
break;
case RESULT_CANCELED:
if (data != null) {
// for some reason camera is not working correctly
mUrl.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
}
break;
default:
break;
}
break;
case LivePushActivity.REQ_CODE_PUSH: {
if (!mLivePushSettingView.getTargetVideoBitrateOnlyEditText().isEmpty() || Integer.parseInt(mLivePushSettingView.getTargetVideoBitrateOnlyHint()) != SharedPreferenceUtils.getTargetBit(getApplicationContext())) {
mLivePushSettingView.setTargetVideoBitrateText(String.valueOf(SharedPreferenceUtils.getTargetBit(getApplicationContext())));
}
if (!mLivePushSettingView.getMinVideoBitrateOnlyEditText().isEmpty() || Integer.parseInt(mLivePushSettingView.getMinVideoBitrateOnlyHint()) != SharedPreferenceUtils.getMinBit(getApplicationContext())) {
mLivePushSettingView.setMinVideoBitrateText(String.valueOf(SharedPreferenceUtils.getMinBit(getApplicationContext())));
}
}
break;
default:
break;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (getCurrentFocus() != null && getCurrentFocus().getWindowToken() != null) {
if (manager == null) {
manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
}
manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
return super.onTouchEvent(event);
}
@Override
protected void onDestroy() {
super.onDestroy();
// SharedPreferenceUtils.clear(getApplicationContext());
mLivePushSettingView.destroy();
}
private void checkModelAndRun(final Runnable runnable) {
runnable.run();
// BeautyMenuMaterial.getInstance().checkModelReady(this, new OnDownloadUICallback() {
// @Override
// public void onDownloadStart(@StringRes int tipsResId) {
// showProgressDialog(tipsResId);
// }
//
// @Override
// public void onDownloadProgress(final float v) {
// }
//
// @Override
// public void onDownloadSuccess() {
// hideProgressDialog();
// runnable.run();
// }
//
// @Override
// public void onDownloadError(@StringRes int tipsResId) {
// hideProgressDialog();
// showErrorTips(tipsResId);
// }
// });
}
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;
}
}
public void showErrorTips(@StringRes int tipsResId) {
Toast.makeText(this, tipsResId, Toast.LENGTH_SHORT).show();
}
private void startDownloadYUV() {
// private PushConfigDialogImpl mPushConfigDialog = new PushConfigDialogImpl();
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 void jump2BackdoorActivity() {
Intent intent = new Intent(this, BackDoorActivity.class);
startActivity(intent);
}
}

View File

@@ -0,0 +1,59 @@
package com.alivc.live.baselive_push.ui;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.alivc.live.baselive_push.R;
import com.alivc.live.baselive_push.adapter.SoundEffectRecyclerViewAdapter;
import com.alivc.live.baselive_push.bean.SoundEffectBean;
import java.util.HashMap;
/**
* 音效设置 Fragment
*/
public class SoundEffectFragment extends Fragment {
private View inflate;
private HashMap<Integer, SoundEffectBean> mDataMap;
private SoundEffectRecyclerViewAdapter.OnSoundEffectItemClickListener mOnSoundEffectItemClickListener;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Bundle arguments = getArguments();
if (arguments != null) {
mDataMap = (HashMap<Integer, SoundEffectBean>) arguments.getSerializable("args");
}
inflate = inflater.inflate(R.layout.fragment_sound_effect, container, false);
return inflate;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView mRecyclerView = inflate.findViewById(R.id.item_recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
SoundEffectRecyclerViewAdapter soundEffectRecyclerViewAdapter = new SoundEffectRecyclerViewAdapter(view.getContext(), mDataMap);
mRecyclerView.setAdapter(soundEffectRecyclerViewAdapter);
soundEffectRecyclerViewAdapter.setOnSoundEffectItemClickListener(position -> {
soundEffectRecyclerViewAdapter.setSelectIndex(position);
if (mOnSoundEffectItemClickListener != null) {
mOnSoundEffectItemClickListener.onSoundEffectItemClick(position);
}
});
}
public void setOnSoundEffectItemClickListener(SoundEffectRecyclerViewAdapter.OnSoundEffectItemClickListener listener) {
this.mOnSoundEffectItemClickListener = listener;
}
}

View File

@@ -0,0 +1,204 @@
package com.alivc.live.baselive_push.ui.widget;
/**
* **********************
*
* @Author bug machine
* 创建时间: 2026/2/2 14:29
* 用途
* **********************
*/
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
public class BabeLiveRingLoadingView extends View {
// 画笔
private final Paint ringPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint ringPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint ringPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
// private final Paint logoPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// private final Paint liveTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 颜色定义
private final int ORANGE = Color.parseColor("#FF782D");
private final int WHITE = Color.WHITE;
// 动画参数
private float ringSweepAngle = 0f;
private ValueAnimator animator;
private ValueAnimator animator1;
private ValueAnimator animator2;
private float ringSweepAngle1 = 0f;
private float ringSweepAngle2 = 0f;
public BabeLiveRingLoadingView(Context context) {
this(context, null);
}
public BabeLiveRingLoadingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BabeLiveRingLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// 初始化圆环画笔
ringPaint.setColor(ORANGE);
ringPaint.setStyle(Paint.Style.STROKE);
ringPaint.setStrokeWidth(12f);
ringPaint.setStrokeCap(Paint.Cap.ROUND);
ringPaint.setAlpha(160);
ringPaint1.setColor(ORANGE);
ringPaint1.setStyle(Paint.Style.STROKE);
ringPaint1.setStrokeWidth(10f);
ringPaint1.setStrokeCap(Paint.Cap.ROUND);
ringPaint1.setAlpha(150);
ringPaint2.setColor(ORANGE);
ringPaint2.setStyle(Paint.Style.STROKE);
ringPaint2.setStrokeWidth(10f);
ringPaint2.setStrokeCap(Paint.Cap.ROUND);
ringPaint2.setAlpha(140);
//
// // 初始化Logo画笔
// logoPaint.setColor(ORANGE);
//
// // 初始化LIVE文字画笔
// liveTextPaint.setColor(WHITE);
// liveTextPaint.setTextSize(48f);
// liveTextPaint.setTextAlign(Paint.Align.CENTER);
startAnima();
}
private void startAnima() {
startAnimation();
startAnimation1();
startAnimation2();
}
private void stopAnima() {
if(animator!=null){
animator.cancel();
animator = null;
}
if(animator1!=null){
animator1.cancel();
animator1 = null;
}
if(animator2!=null){
animator2.cancel();
animator2 = null;
}
}
private void startAnimation() {
animator = ValueAnimator.ofFloat(0f, 360f);
animator.setDuration(1200);
animator.setInterpolator(new LinearInterpolator());
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.addUpdateListener(animation -> {
ringSweepAngle = (float) animation.getAnimatedValue();
invalidate();
});
animator.start();
}
private void startAnimation1() {
animator1 = ValueAnimator.ofFloat(360f, 0f);
animator1.setDuration(1500);
animator1.setInterpolator(new DecelerateInterpolator());
animator1.setRepeatCount(ValueAnimator.INFINITE);
animator1.addUpdateListener(animation -> {
ringSweepAngle1 = (float) animation.getAnimatedValue();
invalidate();
});
animator1.start();
}
private void startAnimation2() {
animator2 = ValueAnimator.ofFloat(0f, 360f);
animator2.setDuration(1800);
animator2.setInterpolator(new AccelerateInterpolator());
animator2.setRepeatCount(ValueAnimator.INFINITE);
animator2.addUpdateListener(animation -> {
ringSweepAngle2 = (float) animation.getAnimatedValue();
invalidate();
});
animator2.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
int logoSize = Math.min(getWidth(), getHeight()) * 3 / 5;
int ringRadius = Math.max(logoSize / 2 + 40, getWidth() / 2 - 30);
int ringRadius1 = Math.max(logoSize / 2 + 25, getWidth() / 2 - 60);
int ringRadius2 = Math.max(logoSize / 2, getWidth() / 2 - 90);
// 绘制背景旋转圆环
RectF ringRect = new RectF(
centerX - ringRadius,
centerY - ringRadius,
centerX + ringRadius,
centerY + ringRadius
);
// 绘制背景旋转圆环
RectF ringRect1 = new RectF(
centerX - ringRadius1,
centerY - ringRadius1,
centerX + ringRadius1,
centerY + ringRadius1
);
// 绘制背景旋转圆环
RectF ringRect2 = new RectF(
centerX - ringRadius2,
centerY - ringRadius2,
centerX + ringRadius2,
centerY + ringRadius2
);
canvas.drawArc(ringRect, -90, ringSweepAngle, false, ringPaint);
canvas.drawArc(ringRect1, 0, ringSweepAngle1, false, ringPaint1);
canvas.drawArc(ringRect2, 90, ringSweepAngle2, false, ringPaint2);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (animator != null) animator.cancel();
}
}

View File

@@ -0,0 +1,280 @@
package com.alivc.live.baselive_push.ui.widget;
import static com.alivc.live.pusher.AlivcLivePushConstants.DEFAULT_VALUE_PREVIEW_MIRROR;
import static com.alivc.live.pusher.AlivcLivePushConstants.DEFAULT_VALUE_PUSH_MIRROR;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import com.alivc.live.commonui.avdialog.AVLiveBaseBottomSheetDialog;
import com.alivc.live.commonui.configview.LivePushResolutionView;
import com.alivc.live.baselive_push.R;
import com.alivc.live.commonbiz.SharedPreferenceUtils;
import com.alivc.live.pusher.AlivcPreviewDisplayMode;
import com.alivc.live.pusher.AlivcQualityModeEnum;
import com.alivc.live.commonutils.DensityUtil;
import com.alivc.live.pusher.AlivcResolutionEnum;
public class PushMoreConfigBottomSheetLive extends AVLiveBaseBottomSheetDialog implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
private EditText mTargetRate = null;
private EditText mMinRate = null;
private Switch mPushMirror;
private Switch mPreviewMirror;
private TextView mPreviewMode;
private OnMoreConfigListener mOnMoreConfigListener;
private int mQualityMode = 0;
private int mDisplayFit;
private View mConfigListLn;
private View mOrientationLn;
private View mRootView;
private View mDisplayModeFull;
private View mDisplayModeFit;
private View mDisplayModeCut;
private View mOrientationBack;
private LivePushResolutionView mLivePushResolutionView;
public PushMoreConfigBottomSheetLive(Context context) {
super(context);
}
public PushMoreConfigBottomSheetLive(Context context, int theme) {
super(context, theme);
}
protected PushMoreConfigBottomSheetLive(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
@Override
protected View getContentView() {
mRootView = getLayoutInflater().inflate(R.layout.push_more, null, false);
mTargetRate = mRootView.findViewById(R.id.target_rate_edit);
mMinRate = mRootView.findViewById(R.id.min_rate_edit);
mPushMirror = mRootView.findViewById(R.id.push_mirror_switch);
mPreviewMirror = mRootView.findViewById(R.id.preview_mirror_switch);
mPreviewMode = mRootView.findViewById(R.id.setting_display_mode);
mPushMirror.setChecked(SharedPreferenceUtils.isPushMirror(getContext().getApplicationContext(), DEFAULT_VALUE_PUSH_MIRROR));
mPreviewMirror.setChecked(SharedPreferenceUtils.isPreviewMirror(getContext().getApplicationContext(), DEFAULT_VALUE_PREVIEW_MIRROR));
mPushMirror.setOnCheckedChangeListener(this);
mPreviewMirror.setOnCheckedChangeListener(this);
mPreviewMode.setOnClickListener(this);
mTargetRate.setText(String.valueOf(SharedPreferenceUtils.getTargetBit(getContext().getApplicationContext())));
mMinRate.setText(String.valueOf(SharedPreferenceUtils.getMinBit(getContext().getApplicationContext())));
mTargetRate.setHint(String.valueOf(SharedPreferenceUtils.getHintTargetBit(getContext().getApplicationContext())));
mMinRate.setHint(String.valueOf(SharedPreferenceUtils.getHintMinBit(getContext().getApplicationContext())));
if (mQualityMode != AlivcQualityModeEnum.QM_CUSTOM.getQualityMode()) {
mTargetRate.setFocusable(false);
mMinRate.setFocusable(false);
mTargetRate.setFocusableInTouchMode(false);
mMinRate.setFocusableInTouchMode(false);
mMinRate.setTextColor(Color.GRAY);
mTargetRate.setTextColor(Color.GRAY);
} else {
mMinRate.setBackgroundColor(Color.WHITE);
mTargetRate.setBackgroundColor(Color.WHITE);
mTargetRate.setFocusable(true);
mMinRate.setFocusable(true);
mTargetRate.setFocusableInTouchMode(true);
mMinRate.setFocusableInTouchMode(true);
mTargetRate.requestFocus();
mMinRate.requestFocus();
}
mConfigListLn = mRootView.findViewById(R.id.config_list);
mOrientationLn = mRootView.findViewById(R.id.orientation_list);
mDisplayModeFull = mRootView.findViewById(R.id.full);
mDisplayModeFit = mRootView.findViewById(R.id.fit);
mDisplayModeCut = mRootView.findViewById(R.id.cut);
mOrientationBack = mRootView.findViewById(R.id.back);
mDisplayModeFull.setOnClickListener(this);
mDisplayModeFit.setOnClickListener(this);
mDisplayModeCut.setOnClickListener(this);
mOrientationBack.setOnClickListener(this);
mRootView.findViewById(R.id.cancel).setOnClickListener(this);
mRootView.findViewById(R.id.confirm_button).setOnClickListener(this);
mDisplayFit = SharedPreferenceUtils.getDisplayFit(getContext().getApplicationContext(),
AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FIT.getPreviewDisplayMode());
if (mDisplayFit == AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_SCALE_FILL.getPreviewDisplayMode()) {
onClick(mDisplayModeFull);
} else if (mDisplayFit == AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FIT.getPreviewDisplayMode()) {
onClick(mDisplayModeFit);
} else if (mDisplayFit == AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FILL.getPreviewDisplayMode()) {
onClick(mDisplayModeCut);
}
mLivePushResolutionView = mRootView.findViewById(R.id.live_push_resolution);
mLivePushResolutionView.setOnResolutionChangedListener(resolutionEnum -> {
if (mOnMoreConfigListener != null) {
mOnMoreConfigListener.onResolutionChanged(resolutionEnum);
}
});
return mRootView;
}
@Override
protected ViewGroup.LayoutParams getContentLayoutParams() {
return new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DensityUtil.dip2px(getContext(), 304));
}
public void setQualityMode(int mode) {
this.mQualityMode = mode;
if (mTargetRate == null || mMinRate == null) {
return;
}
if (mQualityMode != AlivcQualityModeEnum.QM_CUSTOM.getQualityMode()) {
mTargetRate.setFocusable(false);
mMinRate.setFocusable(false);
mTargetRate.setFocusableInTouchMode(false);
mMinRate.setFocusableInTouchMode(false);
mMinRate.setBackgroundColor(Color.GRAY);
mTargetRate.setBackgroundColor(Color.GRAY);
} else {
mMinRate.setBackgroundColor(Color.WHITE);
mTargetRate.setBackgroundColor(Color.WHITE);
mTargetRate.setFocusable(true);
mMinRate.setFocusable(true);
mTargetRate.setFocusableInTouchMode(true);
mMinRate.setFocusableInTouchMode(true);
mTargetRate.requestFocus();
mMinRate.requestFocus();
}
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.confirm_button || id == R.id.cancel) {
dismiss();
} else if (id == R.id.setting_display_mode) {
mConfigListLn.setVisibility(View.GONE);
mOrientationLn.setVisibility(View.VISIBLE);
} else if (id == R.id.back) {
mOrientationLn.setVisibility(View.GONE);
mConfigListLn.setVisibility(View.VISIBLE);
} else if (id == R.id.full) {
mRootView.findViewById(R.id.cut_fit).setVisibility(View.GONE);
mRootView.findViewById(R.id.cut_selected).setVisibility(View.GONE);
mRootView.findViewById(R.id.full_fit).setVisibility(View.VISIBLE);
mPreviewMode.setText(R.string.display_mode_full);
if (mOnMoreConfigListener != null) {
mOnMoreConfigListener.onDisplayModeChanged(AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_SCALE_FILL);
}
SharedPreferenceUtils.setDisplayFit(getContext(), AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_SCALE_FILL.getPreviewDisplayMode());
} else if (id == R.id.fit) {
mRootView.findViewById(R.id.full_fit).setVisibility(View.GONE);
mRootView.findViewById(R.id.cut_selected).setVisibility(View.GONE);
mRootView.findViewById(R.id.cut_fit).setVisibility(View.VISIBLE);
mPreviewMode.setText(R.string.display_mode_fit);
if (mOnMoreConfigListener != null) {
mOnMoreConfigListener.onDisplayModeChanged(AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FIT);
}
SharedPreferenceUtils.setDisplayFit(getContext(), AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FIT.getPreviewDisplayMode());
} else if (id == R.id.cut) {
mRootView.findViewById(R.id.full_fit).setVisibility(View.GONE);
mRootView.findViewById(R.id.cut_fit).setVisibility(View.GONE);
mRootView.findViewById(R.id.cut_selected).setVisibility(View.VISIBLE);
mPreviewMode.setText(R.string.display_mode_cut);
if (mOnMoreConfigListener != null) {
mOnMoreConfigListener.onDisplayModeChanged(AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FILL);
}
SharedPreferenceUtils.setDisplayFit(getContext(), AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FILL.getPreviewDisplayMode());
}
}
public void setOnMoreConfigListener(OnMoreConfigListener onMoreConfigListener) {
mOnMoreConfigListener = onMoreConfigListener;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int id = buttonView.getId();
try {
if (id == R.id.push_mirror_switch) {
if (mOnMoreConfigListener != null) {
mOnMoreConfigListener.onPushMirror(isChecked);
}
SharedPreferenceUtils.setPushMirror(getContext().getApplicationContext(), isChecked);
} else if (id == R.id.preview_mirror_switch) {
if (mOnMoreConfigListener != null) {
mOnMoreConfigListener.onPreviewMirror(isChecked);
}
SharedPreferenceUtils.setPreviewMirror(getContext().getApplicationContext(), isChecked);
} else if (id == R.id.autofocus_switch) {
if (mOnMoreConfigListener != null) {
mOnMoreConfigListener.onAutoFocus(isChecked);
}
SharedPreferenceUtils.setAutofocus(getContext().getApplicationContext(), isChecked);
}
} catch (IllegalStateException e) {
showDialog(getContext(), e.getMessage());
}
}
private static void showDialog(final Context context, final String message) {
if (context == null || message == null) {
return;
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
if (context != null) {
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle(context.getString(R.string.dialog_title));
dialog.setMessage(message);
dialog.setNegativeButton(context.getString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
dialog.show();
}
}
});
}
public int getResolutionWidth() {
return mLivePushResolutionView.getSelfDefineWidth();
}
public int getResolutionHeight() {
return mLivePushResolutionView.getSelfDefineHeight();
}
public interface OnMoreConfigListener {
void onDisplayModeChanged(AlivcPreviewDisplayMode mode);
void onPushMirror(boolean state);
void onPreviewMirror(boolean state);
void onAutoFocus(boolean state);
void onAddDynamic();
void onRemoveDynamic();
void onResolutionChanged(AlivcResolutionEnum resolutionEnum);
}
}

View File

@@ -0,0 +1,277 @@
package com.alivc.live.baselive_push.ui.widget;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.Switch;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.alivc.live.commonui.avdialog.AVLiveBaseBottomSheetDialog;
import com.alivc.live.commonui.bean.MusicInfo;
import com.alivc.live.baselive_push.R;
import com.alivc.live.baselive_push.adapter.MusicSelectAdapter;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class PushMusicBottomSheetLive extends AVLiveBaseBottomSheetDialog implements View.OnClickListener, CompoundButton.OnCheckedChangeListener, SeekBar.OnSeekBarChangeListener, MusicSelectAdapter.OnItemClick {
private OnMusicSelectListener mOnMusicSelectListener;
private MusicSelectAdapter mMusicAdapter;
private Switch mEarsBackSwitch;
private Switch mAudioDenoiseSwitch;
private Switch mAudioIntelligentDenoiseSwitch;
private View mIconVolumeView;
private View mIconPlayView;
private View mIconLoopView;
private SeekBar mAccompanimentBar;
private SeekBar mVoiceBar;
private ProgressBar mMusicProgress;
private TextView mMusicName;
private TextView mCurrentTime;
private TextView mDuration;
public PushMusicBottomSheetLive(Context context) {
super(context);
}
public PushMusicBottomSheetLive(Context context, int theme) {
super(context, theme);
}
protected PushMusicBottomSheetLive(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
@Override
protected View getContentView() {
View rootView = getLayoutInflater().inflate(R.layout.push_music_sheet, null, false);
mEarsBackSwitch = rootView.findViewById(R.id.ears_back);
mAudioDenoiseSwitch = rootView.findViewById(R.id.audio_noise);
mAudioIntelligentDenoiseSwitch = rootView.findViewById(R.id.audio_intelligent_denoise);
mEarsBackSwitch.setOnCheckedChangeListener(this);
mAudioDenoiseSwitch.setOnCheckedChangeListener(this);
mAudioIntelligentDenoiseSwitch.setOnCheckedChangeListener(this);
mIconVolumeView = rootView.findViewById(R.id.img_volume);
mIconPlayView = rootView.findViewById(R.id.img_play);
mIconLoopView = rootView.findViewById(R.id.img_loop);
rootView.findViewById(R.id.cancel).setOnClickListener(this);
rootView.findViewById(R.id.confirm_button).setOnClickListener(this);
mIconVolumeView.setOnClickListener(this);
mIconPlayView.setOnClickListener(this);
mIconLoopView.setOnClickListener(this);
mAccompanimentBar = rootView.findViewById(R.id.accompaniment_seekbar);
mVoiceBar = rootView.findViewById(R.id.voice_seekbar);
mAccompanimentBar.setOnSeekBarChangeListener(this);
mVoiceBar.setOnSeekBarChangeListener(this);
mMusicProgress = rootView.findViewById(R.id.resolution_seekbar);
mMusicName = rootView.findViewById(R.id.music_name);
mCurrentTime = rootView.findViewById(R.id.tv_current_time);
mDuration = rootView.findViewById(R.id.tv_duration_time);
updateButton(false);
RecyclerView recyclerView = rootView.findViewById(R.id.music_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
if (mMusicAdapter == null) {
mMusicAdapter = new MusicSelectAdapter(getContext());
recyclerView.setAdapter(mMusicAdapter);
mMusicAdapter.setOnItemClick(this::onItemClick);
}
return rootView;
}
@Override
protected ViewGroup.LayoutParams getContentLayoutParams() {
return new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public void onClick(View view) {
int id = view.getId();
try {
if (id == R.id.img_play) {
boolean pauseSelected = mIconPlayView.isSelected();
mIconPlayView.setSelected(!pauseSelected);
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onBGPlay(!pauseSelected);
}
} else if (id == R.id.img_loop) {
boolean loopSelected = mIconLoopView.isSelected();
mIconLoopView.setSelected(!loopSelected);
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onBGLoop(!loopSelected);
}
} else if (id == R.id.img_volume) {
boolean isSelect = mIconVolumeView.isSelected();
mIconVolumeView.setSelected(!isSelect);
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onMute(!isSelect);
}
mAccompanimentBar.setEnabled(isSelect);
mVoiceBar.setEnabled(isSelect);
} else if (id == R.id.cancel || id == R.id.confirm_button) {
dismiss();
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int id = buttonView.getId();
if (id == R.id.ears_back) {
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onBGMEarsBack(isChecked);
}
} else if (id == R.id.audio_noise) {
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onAudioNoise(isChecked);
}
updateAudioDenoiseSwitchState();
} else if (id == R.id.audio_intelligent_denoise) {
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onAudioIntelligentNoise(isChecked);
}
updateAudioDenoiseSwitchState();
}
}
// 使用智能降噪,需关闭普通降噪;两者功能互斥使用
private void updateAudioDenoiseSwitchState() {
if (mAudioDenoiseSwitch == null || mAudioIntelligentDenoiseSwitch == null) {
return;
}
boolean useCustom = mAudioDenoiseSwitch.isChecked();
boolean useIntelligent = mAudioIntelligentDenoiseSwitch.isChecked();
if (!useCustom && !useIntelligent) {
mAudioDenoiseSwitch.setEnabled(true);
mAudioIntelligentDenoiseSwitch.setEnabled(true);
} else if (useCustom && !useIntelligent) {
mAudioIntelligentDenoiseSwitch.setEnabled(false);
} else if (!useCustom && useIntelligent) {
mAudioDenoiseSwitch.setEnabled(false);
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
try {
int seekBarId = seekBar.getId();
if (mAccompanimentBar.getId() == seekBarId) {
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onBGMVolume(progress);
}
} else if (mVoiceBar.getId() == seekBarId) {
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onCaptureVolume(progress);
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
public void updateProgress(long progress, long totalTime) {
mDuration.setText(formatTimeFromMs(totalTime));
mCurrentTime.setText(formatTimeFromMs(progress));
mMusicProgress.setProgress((int) progress);
mMusicProgress.setMax((int) totalTime);
}
private void updateButtonState(boolean bool) {
updateButton(bool);
mIconPlayView.setSelected(bool);
}
private void updateButton(boolean bool) {
mIconVolumeView.setEnabled(bool);
mIconPlayView.setEnabled(bool);
mIconLoopView.setEnabled(bool);
if (!bool) {
mAccompanimentBar.setEnabled(false);
mVoiceBar.setEnabled(false);
} else {
mAccompanimentBar.setEnabled(!mIconVolumeView.isSelected());
mVoiceBar.setEnabled(!mIconVolumeView.isSelected());
}
}
public void setOnMusicSelectListener(OnMusicSelectListener onMusicSelectListener) {
mOnMusicSelectListener = onMusicSelectListener;
}
@Override
public void onItemClick(MusicInfo musicInfo, int position) {
updateButtonState(position > 0);
if (musicInfo != null) {
setPlayMusicUiState(musicInfo);
if (mOnMusicSelectListener != null) {
mOnMusicSelectListener.onBgResource(musicInfo.getPath());
}
}
}
private void setPlayMusicUiState(@NonNull MusicInfo musicInfo) {
mMusicName.setText(musicInfo.getMusicName());
mMusicProgress.setProgress(0);
}
public interface OnMusicSelectListener {
void onBGMEarsBack(boolean state);
void onAudioNoise(boolean state);
void onEarphone(boolean state);
void onAudioIntelligentNoise(boolean state);
void onBGPlay(boolean state);
void onBgResource(String path);
void onBGLoop(boolean state);
void onMute(boolean state);
void onCaptureVolume(int progress);
void onBGMVolume(int progress);
}
private static String formatTimeFromMs(long ms) {
SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
String hms = formatter.format(ms);
return hms;
}
}

View File

@@ -0,0 +1,130 @@
package com.alivc.live.baselive_push.ui.widget;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentTransaction;
import com.alivc.live.baselive_push.R;
import com.alivc.live.baselive_push.adapter.OnSoundEffectChangedListener;
import com.alivc.live.baselive_push.bean.SoundEffectBean;
import com.alivc.live.baselive_push.ui.SoundEffectFragment;
import com.google.android.material.tabs.TabLayout;
/**
* 音效 View
*/
public class SoundEffectView extends FrameLayout {
private SoundEffectFragment mSoundEffectChangeVoiceFragment;
private SoundEffectFragment mSoundEffectReverbFragment;
private Fragment mCurrentFragment;
private OnSoundEffectChangedListener mOnSoundEffectChangedListener;
public SoundEffectView(@NonNull Context context) {
super(context);
init(context);
}
public SoundEffectView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SoundEffectView(@NonNull 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_sound_effect_view, this, true);
initFragment();
initTabLayout();
}
private void initFragment() {
mSoundEffectChangeVoiceFragment = new SoundEffectFragment();
Bundle changeVoiceBundle = new Bundle();
changeVoiceBundle.putSerializable("args", SoundEffectBean.SoundEffectChangeVoiceBean.getLivePushSoundEffectChangeVoice());
mSoundEffectChangeVoiceFragment.setArguments(changeVoiceBundle);
mSoundEffectReverbFragment = new SoundEffectFragment();
Bundle reverbBundle = new Bundle();
reverbBundle.putSerializable("args",SoundEffectBean.SoundEffectReverb.getLivePushSoundEffectReverb());
mSoundEffectReverbFragment.setArguments(reverbBundle);
switchFragment(mSoundEffectChangeVoiceFragment);
mSoundEffectChangeVoiceFragment.setOnSoundEffectItemClickListener(position -> {
if (mOnSoundEffectChangedListener != null) {
mOnSoundEffectChangedListener.onSoundEffectChangeVoiceModeSelected(position);
}
});
mSoundEffectReverbFragment.setOnSoundEffectItemClickListener(position -> {
if (mOnSoundEffectChangedListener != null) {
mOnSoundEffectChangedListener.onSoundEffectRevertBSelected(position);
}
});
}
private void initTabLayout() {
TabLayout mTabLayout = findViewById(R.id.tab_layout);
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
switch (tab.getPosition()) {
case 0://变声
switchFragment(mSoundEffectChangeVoiceFragment);
break;
case 1://环境音
switchFragment(mSoundEffectReverbFragment);
break;
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void switchFragment(Fragment targetFragment) {
if (mCurrentFragment == targetFragment) {
return;
}
FragmentTransaction fragmentTransaction = ((FragmentActivity) getContext()).getSupportFragmentManager().beginTransaction();
if (!targetFragment.isAdded()) {
if (mCurrentFragment != null) {
fragmentTransaction.hide(mCurrentFragment);
}
fragmentTransaction
.add(R.id.frame_layout, targetFragment)
.commit();
} else {
if (mCurrentFragment != null) {
fragmentTransaction.hide(mCurrentFragment);
}
fragmentTransaction
.show(targetFragment)
.commit();
}
mCurrentFragment = targetFragment;
}
public void setOnSoundEffectChangedListener(OnSoundEffectChangedListener listener) {
this.mOnSoundEffectChangedListener = listener;
}
}

View File

@@ -0,0 +1,44 @@
package com.alivc.live.baselive_push.ui.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
/**
* Created by kiun_2007 on 2018/3/29.
*/
public class StatusLayout extends LinearLayout {
public StatusLayout(Context context) {
this(context, null);
}
public StatusLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public StatusLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
@Override
protected void onAttachedToWindow() {
ViewGroup.LayoutParams lp = this.getLayoutParams();
lp.width = -1;
lp.height = getStatusBarHeight(getContext());
this.setLayoutParams(lp);
super.onAttachedToWindow();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/push_info_on"/>
<item android:state_selected="false" android:drawable="@drawable/push_info_on"/>
</selector>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/sound_effect_background" />
<size android:width="32dp" android:height="32dp" />
</shape>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false">
<shape android:shape="rectangle">
<corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp" />
<solid android:color="@android:color/white" />
<stroke android:width="1dp" android:color="@color/switch_bar_on_color" />
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="rectangle">
<corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp" />
<solid android:color="@color/switch_bar_on_color" />
<stroke android:width="1dp" android:color="@color/switch_bar_on_color" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false">
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
<stroke android:width="1dp" android:color="@color/switch_bar_on_color" />
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="rectangle">
<solid android:color="@color/switch_bar_on_color" />
<stroke android:width="1dp" android:color="@color/switch_bar_on_color" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/setting_more_on"/>
<item android:state_selected="false" android:drawable="@drawable/setting_more_on"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/loop_on"/>
<item android:state_selected="false" android:drawable="@drawable/loop_off"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/music_play"/>
<item android:state_selected="false" android:drawable="@drawable/music_pause"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/mute_on"/>
<item android:state_selected="false" android:drawable="@drawable/mute_off"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/preview_on"/>
<item android:state_selected="false" android:drawable="@drawable/preview_off"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/push_on"/>
<item android:state_selected="false" android:drawable="@drawable/push_off"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/repush_off"/>
<item android:state_selected="false" android:drawable="@drawable/repush_off"/>
</selector>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false">
<shape android:shape="rectangle">
<corners android:topRightRadius="5dp" android:bottomRightRadius="5dp" />
<solid android:color="@android:color/white" />
<stroke android:width="1dp" android:color="@color/switch_bar_on_color" />
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="rectangle">
<corners android:topRightRadius="5dp" android:bottomRightRadius="5dp" />
<solid android:color="@color/switch_bar_on_color" />
<stroke android:width="1dp" android:color="@color/switch_bar_on_color" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/flash_on"/>
<item android:state_selected="false" android:drawable="@drawable/flash_off"/>
</selector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="8dp" />
<solid android:color="#1C1D22" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="@dimen/alivc_common_5"/>
<solid android:color="@color/text_true_color"/>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/push_pause"/>
<item android:state_selected="false" android:drawable="@drawable/push_pause"/>
</selector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#4DCFE1"/>
<item android:state_selected="false" android:color="@color/text_black"/>
</selector>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 互动模式下的预览view -->
<FrameLayout
android:id="@+id/preview_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/alivc_color_black"
android:visibility="gone" />
<!-- 普通模式默认下的预览view -->
<SurfaceView
android:id="@+id/preview_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/tv_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:ignore="MissingDefaultResource">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/item_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,34 @@
<?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:id="@+id/item_root"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/alivc_common_padding_14"
android:layout_marginEnd="@dimen/alivc_common_20"
tools:ignore="MissingDefaultResource">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="@id/item_sound_effect_title"
app:layout_constraintStart_toStartOf="@id/item_sound_effect_title"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/item_sound_effect_title"
android:layout_width="wrap_content"
android:layout_height="@dimen/alivc_common_41"
android:layout_gravity="center"
android:layout_marginTop="@dimen/view_margin_10"
android:textColor="@color/camera_panel_content"
android:textSize="@dimen/camera_panel_content_text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_icon" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,51 @@
<?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="wrap_content"
android:layout_gravity="bottom"
android:background="@color/menu_bg_color"
tools:ignore="MissingDefaultResource">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorFullWidth="false"
app:tabTextColor="@color/camera_panel_content"
app:tabSelectedTextColor="@color/colorBaseStyle"
app:tabIndicatorColor="@color/colorBaseStyle"
app:tabIndicatorHeight="@dimen/alivc_common_padding_2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sound_effect_change_voice"/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sound_effect_reverb"/>
</com.google.android.material.tabs.TabLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="@dimen/alivc_common_padding_1"
android:background="@color/white"
app:layout_constraintTop_toBottomOf="@id/tab_layout" />
<FrameLayout
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/view_margin_20"
android:layout_marginBottom="@dimen/view_margin_20"
app:layout_constraintTop_toBottomOf="@id/tab_layout"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="45dp"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<TextView
android:id="@+id/music_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:textColor="#FCFCFD"
android:textSize="15sp" />
<ImageView
android:id="@+id/music_check"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_gravity="center_vertical|end"
android:src="@drawable/icon_check"
android:visibility="gone" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
</FrameLayout>

View File

@@ -0,0 +1,330 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<com.alivc.live.baselive_push.ui.widget.StatusLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/staticLayout"/>
<FrameLayout
android:id="@+id/title_fy"
android:layout_width="match_parent"
android:layout_below="@id/staticLayout"
android:layout_height="?actionBarSize">
<ImageView
android:id="@+id/exit"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/back_img"
android:layout_centerVertical="true"
android:scaleType="centerInside"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/tv_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/wating_push"
android:textColor="@color/body_txt_color"
android:textSize="18sp" />
</FrameLayout>
<com.alivc.live.commonui.messageview.AutoScrollMessagesView
android:id="@+id/v_messages"
android:layout_below="@id/title_fy"
android:layout_width="match_parent"
android:layout_height="240dp"
android:layout_centerHorizontal="true"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp" />
<ScrollView
android:id="@+id/scrollview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="116dp">
<LinearLayout
android:id="@+id/top_bar_layout"
android:layout_width="42dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/sound_effect_button"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@drawable/icon_sound_effect_background"
android:scaleType="center"
android:src="@drawable/ic_live_push_sound_effect"
app:tint="@color/text_black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_horizontal"
android:text="@string/sound_effect_title"
android:textColor="@color/wheel_text_color_1"
android:textSize="10sp" />
<ImageView
android:id="@+id/beauty_button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="20dp"
android:src="@drawable/beauty_selector" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_horizontal"
android:text="@string/beauty"
android:textColor="@color/wheel_text_color_1"
android:textSize="10sp" />
<ImageView
android:id="@+id/music"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="20dp"
android:src="@drawable/music" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_horizontal"
android:text="@string/backgroud_music"
android:textColor="@color/wheel_text_color_1"
android:textSize="10sp" />
<ImageView
android:id="@+id/flash"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="20dp"
android:src="@drawable/selector_camera_flash" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_horizontal"
android:text="@string/flash"
android:textColor="@color/wheel_text_color_1"
android:textSize="10sp" />
<ImageView
android:id="@+id/camera"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="20dp"
android:src="@drawable/camera_on" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_horizontal"
android:text="@string/camera"
android:textColor="@color/wheel_text_color_1"
android:textSize="10sp" />
<ImageView
android:id="@+id/snapshot"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="20dp"
android:src="@drawable/screenshot" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp"
android:text="@string/snapshot"
android:textColor="@color/wheel_text_color_1"
android:textSize="10sp" />
</LinearLayout>
</ScrollView>
<HorizontalScrollView
android:id="@+id/bottom_scroll"
android:layout_width="match_parent"
android:layout_height="69dp"
android:layout_alignParentBottom="true"
android:background="#66FCFCFD"
android:overScrollMode="never">
<LinearLayout
android:id="@+id/action_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:orientation="horizontal"
android:paddingStart="38dp"
android:paddingEnd="0dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/preview_button"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginEnd="16dp"
android:drawableTop="@drawable/preview_selector"
android:drawablePadding="2dp"
android:ellipsize="end"
android:gravity="center_horizontal"
android:text="@string/stop_preview_button"
android:textColor="@drawable/tools_tip_selector"
android:textSize="10sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/push_button"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:drawableTop="@drawable/push_selector"
android:drawablePadding="2dp"
android:ellipsize="end"
android:gravity="center_horizontal"
android:text="@string/start_push"
android:textColor="@drawable/tools_tip_selector"
android:textSize="10sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/opera_button"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:drawableTop="@drawable/stop_selector"
android:drawablePadding="2dp"
android:ellipsize="end"
android:gravity="center_horizontal"
android:text="@string/pause_button"
android:textColor="@drawable/tools_tip_selector"
android:textSize="10sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/restart_button"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:drawableTop="@drawable/repush_selector"
android:drawablePadding="2dp"
android:ellipsize="end"
android:gravity="center_horizontal"
android:text="@string/repush_button"
android:textColor="@drawable/tools_tip_selector"
android:textSize="10sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/more"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:drawableTop="@drawable/more_setting_selector"
android:drawablePadding="2dp"
android:ellipsize="end"
android:gravity="center_horizontal"
android:text="@string/more_setting_button"
android:textColor="@drawable/tools_tip_selector"
android:textSize="10sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/network_detect"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:drawableTop="@drawable/live_network_detect"
android:drawablePadding="2dp"
android:ellipsize="end"
android:gravity="center_horizontal"
android:text="@string/network_detect"
android:textColor="@drawable/tools_tip_selector"
android:textSize="10sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/data"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:drawableTop="@drawable/data_selector"
android:drawablePadding="2dp"
android:ellipsize="end"
android:gravity="center_horizontal"
android:text="@string/data_args"
android:textColor="@drawable/tools_tip_selector"
android:textSize="10sp" />
</LinearLayout>
</HorizontalScrollView>
<com.alivc.live.baselive_push.ui.widget.SoundEffectView
android:id="@+id/sound_effect_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:visibility="gone" />
<com.aliyunsdk.queen.menu.QueenBeautyMenu
android:id="@+id/beauty_beauty_menuPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:visibility="gone" />
<LinearLayout
android:id="@+id/layout_configuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/bottom_scroll"
android:orientation="vertical"
android:padding="10dp">
<com.alivc.live.commonui.widgets.LivePushTextSwitch
android:id="@+id/btn_show_custom_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.alivc.live.commonui.widgets.LivePushTextSwitch
android:id="@+id/btn_local_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_manual_create_egl_context"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="6dp"
android:gravity="center_horizontal"
android:text="@string/manual_create_egl_context_tv"
android:textColor="@color/white"
android:textSize="12dp" />
</LinearLayout>
<com.alivc.live.commonui.seiview.LivePusherSEIView
android:id="@+id/sei_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/layout_configuration"
android:padding="10dp"
android:visibility="gone" />
</RelativeLayout>

View File

@@ -0,0 +1,420 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#1C1D22"
android:orientation="vertical">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/config_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="40dp">
<TextView
android:id="@+id/cancel"
android:layout_width="62dp"
android:layout_height="40dp"
android:layout_gravity="start"
android:gravity="center"
android:text="@string/pull_cancel"
android:textColor="#FCFCFD"
android:textSize="15sp" />
<TextView
android:id="@+id/title"
android:layout_width="62dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/more_setting_button"
android:textColor="#FCFCFD"
android:textSize="15sp" />
<TextView
android:id="@+id/confirm_button"
android:layout_width="62dp"
android:layout_height="40dp"
android:layout_gravity="end"
android:gravity="center"
android:text="@string/btn_confirm"
android:textColor="#4DCFE1"
android:textSize="15sp" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#3A3D48" />
<View
android:layout_width="match_parent"
android:layout_height="19dp"
android:background="#141416" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/target_bitrate"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<EditText
android:id="@+id/target_rate_edit"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="28dp"
android:background="@null"
android:hint="@string/target_rate_value"
android:inputType="number"
android:textColor="#747A8C"
android:textColorHint="#747A8C"
android:textSize="@dimen/font_size_28px" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:text="/kbps"
android:textColor="#747A8C"
android:textSize="11sp" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#3A3D48" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/min_bitrate"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<EditText
android:id="@+id/min_rate_edit"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="28dp"
android:background="@null"
android:hint="@string/min_rate_value"
android:inputType="number"
android:textColor="#747A8C"
android:textColorHint="#747A8C"
android:textSize="@dimen/font_size_28px" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:text="/kbps"
android:textColor="#747A8C"
android:textSize="11sp" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/setting_push_mirror"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<Switch
android:id="@+id/push_mirror_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="end|center_vertical"
android:checked="false"
android:textOff=""
android:textOn=""
android:thumb="@drawable/thumb"
android:track="@drawable/track" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/setting_pre_mirror"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<Switch
android:id="@+id/preview_mirror_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="end|center_vertical"
android:checked="false"
android:textOff=""
android:textOn=""
android:thumb="@drawable/thumb"
android:track="@drawable/track" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/landscape_model"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<TextView
android:id="@+id/setting_display_mode"
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:gravity="center_vertical|end"
android:paddingEnd="23dp"
android:text="@string/quality_resolution_first"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_live_arrow_right" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<com.alivc.live.commonui.configview.LivePushResolutionView
android:id="@+id/live_push_resolution"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:layout_marginBottom="50dp"
android:background="#3A3D48" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:id="@+id/orientation_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="40dp">
<TextView
android:id="@+id/back"
android:drawableLeft="@drawable/ic_blue_back"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="start"
android:gravity="center"
android:text="@string/more_setting_button"
android:textColor="#FCFCFD"
android:textSize="15sp" />
<TextView
android:layout_width="62dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/landscape_model"
android:textColor="#FCFCFD"
android:textSize="15sp" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#3A3D48" />
<View
android:layout_width="match_parent"
android:layout_height="19dp"
android:background="#141416" />
<FrameLayout
android:id="@+id/full"
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/display_mode_full"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<ImageView
android:id="@+id/full_fit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/icon_check" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:id="@+id/fit"
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/display_mode_fit"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<ImageView
android:id="@+id/cut_fit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/icon_check"
android:visibility="gone" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:id="@+id/cut"
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/display_mode_cut"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<ImageView
android:id="@+id/cut_selected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/icon_check"
android:visibility="gone" />
</FrameLayout>
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,373 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#1C1D22"
android:orientation="vertical"
tools:ignore="MissingDefaultResource">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_marginBottom="45dp"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="40dp">
<TextView
android:id="@+id/cancel"
android:layout_width="62dp"
android:layout_height="40dp"
android:layout_gravity="start"
android:gravity="center"
android:text="@string/pull_cancel"
android:textColor="#FCFCFD"
android:textSize="15sp" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/backgroud_music"
android:textColor="#FCFCFD"
android:textSize="15sp" />
<TextView
android:id="@+id/confirm_button"
android:layout_width="62dp"
android:layout_height="40dp"
android:layout_gravity="end"
android:gravity="center"
android:text="@string/btn_confirm"
android:textColor="#4DCFE1"
android:textSize="15sp" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#3A3D48" />
<View
android:layout_width="match_parent"
android:layout_height="19dp"
android:background="#141416" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/open_ears_back"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<Switch
android:id="@+id/ears_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="end|center_vertical"
android:checked="false"
android:textOff=""
android:textOn=""
android:thumb="@drawable/thumb"
android:track="@drawable/track" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/open_audio_denoise"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<Switch
android:id="@+id/audio_noise"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="end|center_vertical"
android:checked="false"
android:textOff=""
android:textOn=""
android:thumb="@drawable/thumb"
android:track="@drawable/track" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/open_audio_intelligent_denoise"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<Switch
android:id="@+id/audio_intelligent_denoise"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="end|center_vertical"
android:checked="false"
android:textOff=""
android:textOn=""
android:thumb="@drawable/thumb"
android:track="@drawable/track" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="370dp"
android:background="#141416">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="330dp"
android:layout_margin="20dp"
android:background="@drawable/shape_music_controll_bg"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:id="@+id/music_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FCFCFD"
android:textSize="16sp" />
<ImageView
android:src="@drawable/ic_live_music_yinfu"
android:layout_marginTop="2dp"
android:layout_gravity="end"
android:layout_width="16dp"
android:layout_height="16dp"/>
<ProgressBar
android:id="@+id/resolution_seekbar"
style="@style/AVLive_ProgressBar_Horizontal_Style"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_marginTop="54dp"
android:max="100"
android:maxHeight="5dp"
android:min="0"
android:minHeight="5dp"
android:progressDrawable="@drawable/live_progress_horizontal_shape" />
<TextView
android:id="@+id/tv_current_time"
android:layout_marginTop="76dp"
android:textColor="#747A8C"
android:textSize="12sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_duration_time"
android:layout_marginTop="76dp"
android:layout_gravity="end"
android:textSize="12sp"
android:textColor="#747A8C"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/img_volume"
android:layout_marginTop="110dp"
android:scaleType="fitXY"
android:src="@drawable/music_volume_selector"
android:layout_width="28dp"
android:layout_height="28dp"/>
<ImageView
android:id="@+id/img_play"
android:src="@drawable/music_play_selector"
android:layout_marginTop="110dp"
android:layout_gravity="center_horizontal"
android:scaleType="fitXY"
android:layout_width="28dp"
android:layout_height="28dp"/>
<ImageView
android:id="@+id/img_loop"
android:layout_marginTop="110dp"
android:layout_gravity="end"
android:src="@drawable/music_loop_selector"
android:scaleType="fitXY"
android:layout_width="28dp"
android:layout_height="28dp"/>
<TextView
android:text="@string/accompaniment"
android:textSize="15sp"
android:layout_marginTop="167dp"
android:textColor="#FCFCFD"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/accompaniment_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="5dp"
android:minHeight="5dp"
android:progress="50"
android:layout_marginTop="200dp"
android:theme="@style/Push_SeekBar_Style" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="246dp"
android:text="@string/voice"
android:textSize="15sp"
android:textColor="#FCFCFD" />
<SeekBar
android:id="@+id/voice_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="279dp"
android:maxHeight="5dp"
android:minHeight="5dp"
android:progress="50"
android:theme="@style/Push_SeekBar_Style" />
</FrameLayout>
</FrameLayout>
<LinearLayout
android:visibility="gone"
android:id="@+id/opera"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_marginLeft="16dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:layout_marginRight="10dp"
android:text="@string/av_resolution_music_operations"
android:textColor="@android:color/black"
android:textSize="@dimen/font_size_28px" />
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="30dp"
android:orientation="horizontal">
<Button
android:id="@+id/pause"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@drawable/left_shape_selector"
android:button="@null"
android:gravity="center"
android:text="@string/pause"
android:textSize="@dimen/font_size_28px" />
<Button
android:id="@+id/stop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@drawable/middle_shape_selector"
android:button="@null"
android:gravity="center"
android:text="@string/start"
android:textSize="@dimen/font_size_28px" />
<Button
android:id="@+id/loop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@drawable/middle_shape_selector"
android:button="@null"
android:gravity="center"
android:text="@string/close_loop"
android:textSize="@dimen/font_size_28px" />
<Button
android:id="@+id/mute"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@drawable/right_shape_selector"
android:button="@null"
android:checked="true"
android:gravity="center"
android:text="@string/open_mute"
android:textSize="@dimen/font_size_28px" />
</RadioGroup>
</LinearLayout>
<TextView
android:text="@string/music_list"
android:textColor="#747A8C"
android:gravity="center_vertical"
android:paddingStart="20dp"
android:layout_width="match_parent"
android:layout_height="39dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/music_list"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View File

@@ -0,0 +1,246 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/main_color"
android:fitsSystemWindows="false"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/main_color"
android:fitsSystemWindows="true"
android:orientation="vertical">
<LinearLayout
android:id="@+id/title_layout"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_back"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerInside"
android:src="@mipmap/back_img" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_32"
android:layout_marginEnd="@dimen/view_margin_10"
android:background="#23262F"
android:orientation="horizontal">
<ImageView
android:id="@+id/qr_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/view_margin_12"
android:background="@drawable/scan_icon" />
<EditText
android:id="@+id/url_editor"
android:layout_width="match_parent"
android:layout_height="@dimen/view_margin_22"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/view_margin_12"
android:background="@null"
android:ellipsize="end"
android:hint="@string/view_string_hint_push_url"
android:singleLine="true"
android:textColor="@color/color_text_grey"
android:textColorHint="@color/color_text_grey"
android:textSize="@dimen/font_size_28px" />
</LinearLayout>
</LinearLayout>
<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>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#3A3D48" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rl_interaction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/model_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_marginEnd="10dp"
android:text="@string/live_push_mode"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_28px" />
<RadioGroup
android:id="@+id/live_push_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/model_title"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatRadioButton
android:id="@+id/push_mode_normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/live_push_mode_normal"
android:textColor="#FCFCFD" />
<androidx.appcompat.widget.AppCompatRadioButton
android:id="@+id/push_mode_interaction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/live_push_mode_interaction"
android:textColor="#FCFCFD" />
<androidx.appcompat.widget.AppCompatRadioButton
android:id="@+id/push_mode_raw_stream"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/live_push_mode_raw_stream"
android:textColor="#FCFCFD" />
</RadioGroup>
</RelativeLayout>
<com.alivc.live.commonui.configview.LivePushSettingView
android:id="@+id/push_setting_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/beginPublish"
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="42dp"
android:background="@drawable/shape_pysh_btn_bg"
android:gravity="center"
android:orientation="horizontal"
android:text="@string/start_button"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_36px"
android:textStyle="normal" />
</LinearLayout>
</ScrollView>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:background="@color/main_color">
<RelativeLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@mipmap/logo_left"/>
<com.alivc.live.baselive_push.ui.widget.BabeLiveRingLoadingView
android:layout_width="300dp"
android:layout_height="300dp"
/>
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="interaction_mode">Interaction Mode</string>
<string name="live_push_mode">LivePush Mode</string>
<string name="start_button">Start pushing</string>
<string name="waiting_download_video_resources">waiting for download external video resources</string>
<string name="live_push_mode_normal">Normal</string>
<string name="live_push_mode_interaction">Interaction</string>
<string name="live_push_mode_raw_stream">RawStream</string>
<string name="success">Success</string>
<string name="failed">Failed</string>
<string name="pause_button">Pause</string>
<string name="connecting_dialog_tips">pushing_wating</string>
<string name="pushing">Ingesting...</string>
<string name="beauty_off_tips">Retouching is disabled. Enable retouching and then retry.</string>
<string name="add_dynamic_failed">Add dynamic failed, id=</string>
<string name="start_preview">Start preview</string>
<string name="stop_preview">Stop preview</string>
<string name="stop_push">Stop pushing</string>
<string name="pause_push">Pause</string>
<string name="resume_push">Resume</string>
<string name="restart_success">Restart successfully</string>
<string name="packet_lost">Package lost</string>
<string name="connection_lost">Connection lost</string>
<string name="network_poor">The network is unstable, please quit or try again</string>
<string name="network_recovery">The network has recovered</string>
<string name="reconnect_start">Start reconnecting</string>
<string name="reconnect_fail">Reconnection failed</string>
<string name="reconnect_success">Reconnection succeed</string>
<string name="senddata_timeout">Sending data timeout</string>
<string name="send_message">Send Message</string>
<string name="bgm_open_failed">BGM File open Failed</string>
<string name="reconnect">Reconnect</string>
<string name="resume_button">Resume</string>
<string name="start_preview_button">Start preview</string>
<string name="wating_push">Waiting for Stream Ingest...</string>
<string name="backgroud_music">Background Music</string>
<string name="flash">Flash</string>
<string name="camera">Camera</string>
<string name="snapshot">Snapshot</string>
<string name="stop_preview_button">Stop preview</string>
<string name="repush_button">Restart pushing</string>
<string name="more_setting_button">More setting</string>
<string name="data_args">Data Metrics</string>
<string name="network_detect">Network Detect</string>
<string name="local_info">Statistics on Local Videos</string>
<string name="close_ears_back">Close Ears</string>
<string name="open_ears_back">Open Ears</string>
<string name="open_audio_denoise">Audio Denoise</string>
<string name="open_audio_intelligent_denoise">Audio Intelligent Denoise</string>
<string name="accompaniment">Accompaniment</string>
<string name="voice">Voice</string>
<string name="av_resolution_music_operations">Music Operations</string>
<string name="pause">Pause</string>
<string name="resume">Resume</string>
<string name="stop">Stop</string>
<string name="start">Start</string>
<string name="close_loop">Close Loop</string>
<string name="open_loop">Open Loop</string>
<string name="close_mute">Close Mute</string>
<string name="open_mute">Open Mute</string>
<string name="music_list">Music List</string>
<string name="no_music">No Music</string>
<string name="internet_music">Internet music</string>
<string name="dialog_title">Error tips</string>
<string name="ok">OK</string>
<string name="setting_audio_441">44.1KHz</string>
<string name="setting_audio_320">32KHz</string>
<string name="setting_audio_160">16KHz</string>
<string name="sound_effect_reverb_off">Off</string>
<string name="sound_effect_reverb_vocal1">Vocal1</string>
<string name="sound_effect_reverb_vocal2">Vocal2</string>
<string name="sound_effect_reverb_bathroom">BathRoom</string>
<string name="sound_effect_reverb_smallroom_bright">SmallRoom(bright)</string>
<string name="sound_effect_reverb_smallroom_dark">SmallRoom(Dark)</string>
<string name="sound_effect_reverb_mediumroom">MediumRoom</string>
<string name="sound_effect_reverb_largeroom">LargeRoom</string>
<string name="sound_effect_reverb_churchhall">ChurchHall</string>
<string name="sound_effect_title">Sound Effect</string>
<string name="sound_effect_change_voice">Change Voice</string>
<string name="sound_effect_reverb">Reverb</string>
<string name="sound_effect_changevoice_off">Off</string>
<string name="sound_effect_changevoice_oldman">Old_man</string>
<string name="sound_effect_changevoice_babyboy">Baby_Boy</string>
<string name="sound_effect_changevoice_babygirl">Baby_Girl</string>
<string name="sound_effect_changevoice_robot">Robot</string>
<string name="sound_effect_changevoice_daimo">Daimo</string>
<string name="sound_effect_changevoice_ktv">KTV</string>
<string name="sound_effect_changevoice_echo">Echo</string>
</resources>

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="interaction_mode">互动模式</string>
<string name="live_push_mode">推流模式</string>
<string name="start_button">进入直播</string>
<string name="waiting_download_video_resources">正在下载外部音视频资源中,请等待</string>
<string name="live_push_mode_normal">普通模式</string>
<string name="live_push_mode_interaction">互动模式</string>
<string name="live_push_mode_raw_stream">推拉裸流</string>
<string name="success">成功</string>
<string name="failed">失败</string>
<string name="pause_button">暂停</string>
<string name="connecting_dialog_tips">推流连接中,请稍后</string>
<string name="pushing">推流中</string>
<string name="beauty_off_tips">美颜开关关闭,请在设置开启后重试...</string>
<string name="add_dynamic_failed">添加贴纸失败, id=</string>
<string name="start_preview">开始预览</string>
<string name="stop_preview">停止预览</string>
<string name="stop_push">停止推流</string>
<string name="pause_push">暂停</string>
<string name="resume_push">恢复</string>
<string name="restart_success">重启成功</string>
<string name="packet_lost">推流丢包通知</string>
<string name="connection_lost">推流已断开</string>
<string name="network_poor">网络差,请退出或者重连</string>
<string name="network_recovery">网络恢复</string>
<string name="reconnect_start">重连开始</string>
<string name="reconnect_fail">重连失败</string>
<string name="reconnect_success">重连成功</string>
<string name="senddata_timeout">发送数据超时</string>
<string name="send_message">发送消息</string>
<string name="bgm_open_failed">音乐文件打开失败</string>
<string name="reconnect">重连</string>
<string name="resume_button">恢复</string>
<string name="start_preview_button">开始预览</string>
<string name="wating_push">未推流</string>
<string name="backgroud_music">背景音乐</string>
<string name="flash">闪光灯</string>
<string name="camera">摄像头</string>
<string name="snapshot">截图</string>
<string name="stop_preview_button">停止预览</string>
<string name="repush_button">重新推流</string>
<string name="more_setting_button">更多设置</string>
<string name="data_args">数据指标</string>
<string name="network_detect">网络探测</string>
<string name="local_info">本地视频统计信息</string>
<string name="close_ears_back">关耳返</string>
<string name="open_ears_back">开耳返</string>
<string name="open_audio_denoise">音频降噪</string>
<string name="open_audio_intelligent_denoise">音频智能降噪</string>
<string name="accompaniment">伴奏音量</string>
<string name="voice">人声音量</string>
<string name="av_resolution_music_operations">音乐操作</string>
<string name="pause">暂停</string>
<string name="resume">恢复</string>
<string name="stop">停止</string>
<string name="start">开始</string>
<string name="close_loop">关循环</string>
<string name="open_loop">开循环</string>
<string name="close_mute">关静音</string>
<string name="open_mute">开静音</string>
<string name="music_list">音乐列表</string>
<string name="no_music">无音乐</string>
<string name="internet_music">网络音乐</string>
<string name="dialog_title">提示</string>
<string name="ok">确定</string>
<string name="setting_audio_441">44.1KHz</string>
<string name="setting_audio_320">32KHz</string>
<string name="setting_audio_160">16KHz</string>
<string name="sound_effect_reverb_off"></string>
<string name="sound_effect_reverb_vocal1">人声I</string>
<string name="sound_effect_reverb_vocal2">人声II</string>
<string name="sound_effect_reverb_bathroom">澡堂</string>
<string name="sound_effect_reverb_smallroom_bright">明亮小房间</string>
<string name="sound_effect_reverb_smallroom_dark">黑暗小房间</string>
<string name="sound_effect_reverb_mediumroom">中等房间</string>
<string name="sound_effect_reverb_largeroom">大房间</string>
<string name="sound_effect_reverb_churchhall">教堂走廊</string>
<string name="sound_effect_title">音效</string>
<string name="sound_effect_change_voice">变声</string>
<string name="sound_effect_reverb">混响</string>
<string name="sound_effect_changevoice_off"></string>
<string name="sound_effect_changevoice_oldman">老人</string>
<string name="sound_effect_changevoice_babyboy">男孩</string>
<string name="sound_effect_changevoice_babygirl">女孩</string>
<string name="sound_effect_changevoice_robot">机器人</string>
<string name="sound_effect_changevoice_daimo">大魔王</string>
<string name="sound_effect_changevoice_ktv">KTV</string>
<string name="sound_effect_changevoice_echo">回声</string>
</resources>

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="interaction_mode">Interaction Mode</string>
<string name="live_push_mode">LivePush Mode</string>
<string name="start_button">Start pushing</string>
<string name="waiting_download_video_resources">waiting for download external video resources</string>
<string name="live_push_mode_normal">Normal</string>
<string name="live_push_mode_interaction">Interaction</string>
<string name="live_push_mode_raw_stream">RawStream</string>
<string name="success">Success</string>
<string name="failed">Failed</string>
<string name="pause_button">Pause</string>
<string name="connecting_dialog_tips">pushing_wating</string>
<string name="pushing">Ingesting...</string>
<string name="beauty_off_tips">Retouching is disabled. Enable retouching and then retry.</string>
<string name="add_dynamic_failed">Add dynamic failed, id=</string>
<string name="start_preview">Start preview</string>
<string name="stop_preview">Stop preview</string>
<string name="stop_push">Stop pushing</string>
<string name="pause_push">Pause</string>
<string name="resume_push">Resume</string>
<string name="restart_success">Restart successfully</string>
<string name="packet_lost">Package lost</string>
<string name="connection_lost">Connection lost</string>
<string name="network_poor">The network is unstable, please quit or try again</string>
<string name="network_recovery">The network has recovered</string>
<string name="reconnect_start">Start reconnecting</string>
<string name="reconnect_fail">Reconnection failed</string>
<string name="reconnect_success">Reconnection succeed</string>
<string name="senddata_timeout">Sending data timeout</string>
<string name="send_message">Send Message</string>
<string name="bgm_open_failed">BGM File open Failed</string>
<string name="reconnect">Reconnect</string>
<string name="resume_button">Resume</string>
<string name="start_preview_button">Start preview</string>
<string name="wating_push">Waiting for Stream Ingest...</string>
<string name="backgroud_music">Background Music</string>
<string name="flash">Flash</string>
<string name="camera">Camera</string>
<string name="snapshot">Snapshot</string>
<string name="stop_preview_button">Stop preview</string>
<string name="repush_button">Restart pushing</string>
<string name="more_setting_button">More setting</string>
<string name="data_args">Data Metrics</string>
<string name="network_detect">Network Detect</string>
<string name="local_info">Statistics on Local Videos</string>
<string name="close_ears_back">Close Ears</string>
<string name="open_ears_back">Open Ears</string>
<string name="open_audio_denoise">Audio Denoise</string>
<string name="open_audio_intelligent_denoise">Audio Intelligent Denoise</string>
<string name="accompaniment">Accompaniment</string>
<string name="voice">Voice</string>
<string name="av_resolution_music_operations">Music Operations</string>
<string name="pause">Pause</string>
<string name="resume">Resume</string>
<string name="stop">Stop</string>
<string name="start">Start</string>
<string name="close_loop">Close Loop</string>
<string name="open_loop">Open Loop</string>
<string name="close_mute">Close Mute</string>
<string name="open_mute">Open Mute</string>
<string name="music_list">Music List</string>
<string name="no_music">No Music</string>
<string name="internet_music">Internet music</string>
<string name="dialog_title">Error tips</string>
<string name="ok">OK</string>
<string name="setting_audio_441">44.1KHz</string>
<string name="setting_audio_320">32KHz</string>
<string name="setting_audio_160">16KHz</string>
<string name="sound_effect_reverb_off">Off</string>
<string name="sound_effect_reverb_vocal1">Vocal1</string>
<string name="sound_effect_reverb_vocal2">Vocal2</string>
<string name="sound_effect_reverb_bathroom">BathRoom</string>
<string name="sound_effect_reverb_smallroom_bright">SmallRoom(bright)</string>
<string name="sound_effect_reverb_smallroom_dark">SmallRoom(Dark)</string>
<string name="sound_effect_reverb_mediumroom">MediumRoom</string>
<string name="sound_effect_reverb_largeroom">LargeRoom</string>
<string name="sound_effect_reverb_churchhall">ChurchHall</string>
<string name="sound_effect_title">Sound Effect</string>
<string name="sound_effect_change_voice">Change Voice</string>
<string name="sound_effect_reverb">Reverb</string>
<string name="sound_effect_changevoice_off">Off</string>
<string name="sound_effect_changevoice_oldman">Old_man</string>
<string name="sound_effect_changevoice_babyboy">Baby_Boy</string>
<string name="sound_effect_changevoice_babygirl">Baby_Girl</string>
<string name="sound_effect_changevoice_robot">Robot</string>
<string name="sound_effect_changevoice_daimo">Daimo</string>
<string name="sound_effect_changevoice_ktv">KTV</string>
<string name="sound_effect_changevoice_echo">Echo</string>
<style name="AppThemePlayer" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowBackground">@color/main_color</item>
</style>
</resources>

1
LiveBasic/live_screencap/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,35 @@
plugins {
id 'com.android.library'
}
android {
compileSdkVersion androidCompileSdkVersion
buildToolsVersion androidBuildToolsVersion
defaultConfig {
minSdkVersion androidMinSdkVersion
targetSdkVersion androidTargetSdkVersion
versionCode 1
versionName "1.0"
consumerProguardFiles "consumer-rules.pro"
}
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
implementation project(':LiveCommon:live_commonbiz')
}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.alivc.live.baselive_recording">
<uses-permission android:name="android.permission.REORDER_TASKS" />
<application>
<!-- 请务必添加service否则会因系统权限不足导致推流黑屏 -->
<service
android:name=".service.ForegroundService"
android:enabled="true"
android:foregroundServiceType="mediaProjection|camera" />
<activity
android:name=".ui.VideoRecordConfigActivity"
android:alwaysRetainTaskState="true"
android:configChanges="uiMode"
android:screenOrientation="portrait"
android:theme="@style/AVLiveTheme" />
</application>
</manifest>

View File

@@ -0,0 +1,182 @@
package com.alivc.live.baselive_recording;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.view.Gravity;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import com.alivc.live.baselive_recording.ui.widget.VideoRecordSmallView;
import com.alivc.live.baselive_recording.ui.widget.VideoRecordCameraPreviewView;
import com.alivc.live.pusher.AlivcLivePusher;
import java.lang.reflect.Field;
public class VideoRecordViewManager {
private static VideoRecordSmallView mVideoRecordSmallWindow;
private static LayoutParams mVideoRecordWindowParams;
private static VideoRecordCameraPreviewView mVideoRecordCameraPreviewWindow;
private static LayoutParams mVideoRecordCameraWindowParams;
private static WindowManager mWindowManager;
public static void createViewoRecordWindow(Activity activity, Context context, AlivcLivePusher pusher, CameraOn listener) {
WindowManager windowManager = getWindowManager(context);
int screenWidth = windowManager.getDefaultDisplay().getWidth();
int screenHeight = windowManager.getDefaultDisplay().getHeight();
if (mVideoRecordSmallWindow == null) {
mVideoRecordSmallWindow = new VideoRecordSmallView(context, activity.getTaskId());
if (mVideoRecordWindowParams == null) {
mVideoRecordWindowParams = new LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mVideoRecordWindowParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mVideoRecordWindowParams.type = LayoutParams.TYPE_PHONE;
}
mVideoRecordWindowParams.format = PixelFormat.RGBA_8888;
mVideoRecordWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL |
LayoutParams.FLAG_NOT_FOCUSABLE |
LayoutParams.FLAG_HARDWARE_ACCELERATED;
mVideoRecordWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
mVideoRecordWindowParams.width = LayoutParams.WRAP_CONTENT;
mVideoRecordWindowParams.height = LayoutParams.WRAP_CONTENT;
mVideoRecordWindowParams.x = screenWidth;
mVideoRecordWindowParams.y = screenHeight * 4 / 5;
}
mVideoRecordSmallWindow.setParams(pusher, mVideoRecordWindowParams);
mVideoRecordSmallWindow.setCameraOnListern(listener);
windowManager.addView(mVideoRecordSmallWindow, mVideoRecordWindowParams);
}
}
public interface CameraOn {
public void onCameraOn(boolean on);
}
public static void hideViewRecordWindow() {
if (mVideoRecordSmallWindow != null) {
mVideoRecordSmallWindow.setVisible(false);
}
}
public static void showViewRecordWindow() {
if (mVideoRecordSmallWindow != null) {
mVideoRecordSmallWindow.setVisible(true);
}
}
public static void removeVideoRecordWindow(Context context) {
if (mVideoRecordSmallWindow != null) {
WindowManager windowManager = getWindowManager(context);
windowManager.removeView(mVideoRecordSmallWindow);
mVideoRecordSmallWindow = null;
}
}
public static void createViewoRecordCameraWindow(Activity activity, Context context, AlivcLivePusher pusher) {
WindowManager windowManager = getWindowManager(context);
int screenWidth = windowManager.getDefaultDisplay().getWidth();
int screenHeight = windowManager.getDefaultDisplay().getHeight();
if (mVideoRecordCameraPreviewWindow == null) {
mVideoRecordCameraPreviewWindow = new VideoRecordCameraPreviewView(activity, context);
if (mVideoRecordCameraWindowParams == null) {
mVideoRecordCameraWindowParams = new LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mVideoRecordCameraWindowParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mVideoRecordCameraWindowParams.type = LayoutParams.TYPE_PHONE;
}
mVideoRecordCameraWindowParams.format = PixelFormat.RGBA_8888;
mVideoRecordCameraWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
mVideoRecordCameraWindowParams.gravity = Gravity.START | Gravity.TOP;
mVideoRecordCameraWindowParams.width = VideoRecordCameraPreviewView.viewWidth;
mVideoRecordCameraWindowParams.height = VideoRecordCameraPreviewView.viewHeight;
mVideoRecordCameraWindowParams.x = screenWidth - dip2px(context, 106);
mVideoRecordCameraWindowParams.y = 0;
}
mVideoRecordCameraPreviewWindow.setParams(pusher, mVideoRecordCameraWindowParams);
windowManager.addView(mVideoRecordCameraPreviewWindow, mVideoRecordCameraWindowParams);
}
if (mVideoRecordSmallWindow != null) {
//mVideoRecordSmallWindow.setSurfaceView(mVideoRecordCameraPreviewWindow.getSurfaceView());
}
}
public static void removeVideoRecordCameraWindow(Context context) {
if (mVideoRecordCameraPreviewWindow != null) {
WindowManager windowManager = getWindowManager(context);
windowManager.removeView(mVideoRecordCameraPreviewWindow);
mVideoRecordCameraPreviewWindow = null;
}
}
public static void setCameraPreviewVisible(boolean visible) {
mVideoRecordCameraPreviewWindow.setVisible(visible);
}
private static WindowManager getWindowManager(Context context) {
if (mWindowManager == null) {
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}
return mWindowManager;
}
public static boolean permission(Context context) {
boolean permission = true;
if (Build.VERSION.SDK_INT >= 23) {
try {
if (!Settings.canDrawOverlays(context)) {
Class clazz = Settings.class;
Field field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION");
Intent intent = new Intent(field.get(null).toString());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);
permission = false;
}
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {
}
}
return permission;
}
public static void refreshFloatWindowPosition() {
if (mVideoRecordCameraPreviewWindow != null) {
mVideoRecordCameraPreviewWindow.refreshPosition();
}
}
public static SurfaceView getCameraView() {
if (mVideoRecordCameraPreviewWindow != null) {
return mVideoRecordCameraPreviewWindow.getSurfaceView();
}
return null;
}
/**
* 将dip或dp值转换为px值保证尺寸大小不变
*
* @param dipValue
* @param dipValue DisplayMetrics类中属性density
* @return
*/
private static int dip2px(Context context, float dipValue) {
if (context == null || context.getResources() == null)
return 1;
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}

View File

@@ -0,0 +1,268 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.alivc.live.baselive_recording.floatwindowpermission;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import com.alivc.live.commonui.dialog.CommonDialog;
import com.alivc.live.baselive_recording.R;
import com.alivc.live.baselive_recording.floatwindowpermission.rom.MiuiUtils;
import com.alivc.live.baselive_recording.floatwindowpermission.rom.OppoUtils;
import com.alivc.live.baselive_recording.floatwindowpermission.rom.QikuUtils;
import com.alivc.live.baselive_recording.floatwindowpermission.rom.RomUtils;
import com.alivc.live.baselive_recording.floatwindowpermission.rom.HuaweiUtils;
import com.alivc.live.baselive_recording.floatwindowpermission.rom.MeizuUtils;
import com.alivc.live.commonutils.TextFormatUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Description:
*
* @author zhaozp
* @since 2016-10-17
*/
public class FloatWindowManager {
private static final String TAG = "FloatWindowManager";
private static volatile FloatWindowManager instance;
private CommonDialog dialog;
public static FloatWindowManager getInstance() {
if (instance == null) {
synchronized (FloatWindowManager.class) {
if (instance == null) {
instance = new FloatWindowManager();
}
}
}
return instance;
}
public boolean applyFloatWindow(Context context) {
if (checkPermission(context)) {
return true;
}
applyPermission(context);
return false;
}
private static boolean checkPermission(Context context) {
//6.0 版本之后由于 google 增加了对悬浮窗权限的管理,所以方式就统一了
if (Build.VERSION.SDK_INT < 23) {
if (RomUtils.checkIsMiuiRom()) {
return miuiPermissionCheck(context);
} else if (RomUtils.checkIsMeizuRom()) {
return meizuPermissionCheck(context);
} else if (RomUtils.checkIsHuaweiRom()) {
return huaweiPermissionCheck(context);
} else if (RomUtils.checkIs360Rom()) {
return qikuPermissionCheck(context);
} else if (RomUtils.checkIsOppoRom()) {
return oppoROMPermissionCheck(context);
}
}
return commonROMPermissionCheck(context);
}
private static boolean huaweiPermissionCheck(Context context) {
return HuaweiUtils.checkFloatWindowPermission(context);
}
private static boolean miuiPermissionCheck(Context context) {
return MiuiUtils.checkFloatWindowPermission(context);
}
private static boolean meizuPermissionCheck(Context context) {
return MeizuUtils.checkFloatWindowPermission(context);
}
private static boolean qikuPermissionCheck(Context context) {
return QikuUtils.checkFloatWindowPermission(context);
}
private static boolean oppoROMPermissionCheck(Context context) {
return OppoUtils.checkFloatWindowPermission(context);
}
private static boolean commonROMPermissionCheck(Context context) {
//最新发现魅族6.0的系统这种方式不好用,天杀的,只有你是奇葩,没办法,单独适配一下
if (RomUtils.checkIsMeizuRom()) {
return meizuPermissionCheck(context);
} else {
Boolean result = true;
if (Build.VERSION.SDK_INT >= 23) {
try {
Class clazz = Settings.class;
Method canDrawOverlays = clazz.getDeclaredMethod("canDrawOverlays", Context.class);
result = (Boolean) canDrawOverlays.invoke(null, context);
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
return result;
}
}
private void applyPermission(Context context) {
if (Build.VERSION.SDK_INT < 23) {
if (RomUtils.checkIsMiuiRom()) {
miuiROMPermissionApply(context);
} else if (RomUtils.checkIsMeizuRom()) {
meizuROMPermissionApply(context);
} else if (RomUtils.checkIsHuaweiRom()) {
huaweiROMPermissionApply(context);
} else if (RomUtils.checkIs360Rom()) {
rom360PermissionApply(context);
} else if (RomUtils.checkIsOppoRom()) {
oppoROMPermissionApply(context);
}
}
commonROMPermissionApply(context);
}
private void rom360PermissionApply(final Context context) {
showConfirmDialog(context, new OnConfirmResult() {
@Override
public void confirmResult(boolean confirm) {
if (confirm) {
QikuUtils.applyPermission(context);
} else {
Log.e(TAG, "ROM:360, user manually refuse OVERLAY_PERMISSION");
}
}
});
}
private void huaweiROMPermissionApply(final Context context) {
showConfirmDialog(context, new OnConfirmResult() {
@Override
public void confirmResult(boolean confirm) {
if (confirm) {
HuaweiUtils.applyPermission(context);
} else {
Log.e(TAG, "ROM:huawei, user manually refuse OVERLAY_PERMISSION");
}
}
});
}
private void meizuROMPermissionApply(final Context context) {
showConfirmDialog(context, new OnConfirmResult() {
@Override
public void confirmResult(boolean confirm) {
if (confirm) {
MeizuUtils.applyPermission(context);
} else {
Log.e(TAG, "ROM:meizu, user manually refuse OVERLAY_PERMISSION");
}
}
});
}
private void miuiROMPermissionApply(final Context context) {
showConfirmDialog(context, new OnConfirmResult() {
@Override
public void confirmResult(boolean confirm) {
if (confirm) {
MiuiUtils.applyMiuiPermission(context);
} else {
Log.e(TAG, "ROM:miui, user manually refuse OVERLAY_PERMISSION");
}
}
});
}
private void oppoROMPermissionApply(final Context context) {
showConfirmDialog(context, new OnConfirmResult() {
@Override
public void confirmResult(boolean confirm) {
if (confirm) {
OppoUtils.applyOppoPermission(context);
} else {
Log.e(TAG, "ROM:miui, user manually refuse OVERLAY_PERMISSION");
}
}
});
}
/**
* 通用 rom 权限申请
*/
private void commonROMPermissionApply(final Context context) {
//这里也一样,魅族系统需要单独适配
if (RomUtils.checkIsMeizuRom()) {
meizuROMPermissionApply(context);
} else {
if (Build.VERSION.SDK_INT >= 23) {
showConfirmDialog(context, new OnConfirmResult() {
@Override
public void confirmResult(boolean confirm) {
if (confirm) {
try {
commonROMPermissionApplyInternal(context);
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.d(TAG, "user manually refuse OVERLAY_PERMISSION");
//需要做统计效果
}
}
});
}
}
}
public static void commonROMPermissionApplyInternal(Context context) throws NoSuchFieldException, IllegalAccessException {
Class clazz = Settings.class;
Field field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION");
Intent intent = new Intent(field.get(null).toString());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);
}
private void showConfirmDialog(Context context, OnConfirmResult result) {
showConfirmDialog(context, context.getString(R.string.permission_float_deny_toast), result);
}
private void showConfirmDialog(Context context, String message, final OnConfirmResult result) {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
dialog = new CommonDialog(context);
dialog.setDialogContent(message);
dialog.setConfirmButton(TextFormatUtil.getTextFormat(context,R.string.permission_alert_submit_tip), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirmResult(true);
dialog.dismiss();
}
});
dialog.setCancelButton(TextFormatUtil.getTextFormat(context, R.string.permission_alert_cancel_tip), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirmResult(false);
dialog.dismiss();
}
});
dialog.show();
}
private interface OnConfirmResult {
void confirmResult(boolean confirm);
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.alivc.live.baselive_recording.floatwindowpermission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
import java.lang.reflect.Method;
public class HuaweiUtils {
private static final String TAG = "HuaweiUtils";
/**
* 检测 Huawei 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
}
return true;
}
/**
* 去华为权限申请页面
*/
public static void applyPermission(Context context) {
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity");//悬浮窗管理页面
intent.setComponent(comp);
if (RomUtils.getEmuiVersion() == 3.1) {
//emui 3.1 的适配
context.startActivity(intent);
} else {
//emui 3.0 的适配
comp = new ComponentName("com.huawei.systemmanager", "com.huawei.notificationmanager.ui.NotificationManagmentActivity");//悬浮窗管理页面
intent.setComponent(comp);
context.startActivity(intent);
}
} catch (SecurityException e) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// ComponentName comp = new ComponentName("com.huawei.systemmanager","com.huawei.permissionmanager.ui.MainActivity");//华为权限管理
ComponentName comp = new ComponentName("com.huawei.systemmanager",
"com.huawei.permissionmanager.ui.MainActivity");//华为权限管理跳转到本app的权限管理页面,这个需要华为接口权限,未解决
// ComponentName comp = new ComponentName("com.huawei.systemmanager","com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity");//悬浮窗管理页面
intent.setComponent(comp);
context.startActivity(intent);
Log.e(TAG, Log.getStackTraceString(e));
} catch (ActivityNotFoundException e) {
/**
* 手机管家版本较低 HUAWEI SC-UL10
*/
// Toast.makeText(MainActivity.this, "act找不到", Toast.LENGTH_LONG).show();
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName comp = new ComponentName("com.Android.settings", "com.android.settings.permission.TabItem");//权限管理页面 android4.4
// ComponentName comp = new ComponentName("com.android.settings","com.android.settings.permission.single_app_activity");//此处可跳转到指定app对应的权限管理页面但是需要相关权限未解决
intent.setComponent(comp);
context.startActivity(intent);
e.printStackTrace();
Log.e(TAG, Log.getStackTraceString(e));
} catch (Exception e) {
//抛出异常时提示信息
Toast.makeText(context, "进入设置页面失败,请手动设置", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.alivc.live.baselive_recording.floatwindowpermission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.util.Log;
import com.alivc.live.baselive_recording.floatwindowpermission.FloatWindowManager;
import java.lang.reflect.Method;
public class MeizuUtils {
private static final String TAG = "MeizuUtils";
/**
* 检测 meizu 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
}
return true;
}
/**
* 去魅族权限申请页面
*/
public static void applyPermission(Context context) {
try {
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.setClassName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity");
intent.putExtra("packageName", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}catch (Exception e) {
try {
Log.e(TAG, "获取悬浮窗权限, 打开AppSecActivity失败, " + Log.getStackTraceString(e));
// 最新的魅族flyme 6.2.5 用上述方法获取权限失败, 不过又可以用下述方法获取权限了
FloatWindowManager.commonROMPermissionApplyInternal(context);
} catch (Exception eFinal) {
Log.e(TAG, "获取悬浮窗权限失败, 通用获取方法失败, " + Log.getStackTraceString(eFinal));
}
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.alivc.live.baselive_recording.floatwindowpermission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import java.lang.reflect.Method;
public class MiuiUtils {
private static final String TAG = "MiuiUtils";
/**
* 获取小米 rom 版本号,获取失败返回 -1
*
* @return miui rom version code, if fail , return -1
*/
public static int getMiuiVersion() {
String version = RomUtils.getSystemProperty("ro.miui.ui.version.name");
if (version != null) {
try {
return Integer.parseInt(version.substring(1));
} catch (Exception e) {
Log.e(TAG, "get miui version code error, version : " + version);
Log.e(TAG, Log.getStackTraceString(e));
}
}
return -1;
}
/**
* 检测 miui 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
} else {
// if ((context.getApplicationInfo().flags & 1 << 27) == 1) {
// return true;
// } else {
// return false;
// }
return true;
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
/**
* 小米 ROM 权限申请
*/
public static void applyMiuiPermission(Context context) {
int versionCode = getMiuiVersion();
if (versionCode == 5) {
goToMiuiPermissionActivityV5(context);
} else if (versionCode == 6) {
goToMiuiPermissionActivityV6(context);
} else if (versionCode == 7) {
goToMiuiPermissionActivityV7(context);
} else if (versionCode == 8) {
goToMiuiPermissionActivityV8(context);
} else {
Log.e(TAG, "this is a special MIUI rom version, its version code " + versionCode);
}
}
private static boolean isIntentAvailable(Intent intent, Context context) {
if (intent == null) {
return false;
}
return context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
/**
* 小米 V5 版本 ROM权限申请
*/
public static void goToMiuiPermissionActivityV5(Context context) {
Intent intent = null;
String packageName = context.getPackageName();
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", packageName, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "intent is not available!");
}
//设置页面在应用详情页面
// Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
// PackageInfo pInfo = null;
// try {
// pInfo = context.getPackageManager().getPackageInfo
// (HostInterfaceManager.getHostInterface().getApp().getPackageName(), 0);
// } catch (PackageManager.NameNotFoundException e) {
// AVLogUtils.e(TAG, e.getMessage());
// }
// intent.setClassName("com.android.settings", "com.miui.securitycenter.permission.AppPermissionsEditor");
// intent.putExtra("extra_package_uid", pInfo.applicationInfo.uid);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// if (isIntentAvailable(intent, context)) {
// context.startActivity(intent);
// } else {
// AVLogUtils.e(TAG, "Intent is not available!");
// }
}
/**
* 小米 V6 版本 ROM权限申请
*/
public static void goToMiuiPermissionActivityV6(Context context) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "Intent is not available!");
}
}
/**
* 小米 V7 版本 ROM权限申请
*/
public static void goToMiuiPermissionActivityV7(Context context) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "Intent is not available!");
}
}
/**
* 小米 V8 版本 ROM权限申请
*/
public static void goToMiuiPermissionActivityV8(Context context) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
// intent.setPackage("com.miui.securitycenter");
intent.putExtra("extra_pkgname", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setPackage("com.miui.securitycenter");
intent.putExtra("extra_pkgname", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "Intent is not available!");
}
}
}
}

View File

@@ -0,0 +1,70 @@
package com.alivc.live.baselive_recording.floatwindowpermission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Method;
/**
* Description:
*
* @author Shawn_Dut
* @since 2018-02-01
*/
public class OppoUtils {
private static final String TAG = "OppoUtils";
/**
* 检测 360 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
}
return true;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
/**
* oppo ROM 权限申请
*/
public static void applyOppoPermission(Context context) {
//merge request from https://github.com/zhaozepeng/FloatWindowPermission/pull/26
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//com.coloros.safecenter/.sysfloatwindow.FloatWindowListActivity
ComponentName comp = new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.sysfloatwindow.FloatWindowListActivity");//悬浮窗管理页面
intent.setComponent(comp);
context.startActivity(intent);
}
catch(Exception e){
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.alivc.live.baselive_recording.floatwindowpermission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Method;
public class QikuUtils {
private static final String TAG = "QikuUtils";
/**
* 检测 360 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
}
return true;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int)method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e("", "Below API 19 cannot invoke!");
}
return false;
}
/**
* 去360权限申请页面
*/
public static void applyPermission(Context context) {
Intent intent = new Intent();
intent.setClassName("com.android.settings", "com.android.settings.Settings$OverlaySettingsActivity");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
intent.setClassName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity");
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "can't open permission page with particular name, please use " +
"\"adb shell dumpsys activity\" command and tell me the name of the float window permission page");
}
}
}
private static boolean isIntentAvailable(Intent intent, Context context) {
if (intent == null) {
return false;
}
return context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.alivc.live.baselive_recording.floatwindowpermission.rom;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Description:
*
* @author zhaozp
* @since 2016-05-23
*/
public class RomUtils {
private static final String TAG = "RomUtils";
/**
* 获取 emui 版本号
* @return
*/
public static double getEmuiVersion() {
try {
String emuiVersion = getSystemProperty("ro.build.version.emui");
String version = emuiVersion.substring(emuiVersion.indexOf("_") + 1);
return Double.parseDouble(version);
} catch (Exception e) {
e.printStackTrace();
}
return 4.0;
}
/**
* 获取小米 rom 版本号,获取失败返回 -1
*
* @return miui rom version code, if fail , return -1
*/
public static int getMiuiVersion() {
String version = getSystemProperty("ro.miui.ui.version.name");
if (version != null) {
try {
return Integer.parseInt(version.substring(1));
} catch (Exception e) {
Log.e(TAG, "get miui version code error, version : " + version);
}
}
return -1;
}
public static String getSystemProperty(String propName) {
String line;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + propName);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
Log.e(TAG, "Unable to read sysprop " + propName, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
Log.e(TAG, "Exception while closing InputStream", e);
}
}
}
return line;
}
public static boolean checkIsHuaweiRom() {
return Build.MANUFACTURER.contains("HUAWEI");
}
/**
* check if is miui ROM
*/
public static boolean checkIsMiuiRom() {
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"));
}
public static boolean checkIsMeizuRom() {
//return Build.MANUFACTURER.contains("Meizu");
String meizuFlymeOSFlag = getSystemProperty("ro.build.display.id");
if (TextUtils.isEmpty(meizuFlymeOSFlag)){
return false;
}else if (meizuFlymeOSFlag.contains("flyme") || meizuFlymeOSFlag.toLowerCase().contains("flyme")){
return true;
}else {
return false;
}
}
public static boolean checkIs360Rom() {
//fix issue https://github.com/zhaozepeng/FloatWindowPermission/issues/9
return Build.MANUFACTURER.contains("QiKU")
|| Build.MANUFACTURER.contains("360");
}
public static boolean checkIsOppoRom() {
//https://github.com/zhaozepeng/FloatWindowPermission/pull/26
return Build.MANUFACTURER.contains("OPPO") || Build.MANUFACTURER.contains("oppo");
}
}

View File

@@ -0,0 +1,90 @@
package com.alivc.live.baselive_recording.service;
import static android.app.Notification.FLAG_NO_CLEAR;
import static android.app.Notification.FLAG_ONGOING_EVENT;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.IBinder;
import androidx.annotation.Nullable;
import com.alivc.live.baselive_recording.R;
import com.alivc.live.baselive_recording.ui.VideoRecordConfigActivity;
/**
* 录屏后台service
* 请务必在AndroidManifest.xml里面进行注册否则会因系统权限不足导致推流黑屏
*
* @author aliyun
*/
public class ForegroundService extends Service {
private static final int NOTIFICATION_FLAG = 0X11;
private static final String NOTIFICATION_ID = "alivc_live_push";
private static final String NOTIFICATION_NAME = "alivc_live_push";
@Nullable
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_ID, NOTIFICATION_NAME, NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
}
Intent nfIntent = new Intent(this, VideoRecordConfigActivity.class);
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(this, 0, nfIntent, PendingIntent.FLAG_IMMUTABLE);
} else {
pendingIntent = PendingIntent.getActivity(this, 0, nfIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Notification.Builder builder = new Notification.Builder(this.getApplicationContext());
builder.setContentIntent(pendingIntent)
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.mipmap.ic_launcher))
.setTicker("正在推流中...")
.setContentTitle("推流SDK")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("正在推流中...")
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_VIBRATE)
.setPriority(Notification.PRIORITY_HIGH);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(NOTIFICATION_ID);
}
Notification notification = builder.build();
notification.defaults = Notification.DEFAULT_SOUND;
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.flags |= FLAG_ONGOING_EVENT;
notification.flags |= FLAG_NO_CLEAR;
manager.notify(NOTIFICATION_FLAG, notification);
// 启动前台服务
startForeground(NOTIFICATION_FLAG, notification);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
// 停止前台服务
stopForeground(true);
}
}

View File

@@ -0,0 +1,761 @@
package com.alivc.live.baselive_recording.ui;
import android.Manifest;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.hardware.SensorManager;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Switch;
import android.widget.TextView;
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.alivc.live.annotations.AlivcLiveNetworkQuality;
import com.alivc.live.commonui.configview.PushConfigBottomSheetLive;
import com.alivc.live.commonui.configview.PushConfigDialogImpl;
import com.alivc.live.baselive_recording.R;
import com.alivc.live.baselive_recording.VideoRecordViewManager;
import com.alivc.live.baselive_recording.floatwindowpermission.FloatWindowManager;
import com.alivc.live.baselive_recording.service.ForegroundService;
import com.alivc.live.commonbiz.test.PushDemoTestConstants;
import com.alivc.live.commonui.utils.StatusBarUtil;
import com.alivc.live.commonutils.ToastUtils;
import com.alivc.live.pusher.AlivcLiveBase;
import com.alivc.live.pusher.AlivcLivePushConfig;
import com.alivc.live.pusher.AlivcLivePushError;
import com.alivc.live.pusher.AlivcLivePushErrorListener;
import com.alivc.live.pusher.AlivcLivePushInfoListener;
import com.alivc.live.pusher.AlivcLivePushNetworkListener;
import com.alivc.live.pusher.AlivcLivePushStatsInfo;
import com.alivc.live.pusher.AlivcLivePusher;
import com.alivc.live.pusher.AlivcPreviewOrientationEnum;
import com.alivc.live.pusher.AlivcResolutionEnum;
import java.io.File;
public class VideoRecordConfigActivity extends AppCompatActivity {
private static final String TAG = "VideoRecordConfig";
private AlivcResolutionEnum mDefinition = AlivcResolutionEnum.RESOLUTION_540P;
private static final int REQ_CODE_PERMISSION = 0x1111;
private static final int CAPTURE_PERMISSION_REQUEST_CODE = 0x1123;
private static final int OVERLAY_PERMISSION_REQUEST_CODE = 0x1124;
private static final int PROGRESS_0 = 0;
private static final int PROGRESS_20 = 20;
private static final int PROGRESS_40 = 40;
private static final int PROGRESS_60 = 60;
private static final int PROGRESS_80 = 80;
private static final int PROGRESS_90 = 90;
private static final int PROGRESS_100 = 100;
private InputMethodManager manager;
private SeekBar mResolution;
private TextView mResolutionText;
private EditText mUrl;
private ImageView mQr;
private ImageView mBack;
private TextView mPushTex;
private TextView mOrientation;
private TextView mNoteText;
private AlivcLivePushConfig mAlivcLivePushConfig;
private AlivcLivePusher mAlivcLivePusher = null;
private OrientationEventListener mOrientationEventListener;
private Switch mNarrowBandHDConfig;
private int mLastRotation;
private boolean mIsStartPushing = false;
private PushConfigDialogImpl mPushConfigDialog = new PushConfigDialogImpl();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtil.translucent(this, Color.TRANSPARENT);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.video_recording_setting);
initViews();
// 注册推流SDK
AlivcLiveBase.registerSDK();
mAlivcLivePushConfig = new AlivcLivePushConfig();
configurePushImages(AlivcPreviewOrientationEnum.ORIENTATION_PORTRAIT);
mOrientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
@Override
public void onOrientationChanged(int orientation) {
int rotation = getDisplayRotation();
if (rotation != mLastRotation) {
if (mAlivcLivePusher != null) {
mAlivcLivePusher.setScreenOrientation(rotation);
}
mLastRotation = rotation;
}
}
};
// 获取默认推流地址
Intent intent = getIntent();
String url = intent.getStringExtra("pushUrl");
if (!TextUtils.isEmpty(url)) {
mUrl.setText(url);
}
}
private int getDisplayRotation() {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
default:
break;
}
return 0;
}
@Override
protected void onStart() {
super.onStart();
VideoRecordViewManager.hideViewRecordWindow();
}
@Override
protected void onStop() {
super.onStop();
if (mAlivcLivePusher != null && mAlivcLivePusher.isPushing()) {
VideoRecordViewManager.createViewoRecordWindow(VideoRecordConfigActivity.this, getApplicationContext(), mAlivcLivePusher, cameraOnListener);
VideoRecordViewManager.showViewRecordWindow();
}
}
private VideoRecordViewManager.CameraOn cameraOnListener = new VideoRecordViewManager.CameraOn() {
@Override
public void onCameraOn(boolean on) {
if (on) {
VideoRecordViewManager.createViewoRecordCameraWindow(VideoRecordConfigActivity.this, getApplicationContext(), mAlivcLivePusher);
} else {
VideoRecordViewManager.removeVideoRecordCameraWindow(getApplicationContext());
}
}
};
private void initViews() {
mUrl = (EditText) findViewById(R.id.url_editor);
mPushTex = (TextView) findViewById(R.id.pushStatusTex);
mPushTex.setOnClickListener(onClickListener);
mResolution = (SeekBar) findViewById(R.id.resolution_seekbar);
mResolution.setOnSeekBarChangeListener(onSeekBarChangeListener);
mResolutionText = (TextView) findViewById(R.id.resolution_text);
mOrientation = findViewById(R.id.main_orientation);
mOrientation.setOnClickListener(onClickListener);
mQr = (ImageView) findViewById(R.id.qr_code);
mQr.setOnClickListener(onClickListener);
mBack = (ImageView) findViewById(R.id.iv_back);
mBack.setOnClickListener(onClickListener);
mNoteText = (TextView) findViewById(R.id.note_text);
mNarrowBandHDConfig = (Switch) findViewById(R.id.narrowband_hd);
mNarrowBandHDConfig.setOnCheckedChangeListener(onCheckedChangeListener);
// 初始化调试推流地址
String initUrl = PushDemoTestConstants.getTestPushUrl();
if (!initUrl.isEmpty()) {
mUrl.setText(initUrl);
}
}
private View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.pushStatusTex) {
if (mIsStartPushing) {
return;
}
if (!(mUrl.getText().toString().contains("rtmp://") || mUrl.getText().toString().contains("artc://"))) {
ToastUtils.show("url format unsupported");
return;
}
mIsStartPushing = true;
if (getPushConfig() != null) {
if (mAlivcLivePusher == null) {
//if(VideoRecordViewManager.permission(getApplicationContext()))
if (FloatWindowManager.getInstance().applyFloatWindow(VideoRecordConfigActivity.this)) {
Intent intent = new Intent(VideoRecordConfigActivity.this, ForegroundService.class);
startService(intent);
startScreenCapture();
} else {
mIsStartPushing = false;
}
} else {
view.postDelayed(new Runnable() {
@Override
public void run() {
mIsStartPushing = false;
}
}, 1000);
Intent intent = new Intent(VideoRecordConfigActivity.this, ForegroundService.class);
stopService(intent);
stopPushWithoutSurface();
}
}
} else if (id == R.id.qr_code) {
if (ContextCompat.checkSelfPermission(VideoRecordConfigActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// Do not have the permission of camera, request it.
ActivityCompat.requestPermissions(VideoRecordConfigActivity.this, new String[]{Manifest.permission.CAMERA}, REQ_CODE_PERMISSION);
} else {
// Have gotten the permission
startCaptureActivityForResult();
}
} else if (id == R.id.iv_back) {
finish();
} else if (id == R.id.main_orientation) {
mPushConfigDialog.showConfigDialog(mOrientation, mOrientationListener, 0);
}
}
};
private SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int seekBarId = seekBar.getId();
if (mResolution.getId() == seekBarId) {
if (progress <= PROGRESS_0) {
mDefinition = AlivcResolutionEnum.RESOLUTION_180P;
mResolutionText.setText(R.string.setting_resolution_180P);
} else if (progress > PROGRESS_0 && progress <= PROGRESS_20) {
mDefinition = AlivcResolutionEnum.RESOLUTION_240P;
mResolutionText.setText(R.string.setting_resolution_240P);
} else if (progress > PROGRESS_20 && progress <= PROGRESS_40) {
mDefinition = AlivcResolutionEnum.RESOLUTION_360P;
mResolutionText.setText(R.string.setting_resolution_360P);
} else if (progress > PROGRESS_40 && progress <= PROGRESS_60) {
mDefinition = AlivcResolutionEnum.RESOLUTION_480P;
mResolutionText.setText(R.string.setting_resolution_480P);
} else if (progress > PROGRESS_60 && progress <= PROGRESS_80) {
mDefinition = AlivcResolutionEnum.RESOLUTION_540P;
mResolutionText.setText(R.string.setting_resolution_540P);
} else if (progress > PROGRESS_80 && progress <= PROGRESS_90) {
mDefinition = AlivcResolutionEnum.RESOLUTION_720P;
mResolutionText.setText(R.string.setting_resolution_720P);
} else if (progress > PROGRESS_90) {
mDefinition = AlivcResolutionEnum.RESOLUTION_1080P;
mResolutionText.setText(R.string.setting_resolution_1080P);
}
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int progress = seekBar.getProgress();
if (mResolution.getId() == seekBar.getId()) {
if (progress < PROGRESS_0) {
seekBar.setProgress(0);
} else if (progress > PROGRESS_0 && progress <= PROGRESS_20) {
seekBar.setProgress(PROGRESS_20);
} else if (progress > PROGRESS_20 && progress <= PROGRESS_40) {
seekBar.setProgress(PROGRESS_40);
} else if (progress > PROGRESS_40 && progress <= PROGRESS_60) {
seekBar.setProgress(PROGRESS_60);
} else if (progress > PROGRESS_60 && progress <= PROGRESS_80) {
seekBar.setProgress(PROGRESS_80);
} else if (progress > PROGRESS_80 && progress <= PROGRESS_90) {
seekBar.setProgress(PROGRESS_90);
} else if (progress > PROGRESS_90) {
seekBar.setProgress(PROGRESS_100);
}
}
}
};
private PushConfigBottomSheetLive.OnPushConfigSelectorListener mOrientationListener = new PushConfigBottomSheetLive.OnPushConfigSelectorListener() {
@Override
public void confirm(String data, int index) {
AlivcPreviewOrientationEnum currentOrientation = AlivcPreviewOrientationEnum.ORIENTATION_PORTRAIT;
if (index == 1) {
currentOrientation = AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_LEFT;
} else if (index == 2) {
currentOrientation = AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_RIGHT;
}
if (mAlivcLivePushConfig != null) {
mAlivcLivePushConfig.setPreviewOrientation(currentOrientation);
configurePushImages(currentOrientation);
}
}
};
private OnCheckedChangeListener onCheckedChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int id = buttonView.getId();
if (id == R.id.narrowband_hd) {
mAlivcLivePushConfig.setEnableNarrowbandHDForScreenPusher(isChecked);
}
}
};
/**
* 根据预览方向设置暂停推流和网络不佳时的图片
*
* @param orientation 预览方向
*/
private void configurePushImages(AlivcPreviewOrientationEnum orientation) {
if (mAlivcLivePushConfig == null) {
return;
}
if (orientation == AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_RIGHT || orientation == AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_LEFT) {
// 横屏模式
mAlivcLivePushConfig.setNetworkPoorPushImage(getFilesDir().getPath() + File.separator + "alivc_resource/poor_network_land.png");
mAlivcLivePushConfig.setPausePushImage(getFilesDir().getPath() + File.separator + "alivc_resource/background_push_land.png");
} else {
// 竖屏模式
mAlivcLivePushConfig.setNetworkPoorPushImage(getFilesDir().getPath() + File.separator + "alivc_resource/poor_network.png");
mAlivcLivePushConfig.setPausePushImage(getFilesDir().getPath() + File.separator + "alivc_resource/background_push.png");
}
}
@Override
protected void onPause() {
super.onPause();
VideoRecordViewManager.refreshFloatWindowPosition();
}
@Override
protected void onResume() {
super.onResume();
if (mOrientationEventListener != null && mOrientationEventListener.canDetectOrientation()) {
mOrientationEventListener.enable();
}
}
private void startCaptureActivityForResult() {
Intent intent = new Intent(VideoRecordConfigActivity.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);
}
@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
ToastUtils.show("You must agree the camera permission request before you use the code scan function");
}
}
break;
default:
break;
}
}
private AlivcLivePushConfig getPushConfig() {
if (mUrl.getText().toString().isEmpty()) {
ToastUtils.show(getString(R.string.url_empty));
return null;
}
mAlivcLivePushConfig.setResolution(mDefinition);
return mAlivcLivePushConfig;
}
@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:
mUrl.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT)); //or do sth
break;
case RESULT_CANCELED:
if (data != null) {
// for some reason camera is not working correctly
mUrl.setText(data.getStringExtra(CaptureActivity.EXTRA_SCAN_RESULT));
}
break;
default:
break;
}
break;
case CAPTURE_PERMISSION_REQUEST_CODE: {
if (resultCode == Activity.RESULT_CANCELED) {
ToastUtils.show("Start screen recording failed, cancelled by the user");
mIsStartPushing = false;
return;
}
if (resultCode == Activity.RESULT_OK) {
mAlivcLivePushConfig.setMediaProjectionPermissionResultData(data);
if (mAlivcLivePushConfig.getMediaProjectionPermissionResultData() != null) {
if (mAlivcLivePusher == null) {
startPushWithoutSurface(mUrl.getText().toString());
} else {
stopPushWithoutSurface();
}
}
}
}
break;
case OVERLAY_PERMISSION_REQUEST_CODE:
break;
default:
break;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (getCurrentFocus() != null && getCurrentFocus().getWindowToken() != null) {
if (manager == null) {
manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
}
manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
return super.onTouchEvent(event);
}
@Override
protected void onDestroy() {
Intent intent = new Intent(VideoRecordConfigActivity.this, ForegroundService.class);
stopService(intent);
VideoRecordViewManager.removeVideoRecordCameraWindow(getApplicationContext());
VideoRecordViewManager.removeVideoRecordWindow(getApplicationContext());
if (mAlivcLivePusher != null) {
try {
mAlivcLivePusher.stopCamera();
} catch (Exception e) {
}
try {
mAlivcLivePusher.stopCameraMix();
} catch (Exception e) {
}
try {
mAlivcLivePusher.stopPush();
} catch (Exception e) {
}
try {
mAlivcLivePusher.stopPreview();
} catch (Exception e) {
}
mAlivcLivePusher.destroy();
mAlivcLivePusher.setLivePushInfoListener(null);
mAlivcLivePusher = null;
}
if (mOrientationEventListener != null) {
mOrientationEventListener.disable();
}
super.onDestroy();
}
private void startScreenCapture() {
if (Build.VERSION.SDK_INT >= 21) {
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getApplication().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
try {
this.startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), CAPTURE_PERMISSION_REQUEST_CODE);
} catch (ActivityNotFoundException ex) {
ex.printStackTrace();
ToastUtils.show("Start ScreenRecording failed, current device is NOT supported!");
}
} else {
ToastUtils.show("录屏需要5.0版本以上");
}
}
private void stopPushWithoutSurface() {
VideoRecordViewManager.removeVideoRecordCameraWindow(getApplicationContext());
VideoRecordViewManager.removeVideoRecordWindow(getApplicationContext());
if (mAlivcLivePusher != null) {
try {
mAlivcLivePusher.stopCamera();
} catch (Exception e) {
}
try {
mAlivcLivePusher.stopCameraMix();
} catch (Exception e) {
}
try {
mAlivcLivePusher.stopPush();
} catch (Exception e) {
}
try {
mAlivcLivePusher.stopPreview();
} catch (Exception e) {
}
try {
mAlivcLivePusher.destroy();
} catch (Exception e) {
}
mAlivcLivePusher.setLivePushInfoListener(null);
mAlivcLivePusher = null;
}
mPushTex.setText(R.string.start_push);
mNoteText.setText(getString(R.string.screen_note1));
mNoteText.setVisibility(View.VISIBLE);
mResolution.setEnabled(true);
mNarrowBandHDConfig.setEnabled(true);
}
private void startPushWithoutSurface(String url) {
mAlivcLivePusher = new AlivcLivePusher();
try {
mAlivcLivePusher.init(getApplicationContext(), mAlivcLivePushConfig);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
mAlivcLivePusher.setLivePushInfoListener(new AlivcLivePushInfoListener() {
@Override
public void onPreviewStarted(AlivcLivePusher pusher) {
Log.d(TAG, "onPreviewStarted: ");
}
@Override
public void onPreviewStopped(AlivcLivePusher pusher) {
Log.d(TAG, "onPreviewStopped: ");
}
@Override
public void onPushStarted(AlivcLivePusher pusher) {
Log.d(TAG, "onPushStarted: ");
}
@Override
public void onPushPaused(AlivcLivePusher pusher) {
Log.d(TAG, "onPushPaused: ");
}
@Override
public void onPushResumed(AlivcLivePusher pusher) {
Log.d(TAG, "onPushResumed: ");
}
@Override
public void onPushStopped(AlivcLivePusher pusher) {
Log.d(TAG, "onPushStopped: ");
}
@Override
public void onPushRestarted(AlivcLivePusher pusher) {
Log.d(TAG, "onPushRestarted: ");
}
@Override
public void onFirstFramePushed(AlivcLivePusher pusher) {
Log.d(TAG, "onFirstFramePushed: ");
}
@Override
public void onFirstFramePreviewed(AlivcLivePusher pusher) {
Log.d(TAG, "onFirstFramePreviewed: ");
mIsStartPushing = false;
}
@Override
public void onDropFrame(AlivcLivePusher pusher, int countBef, int countAft) {
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 pusher, int curFps, int targetFps) {
Log.d(TAG, "onAdjustFps: ");
}
@Override
public void onPushStatistics(AlivcLivePusher pusher, AlivcLivePushStatsInfo statistics) {
// Log.i(TAG, "onPushStatistics: ");
}
});
mAlivcLivePusher.setLivePushErrorListener(new AlivcLivePushErrorListener() {
@Override
public void onSystemError(AlivcLivePusher livePusher, AlivcLivePushError error) {
showDialog(getString(R.string.system_error) + error.toString());
}
@Override
public void onSDKError(AlivcLivePusher livePusher, AlivcLivePushError error) {
showDialog(getString(R.string.sdk_error) + error.toString());
}
});
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: ");
}
@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: ");
showDialog(getResources().getString(R.string.connect_fail));
}
@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: ");
}
});
try {
mAlivcLivePusher.startPreview(null);
} catch (Exception e) {
showDialog("StartPreview failed");
return;
}
try {
mAlivcLivePusher.startPush(url);
} catch (Exception e) {
showDialog("startPush failed");
return;
}
mPushTex.setText(R.string.stop_button);
mNoteText.setText(getString(R.string.screen_note));
mNoteText.setVisibility(View.VISIBLE);
mResolution.setEnabled(false);
mNarrowBandHDConfig.setEnabled(false);
}
private void showDialog(final String message) {
if (getApplicationContext() == null || message == null) {
return;
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
mNoteText.setText(message);
}
});
}
}

View File

@@ -0,0 +1,195 @@
package com.alivc.live.baselive_recording.ui.widget;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import com.alivc.live.baselive_recording.R;
import com.alivc.live.pusher.AlivcLivePushStats;
import com.alivc.live.pusher.AlivcLivePusher;
import java.lang.reflect.Field;
public class VideoRecordCameraPreviewView extends LinearLayout {
public static int viewWidth;
public static int viewHeight;
private static int statusBarHeight;
private WindowManager windowManager;
private WindowManager.LayoutParams mParams;
private AlivcLivePusher mLivePusher = null;
private float xInScreen;
private float yInScreen;
private float xDownInScreen;
private float yDownInScreen;
private float xInView;
private float yInView;
private Activity mActivity;
private SurfaceView cameraPreview = null;
public VideoRecordCameraPreviewView(Activity activity, Context context) {
super(context);
this.mActivity = activity;
windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
LayoutInflater.from(context).inflate(R.layout.record_camera_preview, this);
View view = findViewById(R.id.record_camera_layout);
viewWidth = dip2px(activity, 90);
viewHeight = dip2px(activity, 160);
cameraPreview = (SurfaceView) findViewById(R.id.camera_preview);
cameraPreview.getHolder().addCallback(mCallback);
}
public void setVisible(boolean visible) {
if (visible) {
cameraPreview.setVisibility(VISIBLE);
} else {
cameraPreview.setVisibility(INVISIBLE);
}
}
SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (mLivePusher != null) {
AlivcLivePushStats currentStatus = mLivePusher.getCurrentStatus();
mLivePusher.startCamera(cameraPreview);
int rotation = getDisplayRotation();
mLivePusher.setScreenOrientation(rotation);
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
if (mLivePusher != null) {
try {
mLivePusher.stopCamera();
} catch (Exception e) {
}
}
}
};
public void refreshPosition() {
updateViewPosition();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
xInView = event.getX();
yInView = event.getY();
xDownInScreen = event.getRawX();
yDownInScreen = event.getRawY() - getStatusBarHeight();
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
break;
case MotionEvent.ACTION_MOVE:
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
updateViewPosition();
break;
case MotionEvent.ACTION_UP:
if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {
}
break;
default:
break;
}
return true;
}
public void setParams(AlivcLivePusher pusher, WindowManager.LayoutParams params) {
mParams = params;
mLivePusher = pusher;
}
/**
* 更新小悬浮窗在屏幕中的位置。
*/
private void updateViewPosition() {
mParams.x = (int) (xInScreen - xInView);
mParams.y = (int) (yInScreen - yInView);
windowManager.updateViewLayout(this, mParams);
}
/**
* 用于获取状态栏的高度。
*
* @return 返回状态栏高度的像素值。
*/
private int getStatusBarHeight() {
if (statusBarHeight == 0) {
try {
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object o = c.newInstance();
Field field = c.getField("status_bar_height");
int x = (Integer) field.get(o);
statusBarHeight = getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
}
return statusBarHeight;
}
public SurfaceView getSurfaceView() {
return cameraPreview;
}
private int getDisplayRotation() {
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
default:
break;
}
return 0;
}
/**
* 将dip或dp值转换为px值保证尺寸大小不变
*
* @param dipValue
* @param dipValue DisplayMetrics类中属性density
* @return
*/
private static int dip2px(Context context, float dipValue) {
if (context == null || context.getResources() == null)
return 1;
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}

View File

@@ -0,0 +1,299 @@
package com.alivc.live.baselive_recording.ui.widget;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.alivc.live.baselive_recording.R;
import com.alivc.live.baselive_recording.ui.VideoRecordConfigActivity;
import com.alivc.live.pusher.AlivcLivePusher;
import com.alivc.live.baselive_recording.VideoRecordViewManager;
import java.lang.reflect.Field;
import java.util.List;
public class VideoRecordSmallView extends LinearLayout {
public static int viewHeight;
private static int statusBarHeight;
private WindowManager windowManager;
private WindowManager.LayoutParams mParams;
private AlivcLivePusher mAlivcLivePusher = null;
private float xInScreen;
private float yInScreen;
private float xDownInScreen;
private float yDownInScreen;
private float xInView;
private float yInView;
private LinearLayout mRecording;
private LinearLayout mOpera;
private TextView mPrivacy;
private TextView mCamera;
private TextView mMic;
private TextView mMix;
private boolean mPrivacyOn = false;
private boolean mCameraOn = false;
private boolean mMicOn = true;
private boolean mMixOn = false;
private Context mContext;
private int mCurrentTaskId;
private View mRootView = null;
private VideoRecordViewManager.CameraOn mCameraOnListener = null;
private final View mContentView;
private Runnable mCloseRunnable = new Runnable() {
@Override
public void run() {
mContentView.setAlpha(0.5f);
mOpera.setVisibility(GONE);
}
};
public VideoRecordSmallView(Context context, int currentTaskId) {
super(context);
this.mContext = context;
this.mCurrentTaskId = currentTaskId;
windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mRootView = LayoutInflater.from(context).inflate(R.layout.record_view_small, this);
mContentView = findViewById(R.id.record_window_layout);
mRecording = (LinearLayout) mContentView.findViewById(R.id.recording_linear);
mOpera = (LinearLayout) mContentView.findViewById(R.id.opera_linear);
mPrivacy = (TextView) mContentView.findViewById(R.id.privacy);
mPrivacy.setSelected(mPrivacyOn);
mCamera = (TextView) mContentView.findViewById(R.id.camera);
mCamera.setSelected(mCameraOn);
mMic = (TextView) mContentView.findViewById(R.id.mic);
mMic.setSelected(mMicOn);
mMix = (TextView) mContentView.findViewById(R.id.mix);
mMix.setSelected(mMixOn);
mRecording.setOnClickListener(mOnClickListener);
mOpera.setOnClickListener(mOnClickListener);
mPrivacy.setOnClickListener(mOnClickListener);
mCamera.setOnClickListener(mOnClickListener);
mMic.setOnClickListener(mOnClickListener);
mMix.setOnClickListener(mOnClickListener);
viewHeight = mContentView.getLayoutParams().height;
}
public void setVisible(boolean visible) {
if (visible) {
mRootView.setVisibility(VISIBLE);
} else {
mRootView.setVisibility(INVISIBLE);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("fclaa", "onTouchEvent: "+event.getActionMasked() );
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
xInView = event.getX();
yInView = event.getY();
xDownInScreen = event.getRawX();
yDownInScreen = event.getRawY() - getStatusBarHeight();
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
break;
case MotionEvent.ACTION_MOVE:
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
updateViewPosition();
break;
case MotionEvent.ACTION_UP:
if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {
}
break;
default:
break;
}
return true;
}
public void setParams(AlivcLivePusher pusher, WindowManager.LayoutParams params) {
mAlivcLivePusher = pusher;
mParams = params;
}
public void setCameraOnListern(VideoRecordViewManager.CameraOn listern) {
mCameraOnListener = listern;
}
/**
* 更新小悬浮窗在屏幕中的位置。
*/
private void updateViewPosition() {
mParams.x = (int) (xInScreen - xInView);
mParams.y = (int) (yInScreen - yInView);
windowManager.updateViewLayout(this, mParams);
}
/**
* 用于获取状态栏的高度。
*
* @return 返回状态栏高度的像素值。
*/
private int getStatusBarHeight() {
if (statusBarHeight == 0) {
try {
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object o = c.newInstance();
Field field = c.getField("status_bar_height");
int x = (Integer) field.get(o);
statusBarHeight = getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
}
return statusBarHeight;
}
private boolean IsForeground(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
if (tasks != null && !tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
private OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.recording_linear) {
if (mOpera.getVisibility() == VISIBLE){
mContentView.removeCallbacks(mCloseRunnable);
mOpera.setVisibility(GONE);
mContentView.setAlpha(0.5f);
if (mContext != null) {
if (!IsForeground(mContext) && mCurrentTaskId != 0) {
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
if (am != null) {
am.moveTaskToFront(mCurrentTaskId, ActivityManager.MOVE_TASK_WITH_HOME);
}
} else {
Intent intent = new Intent(mContext, VideoRecordConfigActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
}
}else {
mContentView.setAlpha(1.0f);
mOpera.setVisibility(VISIBLE);
mContentView.removeCallbacks(mCloseRunnable);
mContentView.postDelayed(mCloseRunnable,5000);
}
} else if (id == R.id.privacy) {
if (mAlivcLivePusher != null && mPrivacyOn) {
try {
mAlivcLivePusher.resumeScreenCapture();
} catch (Exception e) {
}
mPrivacyOn = false;
} else if (mAlivcLivePusher != null && !mPrivacyOn) {
try {
mAlivcLivePusher.pauseScreenCapture();
} catch (Exception e) {
}
mPrivacyOn = true;
}
mPrivacy.setSelected(mPrivacyOn);
} else if (id == R.id.camera) {
if (mAlivcLivePusher != null && !mCameraOn && mCameraOnListener != null) {
mMix.setSelected(false);
mMix.setClickable(false);
mCameraOnListener.onCameraOn(true);
mCameraOn = true;
} else if (mAlivcLivePusher != null && mCameraOn && mCameraOnListener != null) {
try {
mAlivcLivePusher.stopCamera();
} catch (Exception e) {
}
mCameraOnListener.onCameraOn(false);
mCameraOn = false;
mMix.setClickable(true);
}
mCamera.setSelected(mCameraOn);
} else if (id == R.id.mix) {
if (mAlivcLivePusher != null && !mMixOn) {
mCamera.setSelected(false);
mCamera.setClickable(false);
try {
mAlivcLivePusher.startCamera(null);
} catch (Exception e) {
e.printStackTrace();
}
//set orientation
/*int orientation = getContext().getResources().getConfiguration().orientation;
if(orientation == 0) {
mAlivcLivePusher.setScreenOrientation(0);
} else if(orientation == 2) {
mAlivcLivePusher.setScreenOrientation(90);
} else if(orientation == 1) {
mAlivcLivePusher.setScreenOrientation(270);
}*/
mAlivcLivePusher.startCameraMix(0.6f, 0.08f, 0.3f, 0.3f);
mMixOn = true;
} else if (mAlivcLivePusher != null && mMixOn) {
mAlivcLivePusher.stopCameraMix();
// if (mCameraOpenByMix) {
// mAlivcLivePusher.stopCamera();
// }
mMixOn = false;
mCamera.setClickable(true);
}
mMix.setSelected(mMixOn);
} else if (id == R.id.mic) {
if (mAlivcLivePusher != null) {
try {
mAlivcLivePusher.setMute(mMicOn);
} catch (Exception e) {
e.printStackTrace();
}
mMicOn = !mMicOn;
mMic.setSelected(mMicOn);
}
}
}
};
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mContentView != null){
mContentView.removeCallbacks(mCloseRunnable);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_camera_on"/>
<item android:state_selected="false" android:drawable="@drawable/ic_camera_off"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_mic_on"/>
<item android:state_selected="false" android:drawable="@drawable/ic_mic_off"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_mix_on"/>
<item android:state_selected="false" android:drawable="@drawable/ic_mix_off"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_privacy_on"/>
<item android:state_selected="false" android:drawable="@drawable/ic_privacy_off"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#4DCFE1"/>
<item android:state_selected="false" android:color="#FCFCFD"/>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1C1D22" />
<corners android:topLeftRadius="32dp" android:bottomLeftRadius="32dp" />
</shape>

View File

@@ -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>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="304dp"
android:background="#1C1D22"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/cancel"
android:gravity="center"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="@string/pull_cancel"
android:textSize="15sp"
android:textColor="#4DCFE1"
android:layout_width="62dp"
android:layout_height="39dp"/>
<TextView
android:id="@+id/confirm_button"
android:gravity="center"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="@string/btn_confirm"
android:textSize="15sp"
android:textColor="#4DCFE1"
android:layout_width="62dp"
android:layout_height="39dp"/>
<View
android:id="@+id/div"
app:layout_constraintTop_toBottomOf="@+id/cancel"
android:layout_width="match_parent"
android:background="#3A3D48"
android:layout_height="1px"/>
<com.alivc.live.commonui.configview.OptionSelectorView
android:id="@+id/optionSelectorView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/div"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/record_camera_layout"
android:layout_width="90dp"
android:layout_height="160dp">
<SurfaceView
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/record_window_layout"
android:layout_width="wrap_content"
android:layout_height="64dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:alpha="0.5"
android:background="@drawable/shap_oval_gray">
<LinearLayout
android:id="@+id/recording_linear"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_blue_back"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="19dp"
android:gravity="center"
android:text="@string/back"
android:textSize="15sp"
android:textColor="#4DCFE1"/>
</LinearLayout>
<LinearLayout
android:id="@+id/opera_linear"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/privacy"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:gravity="center"
android:text="@string/privacy_on"
android:textSize="10sp"
android:drawablePadding="5dp"
android:layout_marginEnd="20dp"
android:drawableTop="@drawable/selector_push_drawable_privacy"
android:textColor="@drawable/selector_push_text_color"/>
<TextView
android:id="@+id/camera"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:gravity="center"
android:text="@string/camera_on"
android:textSize="10sp"
android:drawablePadding="8dp"
android:layout_marginEnd="20dp"
android:drawableTop="@drawable/selector_push_drawable_camera"
android:textColor="@drawable/selector_push_text_color"/>
<TextView
android:id="@+id/mix"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:gravity="center"
android:text="@string/mix_on"
android:textSize="10sp"
android:drawablePadding="5dp"
android:layout_marginEnd="20dp"
android:drawableTop="@drawable/selector_push_drawable_mix"
android:textColor="@drawable/selector_push_text_color"/>
<TextView
android:id="@+id/mic"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:gravity="center"
android:text="@string/mic_on"
android:textSize="10sp"
android:drawablePadding="1dp"
android:layout_marginEnd="20dp"
android:drawableTop="@drawable/selector_push_drawable_mic"
android:textColor="@drawable/selector_push_text_color"/>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,228 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1C1D22"
android:fitsSystemWindows="true"
android:orientation="vertical">
<View
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#141416" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#1C1D22"
android:orientation="vertical">
<LinearLayout
android:id="@+id/title_layout"
android:layout_width="match_parent"
android:layout_height="63dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="24dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_back"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_marginTop="8dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_live_action_bar_back" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="32dp"
android:layout_marginStart="8dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="0dp"
android:background="#23262F"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/qr_code"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:background="@drawable/ic_live_scan"
android:scaleType="fitXY" />
<EditText
android:id="@+id/url_editor"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="@null"
android:ellipsize="end"
android:hint="@string/view_string_hint_push_url"
android:singleLine="true"
android:textColor="#747A8C"
android:textColorHint="#747A8C"
android:textSize="@dimen/view_size_text_14" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#3A3D48" />
<TextView
android:id="@+id/note_text"
android:layout_width="match_parent"
android:layout_height="39dp"
android:background="@color/tips_color"
android:gravity="center"
android:text="@string/screen_note"
android:textColor="@color/wheel_white"
android:visibility="gone" />
<TextView
android:layout_width="match_parent"
android:layout_height="39dp"
android:background="#141416"
android:gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="@string/resolution_label"
android:textColor="#747A8C"
android:textSize="@dimen/font_size_24px" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:orientation="horizontal"
android:paddingEnd="20dp">
<SeekBar
android:id="@+id/resolution_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:progressDrawable="@drawable/live_seekbar_drawable"
android:layout_marginEnd="30dp"
android:maxHeight="5dp"
android:minHeight="5dp"
android:progress="80"
android:theme="@style/Push_SeekBar_Style" />
<TextView
android:id="@+id/resolution_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:text="@string/setting_resolution_540P"
android:textColor="#FCFCFD"
android:textSize="12sp" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/push_orientation"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<TextView
android:id="@+id/main_orientation"
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:gravity="center_vertical|end"
android:paddingEnd="23dp"
android:text="@string/portrait"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_live_arrow_right" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="20dp"
android:background="#3A3D48" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/view_height_size_45"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="100dp"
android:text="@string/narrowband_hd"
android:textColor="#FCFCFD"
android:textSize="@dimen/font_size_30px" />
<Switch
android:id="@+id/narrowband_hd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="end|center_vertical"
android:checked="true"
android:textOff=""
android:textOn=""
android:thumb="@drawable/thumb"
android:track="@drawable/track" />
</FrameLayout>
</LinearLayout>
<TextView
android:id="@+id/pushStatusTex"
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="42dp"
android:background="@drawable/shape_rect_blue"
android:ellipsize="end"
android:gravity="center"
android:includeFontPadding="false"
android:maxLines="2"
android:text="@string/start_push"
android:textColor="@android:color/white"
android:textSize="@dimen/font_size_28px" />
</FrameLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="screen_note">You can start other applications and start live...</string>
<string name="screen_note1">The screen function has stopped.</string>
<string name="narrowband_hd">Narrowband HD</string>
<string name="permission_float_deny_toast">The floating window permission is required. Obtain the floating window permission and try again.</string>
<string name="permission_alert_cancel_tip">Enable Later</string>
<string name="permission_alert_submit_tip">Enable Now</string>
<string name="back">back</string>
<string name="privacy_on">Privacy</string>
<string name="camera_on">Camera</string>
<string name="mix_on">Mix</string>
<string name="mix_off">Mix Off</string>
<string name="mic_on">Mic</string>
<string name="mic_off">Mic Off</string>
</resources>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="screen_note">录制中</string>
<string name="screen_note1">录屏功能已停止</string>
<string name="narrowband_hd">窄带高清</string>
<string name="permission_float_deny_toast">您的手机没有授予悬浮窗权限,请开启后再试</string>
<string name="permission_alert_cancel_tip">暂不开启</string>
<string name="permission_alert_submit_tip">现在去开启</string>
<string name="back">返回</string>
<string name="privacy_on">隐私模式</string>
<string name="camera_on">摄像头</string>
<string name="mix_on">混流</string>
<string name="mix_off">混流关</string>
<string name="mic_on">麦克风</string>
<string name="mic_off">麦克风关</string>
</resources>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="screen_note">You can start other applications and start live...</string>
<string name="screen_note1">The screen function has stopped.</string>
<string name="narrowband_hd">Narrowband HD</string>
<string name="permission_float_deny_toast">The floating window permission is required. Obtain the floating window permission and try again.</string>
<string name="permission_alert_cancel_tip">Enable Later</string>
<string name="permission_alert_submit_tip">Enable Now</string>
<string name="back">back</string>
<string name="privacy_on">Privacy</string>
<string name="camera_on">Camera</string>
<string name="mix_on">Mix</string>
<string name="mix_off">Mix Off</string>
<string name="mic_on">Mic</string>
<string name="mic_off">Mic Off</string>
</resources>