集成完直播后提交代码
1
LiveBasic/live_pull/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
46
LiveBasic/live_pull/build.gradle
Normal 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')
|
||||
}
|
||||
0
LiveBasic/live_pull/consumer-rules.pro
Normal file
12
LiveBasic/live_pull/src/main/AndroidManifest.xml
Normal 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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.alivc.live.baselive_pull.listener;
|
||||
|
||||
public interface ButtonClickListener {
|
||||
void onButtonClick(String message, int position);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
BIN
LiveBasic/live_pull/src/main/res/drawable-xxhdpi/colour_bg.webp
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
LiveBasic/live_pull/src/main/res/drawable-xxhdpi/finish_play.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 695 B |
|
After Width: | Height: | Size: 643 B |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
BIN
LiveBasic/live_pull/src/main/res/drawable-xxhdpi/live_beauty.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
LiveBasic/live_pull/src/main/res/drawable-xxhdpi/live_carmer.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
LiveBasic/live_pull/src/main/res/drawable-xxhdpi/live_data.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
BIN
LiveBasic/live_pull/src/main/res/drawable-xxhdpi/live_push.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
BIN
LiveBasic/live_pull/src/main/res/drawable-xxhdpi/live_sound.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
LiveBasic/live_pull/src/main/res/drawable-xxhdpi/mute_btn.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
118
LiveBasic/live_pull/src/main/res/layout/activity_player.xml
Normal 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>
|
||||
158
LiveBasic/live_pull/src/main/res/layout/common_dialog.xml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
6
LiveBasic/live_pull/src/main/res/values-en/strings.xml
Normal 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>
|
||||
@@ -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>
|
||||
10
LiveBasic/live_pull/src/main/res/values/strings.xml
Normal 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
@@ -0,0 +1 @@
|
||||
/build
|
||||
46
LiveBasic/live_pull_rts/build.gradle
Normal 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')
|
||||
}
|
||||
0
LiveBasic/live_pull_rts/consumer-rules.pro
Normal file
21
LiveBasic/live_pull_rts/src/main/AndroidManifest.xml
Normal 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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 257 B |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#4D4DCFE1"/>
|
||||
<stroke android:color="#4DCFE1" android:width="1px"/>
|
||||
<corners android:radius="24dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,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>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="16dp" />
|
||||
<solid android:color="#23262F" />
|
||||
</shape>
|
||||
@@ -0,0 +1,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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
27
LiveBasic/live_pull_rts/src/main/res/values-en/strings.xml
Normal 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>
|
||||
@@ -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>
|
||||
7
LiveBasic/live_pull_rts/src/main/res/values/dimens.xml
Normal 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>
|
||||
27
LiveBasic/live_pull_rts/src/main/res/values/strings.xml
Normal 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
@@ -0,0 +1 @@
|
||||
/build
|
||||
40
LiveBasic/live_push/build.gradle
Normal 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')
|
||||
}
|
||||
0
LiveBasic/live_push/consumer-rules.pro
Normal file
19
LiveBasic/live_push/src/main/AndroidManifest.xml
Normal 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>
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.alivc.live.baselive_push.adapter;
|
||||
|
||||
public interface OnSoundEffectChangedListener {
|
||||
void onSoundEffectChangeVoiceModeSelected(int position);
|
||||
|
||||
void onSoundEffectRevertBSelected(int position);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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_QUEEN,即:InteractQueenBeautyImpl;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/back_icon.png
Normal file
|
After Width: | Height: | Size: 565 B |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/camera_on.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/flash_off.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/flash_on.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 499 B |
|
After Width: | Height: | Size: 799 B |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/icon_check.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/loop_off.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/loop_on.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/music.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/music_pause.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/music_play.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/mute_off.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/mute_on.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/preview_off.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/preview_on.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/push_off.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/push_on.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/push_pause.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/repush_off.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/scan_icon.png
Normal file
|
After Width: | Height: | Size: 257 B |
BIN
LiveBasic/live_push/src/main/res/drawable-xxhdpi/screenshot.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
26
LiveBasic/live_push/src/main/res/layout/activity_push.xml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
330
LiveBasic/live_push/src/main/res/layout/push_fragment.xml
Normal 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>
|
||||
420
LiveBasic/live_push/src/main/res/layout/push_more.xml
Normal 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>
|
||||
373
LiveBasic/live_push/src/main/res/layout/push_music_sheet.xml
Normal 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>
|
||||
246
LiveBasic/live_push/src/main/res/layout/push_setting.xml
Normal 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>
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
LiveBasic/live_push/src/main/res/mipmap-xxhdpi/back_img.png
Normal file
|
After Width: | Height: | Size: 903 B |
BIN
LiveBasic/live_push/src/main/res/mipmap-xxhdpi/logo_left.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
101
LiveBasic/live_push/src/main/res/values-en/strings.xml
Normal 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>
|
||||
101
LiveBasic/live_push/src/main/res/values-zh-rCN/strings.xml
Normal 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>
|
||||
112
LiveBasic/live_push/src/main/res/values/strings.xml
Normal 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
@@ -0,0 +1 @@
|
||||
/build
|
||||
35
LiveBasic/live_screencap/build.gradle
Normal 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')
|
||||
}
|
||||
0
LiveBasic/live_screencap/consumer-rules.pro
Normal file
21
LiveBasic/live_screencap/src/main/AndroidManifest.xml
Normal 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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 805 B |
|
After Width: | Height: | Size: 1.0 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#4D4DCFE1"/>
|
||||
<stroke android:color="#4DCFE1" android:width="1px"/>
|
||||
<corners android:radius="24dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 16 KiB |
19
LiveBasic/live_screencap/src/main/res/values-en/strings.xml
Normal 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>
|
||||
@@ -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>
|
||||
19
LiveBasic/live_screencap/src/main/res/values/strings.xml
Normal 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>
|
||||