集成完直播后提交代码
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>
|
||||