pangweixin 4 роки тому
батько
коміт
033aef413e
44 змінених файлів з 1410 додано та 98 видалено
  1. 1 0
      .idea/gradle.xml
  2. 6 1
      .idea/misc.xml
  3. 1 0
      VideoCall/.gitignore
  4. 27 0
      VideoCall/build.gradle
  5. 21 0
      VideoCall/proguard-rules.pro
  6. 13 0
      VideoCall/src/main/AndroidManifest.xml
  7. 25 0
      VideoCall/src/main/java/com/tencent/trtc/videocall/Constant.java
  8. 1 1
      VideoCall/src/main/java/com/tencent/trtc/videocall/DeviceUtil.java
  9. 193 0
      VideoCall/src/main/java/com/tencent/trtc/videocall/FloatingView.java
  10. 280 0
      VideoCall/src/main/java/com/tencent/trtc/videocall/GenerateTestUserSig.java
  11. 68 0
      VideoCall/src/main/java/com/tencent/trtc/videocall/TRTCBaseActivity.java
  12. 250 0
      VideoCall/src/main/java/com/tencent/trtc/videocall/VideoCallingActivity.java
  13. 81 0
      VideoCall/src/main/java/com/tencent/trtc/videocall/VideoCallingEnterActivity.java
  14. 11 0
      VideoCall/src/main/res/drawable/common_button_bg.xml
  15. 11 0
      VideoCall/src/main/res/drawable/un_button_bg.xml
  16. 5 0
      VideoCall/src/main/res/drawable/videocall_background.xml
  17. 93 0
      VideoCall/src/main/res/layout/videocall_activit_enter.xml
  18. 84 0
      VideoCall/src/main/res/layout/videocall_activity_calling.xml
  19. 18 0
      VideoCall/src/main/res/layout/videocall_popup_layout.xml
  20. 12 0
      VideoCall/src/main/res/layout/videocall_view_floating_default.xml
  21. BIN
      VideoCall/src/main/res/mipmap-xxhdpi/common_ic_back.png
  22. BIN
      VideoCall/src/main/res/mipmap-xxhdpi/icon_guaduan.png
  23. BIN
      VideoCall/src/main/res/mipmap-xxhdpi/icon_maike.png
  24. BIN
      VideoCall/src/main/res/mipmap-xxhdpi/icon_qiehuan.png
  25. BIN
      VideoCall/src/main/res/mipmap-xxhdpi/videocall_float_logo.png
  26. BIN
      VideoCall/src/main/res/mipmap-xxhdpi/videocall_home.png
  27. 18 0
      VideoCall/src/main/res/values-en/strings.xml
  28. 7 0
      VideoCall/src/main/res/values/colors.xml
  29. 18 0
      VideoCall/src/main/res/values/strings.xml
  30. 2 2
      app/build.gradle
  31. BIN
      app/release/fushan_1.0.0.202110140001.apk
  32. BIN
      app/release/fushan_1.0.0.apk
  33. 18 0
      app/release/output-metadata.json
  34. 14 6
      app/src/main/AndroidManifest.xml
  35. 30 12
      app/src/main/java/com/qingdaofushan/home/activity/MainActivity.java
  36. 6 11
      app/src/main/java/com/qingdaofushan/home/component/ApiInterceptor.java
  37. 29 2
      app/src/main/java/com/qingdaofushan/home/component/CoreService.java
  38. 1 2
      app/src/main/java/com/qingdaofushan/home/view/VersionCheckingUtil.java
  39. 58 58
      app/src/main/java/com/qingdaofushan/home/weiview/WebViewActivity.java
  40. 6 2
      app/src/main/res/layout/activity_main.xml
  41. BIN
      app/src/main/res/mipmap-xhdpi/icon_laoren_logo.png
  42. BIN
      app/src/main/res/mipmap-xhdpi/icon_login_bg.png
  43. BIN
      fushan
  44. 2 1
      settings.gradle

+ 1 - 0
.idea/gradle.xml

@@ -11,6 +11,7 @@
         <option name="modules">
           <set>
             <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/VideoCall" />
             <option value="$PROJECT_DIR$/app" />
           </set>
         </option>

+ 6 - 1
.idea/misc.xml

@@ -4,13 +4,18 @@
     <option name="filePathToZoomLevelMap">
       <map>
         <entry key="../../../../layout/custom_preview.xml" value="0.20925925925925926" />
+        <entry key="VideoCall/src/main/res/drawable/common_button_bg.xml" value="0.2765625" />
+        <entry key="VideoCall/src/main/res/drawable/un_button_bg.xml" value="0.2765625" />
+        <entry key="VideoCall/src/main/res/layout/videocall_activit_enter.xml" value="0.13489583333333333" />
+        <entry key="VideoCall/src/main/res/layout/videocall_activity_calling.xml" value="0.125" />
+        <entry key="VideoCall/src/main/res/layout/videocall_popup_layout.xml" value="0.18070652173913043" />
         <entry key="app/src/main/res/drawable/progressbar_h1.xml" value="0.20833333333333334" />
         <entry key="app/src/main/res/drawable/progressbar_h_shape1.xml" value="0.20833333333333334" />
         <entry key="app/src/main/res/drawable/shape_custom_dialog.xml" value="0.20833333333333334" />
         <entry key="app/src/main/res/drawable/toast_background.xml" value="0.2212962962962963" />
         <entry key="app/src/main/res/layout/activity_cam.xml" value="0.18297101449275363" />
         <entry key="app/src/main/res/layout/activity_live.xml" value="0.18931159420289856" />
-        <entry key="app/src/main/res/layout/activity_main.xml" value="0.165" />
+        <entry key="app/src/main/res/layout/activity_main.xml" value="0.25" />
         <entry key="app/src/main/res/layout/activity_scanner.xml" value="0.18297101449275363" />
         <entry key="app/src/main/res/layout/activity_web.xml" value="0.2028985507246377" />
         <entry key="app/src/main/res/layout/layout_download_dialog.xml" value="0.1" />

+ 1 - 0
VideoCall/.gitignore

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

+ 27 - 0
VideoCall/build.gradle

@@ -0,0 +1,27 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+    defaultConfig {
+        minSdk 22
+        targetSdk 29
+        ndk {
+            abiFilters "armeabi-v7a", "arm64-v8a"
+        }
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'androidx.appcompat:appcompat:1.1.0'
+    implementation 'com.tencent.liteav:LiteAVSDK_TRTC:latest.release'
+}

+ 21 - 0
VideoCall/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 13 - 0
VideoCall/src/main/AndroidManifest.xml

@@ -0,0 +1,13 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.tencent.trtc.videocall">
+
+    <application>
+        <activity
+            android:name="com.tencent.trtc.videocall.VideoCallingActivity"
+            android:screenOrientation="landscape" />
+        <activity
+            android:name="com.tencent.trtc.videocall.VideoCallingEnterActivity"
+            android:screenOrientation="landscape" />
+    </application>
+
+</manifest>

+ 25 - 0
VideoCall/src/main/java/com/tencent/trtc/videocall/Constant.java

@@ -0,0 +1,25 @@
+package com.tencent.trtc.videocall;
+
+public class Constant {
+
+    public static final String ROOM_ID = "room_id";
+    public static final String USER_ID = "user_id";
+    public static final String ROLE_TYPE = "role_type";
+    public static final String CUSTOM_VIDEO = "custom_video";
+
+    // 美颜风格.三种美颜风格:0 :光滑  1:自然  2:朦胧
+    public static final int     BEAUTY_STYLE_SMOOTH              = 0;
+    public static final int     BEAUTY_STYLE_NATURE              = 1;
+
+    public static final int     VIDEO_FPS                        = 15;
+    // RTC 通话场景:640*360,15fps,550kbps
+    public static final int     RTC_VIDEO_BITRATE                = 550;
+
+    // 直播场景:连麦小主播:270*480, 15pfs, 400kbps
+    public static final int LIVE_270_480_VIDEO_BITRATE           = 400;
+    public static final int     LIVE_360_640_VIDEO_BITRATE       = 800;
+    // 直播场景:大主播:默认 540*960, 15fps,1200kbps
+    public static final int     LIVE_540_960_VIDEO_BITRATE       = 900;
+    public static final int     LIVE_720_1280_VIDEO_BITRATE      = 1500;
+
+}

+ 1 - 1
app/src/main/java/com/qingdaofushan/home/utils/DeviceUtil.java → VideoCall/src/main/java/com/tencent/trtc/videocall/DeviceUtil.java

@@ -1,4 +1,4 @@
-package com.qingdaofushan.home.utils;
+package com.tencent.trtc.videocall;
 
 import android.app.Activity;
 import android.app.ActivityManager;

+ 193 - 0
VideoCall/src/main/java/com/tencent/trtc/videocall/FloatingView.java

@@ -0,0 +1,193 @@
+package com.tencent.trtc.videocall;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.PopupWindow;
+
+/**
+ * 悬浮球,点击可以弹出菜单
+ */
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+public class FloatingView extends FrameLayout implements GestureDetector.OnGestureListener {
+
+    private Context                     mContext;
+    private WindowManager               mWindowManager;
+    private GestureDetector             mGestureDetector;
+    private WindowManager.LayoutParams  mLayoutParams;
+    private float                       mLastX;
+    private float                       mLastY;
+    private PopupWindow                 mPopupWindow;
+    private long                        mTapOutsideTime;
+    private boolean                     mIsShowing = false;
+
+    public FloatingView(Context context) {
+        super(context);
+        this.mContext = context;
+        this.mGestureDetector = new GestureDetector(context, this);
+    }
+
+    public FloatingView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        this.mContext = context;
+        this.mGestureDetector = new GestureDetector(context, this);
+    }
+
+    public FloatingView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        this.mContext = context;
+        this.mGestureDetector = new GestureDetector(context, this);
+    }
+
+    public FloatingView(Context context, int viewResId) {
+        super(context);
+        this.mContext = context;
+        View.inflate(context, viewResId, this);
+        this.mGestureDetector = new GestureDetector(context, this);
+    }
+
+    public void showView(View view) {
+        showView(view, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
+    }
+
+    public void showView(View view, int width, int height) {
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        int type = WindowManager.LayoutParams.TYPE_TOAST;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
+            type = WindowManager.LayoutParams.TYPE_PHONE;
+        }
+        mLayoutParams = new WindowManager.LayoutParams(type);
+        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+        mLayoutParams.width = width;
+        mLayoutParams.height = height;
+        mLayoutParams.format = PixelFormat.TRANSLUCENT;
+        mWindowManager.addView(view, mLayoutParams);
+    }
+
+    public void hideView() {
+        if (null != mWindowManager) {
+            mWindowManager.removeViewImmediate(this);
+        }
+        mWindowManager = null;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return mGestureDetector.onTouchEvent(event);
+    }
+
+    @Override
+    public boolean onDown(MotionEvent e) {
+        mLastX = e.getRawX();
+        mLastY = e.getRawY();
+        return false;
+    }
+
+    @Override
+    public void onShowPress(MotionEvent e) {
+    }
+
+    @Override
+    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+        float nowX, nowY, tranX, tranY;
+        nowX = e2.getRawX();
+        nowY = e2.getRawY();
+        tranX = nowX - mLastX;
+        tranY = nowY - mLastY;
+        mLayoutParams.x += tranX;
+        mLayoutParams.y += tranY;
+        mWindowManager.updateViewLayout(this, mLayoutParams);
+        mLastX = nowX;
+        mLastY = nowY;
+        return false;
+    }
+
+    @Override
+    public void onLongPress(MotionEvent e) {
+    }
+
+    @Override
+    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+        return false;
+    }
+
+    public void setPopupWindow(int id) {
+        mPopupWindow = new PopupWindow(this);
+        mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
+        mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+        mPopupWindow.setTouchable(true);
+        mPopupWindow.setOutsideTouchable(true);
+        mPopupWindow.setFocusable(false);
+        mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
+        mPopupWindow.setContentView(LayoutInflater.from(getContext()).inflate(id, null));
+        mPopupWindow.setTouchInterceptor(new OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                    mPopupWindow.dismiss();
+                    mTapOutsideTime = System.currentTimeMillis();
+                    return true;
+                }
+                return false;
+            }
+        });
+    }
+
+    public View getPopupView() {
+        return mPopupWindow.getContentView();
+    }
+
+    public void setOnPopupItemClickListener(OnClickListener listener) {
+        if (mPopupWindow == null)
+            return;
+
+        ViewGroup layout = (ViewGroup) mPopupWindow.getContentView();
+        for (int i = 0; i < layout.getChildCount(); i++) {
+            layout.getChildAt(i).setOnClickListener(listener);
+        }
+    }
+
+    public void show() {
+        if (!mIsShowing) {
+            showView(this);
+        }
+        mIsShowing = true;
+    }
+
+    public void dismiss() {
+        if (mIsShowing) {
+            hideView();
+        }
+        mIsShowing = false;
+        ViewGroup layout = (ViewGroup) mPopupWindow.getContentView();
+        for (int i = 0; i < layout.getChildCount(); i++) {
+            layout.getChildAt(i).setOnClickListener(null);
+        }
+    }
+
+    @Override
+    public boolean onSingleTapUp(MotionEvent e) {
+        if (null != mPopupWindow)
+            mPopupWindow.dismiss();
+        if (!(System.currentTimeMillis() - mTapOutsideTime < 80)) {
+            mPopupWindow.showAtLocation(this, Gravity.NO_GRAVITY, 100, 0);
+        }
+        return false;
+    }
+
+
+}

+ 280 - 0
VideoCall/src/main/java/com/tencent/trtc/videocall/GenerateTestUserSig.java

@@ -0,0 +1,280 @@
+package com.tencent.trtc.videocall;
+
+
+import android.util.Base64;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.zip.Deflater;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Module:   GenerateTestUserSig
+ *
+ * Function: 用于生成测试用的 UserSig,UserSig 是腾讯云为其云服务设计的一种安全保护签名。
+ *           其计算方法是对 SDKAppID、UserID 和 EXPIRETIME 进行加密,加密算法为 HMAC-SHA256。
+ *
+ * Attention: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
+ *
+ *            本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
+ *            这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
+ *            一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
+ *
+ *            正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
+ *            由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
+ *
+ * Reference:https://cloud.tencent.com/document/product/647/17275#Server
+ */
+
+/**
+ * Module:   GenerateTestUserSig
+ *
+ * Description: generates UserSig for testing. UserSig is a security signature designed by Tencent Cloud for its cloud services.
+ *           It is calculated based on `SDKAppID`, `UserID`, and `EXPIRETIME` using the HMAC-SHA256 encryption algorithm.
+ *
+ * Attention: do not use the code below in your commercial app. This is because:
+ *
+ *            The code may be able to calculate UserSig correctly, but it is only for quick testing of the SDK’s basic features, not for commercial apps.
+ *            `SECRETKEY` in client code can be easily decompiled and reversed, especially on web.
+ *             Once your key is disclosed, attackers will be able to steal your Tencent Cloud traffic.
+ *
+ *            The correct method is to deploy the `UserSig` calculation code and encryption key on your project server so that your app can request from your server a `UserSig` that is calculated whenever one is needed.
+ *           Given that it is more difficult to hack a server than a client app, server-end calculation can better protect your key.
+ *
+ * Reference: https://cloud.tencent.com/document/product/647/17275#Server
+ */
+public class GenerateTestUserSig {
+
+    /**
+     * 配置为CDN发布、混流的域名
+     *
+     */
+
+    /**
+     * Domain name for CDN publishing and stream mixing
+     */
+    public static final String  CDN_DOMAIN_NAME = "live.pwxmax.cn";
+
+    /**
+     * CDN发布功能 混流bizId
+     */
+
+    /**
+     * `bizId` for CDN publishing and stream mixing
+     */
+    public static final int BIZID = 135161;
+
+    /**
+     * CDN发布功能 混流appId
+     */
+
+    /**
+     * `appId` for CDN publishing and stream mixing
+     */
+    public static final int APPID = 1253658654;
+
+    /**
+     * 腾讯云 SDKAppId,需要替换为您自己账号下的 SDKAppId。
+     *
+     * 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ) 创建应用,即可看到 SDKAppId,
+     * 它是腾讯云用于区分客户的唯一标识。
+     */
+
+    /**
+     * Tencent Cloud `SDKAppID`. Set it to the `SDKAppID` of your account.
+     *
+     * You can view your `SDKAppID` after creating an application in the [TRTC console](https://console.cloud.tencent.com/rav).
+     * `SDKAppID` uniquely identifies a Tencent Cloud account.
+     */
+    public static final int SDKAPPID = 1400589545;
+
+    /**
+     * 签名过期时间,建议不要设置的过短
+     * <p>
+     * 时间单位:秒
+     * 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天
+     */
+
+    /**
+     * Signature validity period, which should not be set too short
+     * <p>
+     * Unit: second
+     * Default value: 604800 (7 days)
+     */
+    private static final int EXPIRETIME = 604800;
+
+
+    /**
+     * 计算签名用的加密密钥,获取步骤如下:
+     *
+     * step1. 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ),如果还没有应用就创建一个,
+     * step2. 单击应用信息,并进一步找到“快速上手”部分。
+     * step3. 点击“复制密钥”按钮,复制密钥,请将其拷贝并复制到如下的变量中
+     *
+     * 注意:该方案仅适用于调试Demo,正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。
+     * 文档:https://cloud.tencent.com/document/product/647/17275#Server
+     */
+
+    /**
+     * Follow the steps below to obtain the key required for UserSig calculation.
+     *
+     * Step 1. Log in to the [TRTC console](https://console.cloud.tencent.com/rav), and create an application if you don’t have one.
+     * Step 2. Find your application, click “Application Info”, and click the “Quick Start” tab.
+     * Step 3. Copy and paste the key to the code, as shown below.
+     *
+     * Note: this method is for testing only. Before commercial launch, please migrate the UserSig calculation code and key to your backend server to prevent key disclosure and traffic stealing.
+     * Reference: https://cloud.tencent.com/document/product/647/17275#Server
+     */
+    public static final String SECRETKEY = "310c3bedc8287ecef1740655bc1f2cbd5c78ea7a4588bdde61a085d09affd3f1";
+
+    /**
+     * 计算 UserSig 签名
+     *
+     * 函数内部使用 HMAC-SHA256 非对称加密算法,对 SDKAPPID、userId 和 EXPIRETIME 进行加密。
+     *
+     * @note: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
+     *
+     * 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
+     * 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
+     * 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
+     *
+     * 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
+     * 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
+     *
+     * 文档:https://cloud.tencent.com/document/product/647/17275#Server
+     */
+
+    /**
+     * Calculating UserSig
+     *
+     * The asymmetric encryption algorithm HMAC-SHA256 is used in the function to calculate UserSig based on `SDKAppID`, `UserID`, and `EXPIRETIME`.
+     *
+     * @note: do not use the code below in your commercial app. This is because:
+     *
+     * The code may be able to calculate UserSig correctly, but it is only for quick testing of the SDK’s basic features, not for commercial apps.
+     * `SECRETKEY` in client code can be easily decompiled and reversed, especially on web.
+     * Once your key is disclosed, attackers will be able to steal your Tencent Cloud traffic.
+     *
+     * The correct method is to deploy the `UserSig` calculation code on your project server so that your app can request from your server a `UserSig` that is calculated whenever one is needed.
+     * Given that it is more difficult to hack a server than a client app, server-end calculation can better protect your key.
+     *
+     * Reference: https://cloud.tencent.com/document/product/647/17275#Server
+     */
+    public static String genTestUserSig(String userId) {
+        return GenTLSSignature(SDKAPPID, userId, EXPIRETIME, null, SECRETKEY);
+    }
+
+    /**
+     * 生成 tls 票据
+     *
+     * @param sdkappid    应用的 appid
+     * @param userId      用户 id
+     * @param expire      有效期,单位是秒
+     * @param userbuf     默认填写null
+     * @param priKeyContent 生成 tls 票据使用的私钥内容
+     * @return 如果出错,会返回为空,或者有异常打印,成功返回有效的票据
+     */
+
+    /**
+     * Generating a TLS Ticket
+     *
+     * @param sdkappid    `appid` of your application
+     * @param userId      User ID
+     * @param expire      Validity period, in seconds
+     * @param userbuf     `null` by default
+     * @param priKeyContent Private key required for generating a TLS ticket
+     * @return If an error occurs, an empty string will be returned or exceptions printed. If the operation succeeds, a valid ticket will be returned.
+     */
+    private static String GenTLSSignature(long sdkappid, String userId, long expire, byte[] userbuf, String priKeyContent) {
+        long currTime = System.currentTimeMillis() / 1000;
+        JSONObject sigDoc = new JSONObject();
+        try {
+            sigDoc.put("TLS.ver", "2.0");
+            sigDoc.put("TLS.identifier", userId);
+            sigDoc.put("TLS.sdkappid", sdkappid);
+            sigDoc.put("TLS.expire", expire);
+            sigDoc.put("TLS.time", currTime);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        String base64UserBuf = null;
+        if (null != userbuf) {
+            base64UserBuf = Base64.encodeToString(userbuf, Base64.NO_WRAP);
+            try {
+                sigDoc.put("TLS.userbuf", base64UserBuf);
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+        }
+        String sig = hmacsha256(sdkappid, userId, currTime, expire, priKeyContent, base64UserBuf);
+        if (sig.length() == 0) {
+            return "";
+        }
+        try {
+            sigDoc.put("TLS.sig", sig);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        Deflater compressor = new Deflater();
+        compressor.setInput(sigDoc.toString().getBytes(Charset.forName("UTF-8")));
+        compressor.finish();
+        byte[] compressedBytes = new byte[2048];
+        int compressedBytesLength = compressor.deflate(compressedBytes);
+        compressor.end();
+        return new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength)));
+    }
+
+
+    private static String hmacsha256(long sdkappid, String userId, long currTime, long expire, String priKeyContent, String base64Userbuf) {
+        String contentToBeSigned = "TLS.identifier:" + userId + "\n"
+                + "TLS.sdkappid:" + sdkappid + "\n"
+                + "TLS.time:" + currTime + "\n"
+                + "TLS.expire:" + expire + "\n";
+        if (null != base64Userbuf) {
+            contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
+        }
+        try {
+            byte[] byteKey = priKeyContent.getBytes("UTF-8");
+            Mac hmac = Mac.getInstance("HmacSHA256");
+            SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
+            hmac.init(keySpec);
+            byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes("UTF-8"));
+            return new String(Base64.encode(byteSig, Base64.NO_WRAP));
+        } catch (UnsupportedEncodingException e) {
+            return "";
+        } catch (NoSuchAlgorithmException e) {
+            return "";
+        } catch (InvalidKeyException e) {
+            return "";
+        }
+    }
+
+    private static byte[] base64EncodeUrl(byte[] input) {
+        byte[] base64 = new String(Base64.encode(input, Base64.NO_WRAP)).getBytes();
+        for (int i = 0; i < base64.length; ++i)
+            switch (base64[i]) {
+                case '+':
+                    base64[i] = '*';
+                    break;
+                case '/':
+                    base64[i] = '-';
+                    break;
+                case '=':
+                    base64[i] = '_';
+                    break;
+                default:
+                    break;
+            }
+        return base64;
+    }
+
+}

+ 68 - 0
VideoCall/src/main/java/com/tencent/trtc/videocall/TRTCBaseActivity.java

@@ -0,0 +1,68 @@
+package com.tencent.trtc.videocall;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public abstract class TRTCBaseActivity extends AppCompatActivity {
+
+    protected static final int REQ_PERMISSION_CODE = 0x1000;
+    protected int              mGrantedCount       = 0;
+
+    protected abstract void onPermissionGranted();
+
+    protected boolean checkPermission() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            List<String> permissions = new ArrayList<>();
+            if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+                permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+            }
+            if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)) {
+                permissions.add(Manifest.permission.CAMERA);
+            }
+            if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)) {
+                permissions.add(Manifest.permission.RECORD_AUDIO);
+            }
+            if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
+                permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+            }
+            if (permissions.size() != 0) {
+                ActivityCompat.requestPermissions(TRTCBaseActivity.this,
+                        permissions.toArray(new String[0]),
+                        REQ_PERMISSION_CODE);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        switch (requestCode) {
+            case REQ_PERMISSION_CODE:
+                for (int ret : grantResults) {
+                    if (PackageManager.PERMISSION_GRANTED == ret) {
+                        mGrantedCount ++;
+                    }
+                }
+                if (mGrantedCount == permissions.length) {
+                    onPermissionGranted();
+                } else {
+                    Toast.makeText(this, "用户没有允许需要的权限,加入通话失败", Toast.LENGTH_SHORT).show();
+                }
+                mGrantedCount = 0;
+                break;
+            default:
+                break;
+        }
+    }
+}

+ 250 - 0
VideoCall/src/main/java/com/tencent/trtc/videocall/VideoCallingActivity.java

@@ -0,0 +1,250 @@
+package com.tencent.trtc.videocall;
+
+import static android.widget.RelativeLayout.ALIGN_PARENT_END;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.tencent.liteav.TXLiteAVCode;
+import com.tencent.liteav.device.TXDeviceManager;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+import com.tencent.trtc.TRTCCloud;
+import com.tencent.trtc.TRTCCloudDef;
+import com.tencent.trtc.TRTCCloudListener;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * TRTC视频通话的主页面
+ * <p>
+ * 包含如下简单功能:
+ * - 进入视频通话房间{@link VideoCallingActivity#enterRoom()}
+ * - 退出视频通话房间{@link VideoCallingActivity#exitRoom()}
+ * - 切换前置/后置摄像头{@link VideoCallingActivity#switchCamera()}
+ * - 打开/关闭摄像头{@link VideoCallingActivity#muteVideo()}
+ * - 打开/关闭麦克风{@link VideoCallingActivity#muteAudio()}
+ * - 显示房间内其他用户的视频画面(当前示例最多可显示6个其他用户的视频画面){@link TRTCCloudImplListener#refreshRemoteVideoViews()}
+ * <p>
+ * - 详见接入文档{https://cloud.tencent.com/document/product/647/42045}
+ */
+
+/**
+ * Video Call
+ * <p>
+ * Features:
+ * - Enter a video call room: {@link VideoCallingActivity#enterRoom()}
+ * - Exit a video call room: {@link VideoCallingActivity#exitRoom()}
+ * - Display the video of other users (max. 6) in the room: {@link TRTCCloudImplListener#refreshRemoteVideoViews()}
+ * <p>
+ * - For more information, please see the integration document {https://cloud.tencent.com/document/product/647/42045}.
+ */
+public class VideoCallingActivity extends TRTCBaseActivity implements View.OnClickListener {
+
+    private static final String TAG = "VideoCallingActivity";
+    private static final int OVERLAY_PERMISSION_REQ_CODE = 1234;
+
+    private TXCloudVideoView mTXCVVLocalPreviewView;
+    private TXCloudVideoView mTXCVVLocalTwoView;
+    private TXCloudVideoView mTXCVVLocalTwoView1;
+    private RelativeLayout rl_maike;
+    private RelativeLayout rl_guaduan;
+    private RelativeLayout rl_qiehuan;
+
+    private TRTCCloud mTRTCCloud;
+    private TXDeviceManager mTXDeviceManager;
+    private boolean mIsFrontCamera = true;
+    private String mRemoteUid;
+    private int mUserCount = 0;
+    private String mRoomId;
+    private String mUserId;
+    private boolean mAudioRouteFlag = true;
+    private boolean mVideoViewFlag = true;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.videocall_activity_calling);
+        handleIntent();
+
+        if (checkPermission()) {
+            initView();
+            enterRoom();
+        }
+    }
+
+    private void handleIntent() {
+        Intent intent = getIntent();
+        if (null != intent) {
+            if (intent.getStringExtra(Constant.USER_ID) != null) {
+                mUserId = intent.getStringExtra(Constant.USER_ID);
+            }
+            if (intent.getStringExtra(Constant.ROOM_ID) != null) {
+                mRoomId = intent.getStringExtra(Constant.ROOM_ID);
+            }
+        }
+    }
+
+    private void initView() {
+        mTXCVVLocalPreviewView = findViewById(R.id.txcvv_main);
+        mTXCVVLocalTwoView = findViewById(R.id.trtc_view_1);
+        mTXCVVLocalTwoView1 = findViewById(R.id.trtc_view_2);
+        rl_maike = findViewById(R.id.rl_maike);
+        rl_guaduan = findViewById(R.id.rl_guaduan);
+        rl_qiehuan = findViewById(R.id.rl_qiehuan);
+        rl_maike.setOnClickListener(this);
+        rl_guaduan.setOnClickListener(this);
+        rl_qiehuan.setOnClickListener(this);
+    }
+
+    private void enterRoom() {
+        mTRTCCloud = TRTCCloud.sharedInstance(getApplicationContext());
+        mTRTCCloud.setListener(new TRTCCloudImplListener(VideoCallingActivity.this));
+        mTXDeviceManager = mTRTCCloud.getDeviceManager();
+
+        TRTCCloudDef.TRTCParams trtcParams = new TRTCCloudDef.TRTCParams();
+        trtcParams.sdkAppId = GenerateTestUserSig.SDKAPPID;
+        trtcParams.userId = mUserId;
+        trtcParams.roomId = Integer.parseInt(mRoomId);
+        trtcParams.userSig = GenerateTestUserSig.genTestUserSig(trtcParams.userId);
+
+        mTRTCCloud.startLocalPreview(mIsFrontCamera, mTXCVVLocalPreviewView);
+        mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH);
+        mTRTCCloud.enterRoom(trtcParams, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL);
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        exitRoom();
+    }
+
+    private void exitRoom() {
+        if (mTRTCCloud != null) {
+            mTRTCCloud.stopLocalAudio();
+            mTRTCCloud.stopLocalPreview();
+            mTRTCCloud.exitRoom();
+            mTRTCCloud.setListener(null);
+        }
+        mTRTCCloud = null;
+        TRTCCloud.destroySharedInstance();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    protected void onPermissionGranted() {
+        initView();
+        enterRoom();
+    }
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == R.id.iv_back) {
+            finish();
+        } else if (id == R.id.rl_qiehuan) {
+            qiehuan();
+        } else if (id == R.id.rl_maike) {
+            muteAudio();
+        } else if (id == R.id.rl_guaduan) {
+            finish();
+        }
+    }
+
+
+    private void qiehuan() {
+        if (mVideoViewFlag) {
+            mVideoViewFlag = false;
+            mTRTCCloud.stopAllRemoteView();
+            mTRTCCloud.stopLocalPreview();
+            mTRTCCloud.startRemoteView(mRemoteUid, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SMALL, mTXCVVLocalTwoView1);
+            mTRTCCloud.startLocalPreview(mIsFrontCamera, mTXCVVLocalTwoView);
+        } else {
+            mVideoViewFlag = true;
+            mTRTCCloud.stopAllRemoteView();
+            mTRTCCloud.stopLocalPreview();
+            mTRTCCloud.startRemoteView(mRemoteUid, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SMALL, mTXCVVLocalTwoView);
+            mTRTCCloud.startLocalPreview(mIsFrontCamera, mTXCVVLocalPreviewView);
+        }
+
+    }
+
+    private boolean isAudio = true;
+
+    private void muteAudio() {
+        if (isAudio) {
+            isAudio = false;
+            rl_maike.setBackground(this.getDrawable(R.drawable.un_button_bg));
+            mTRTCCloud.muteLocalAudio(true);
+        } else {
+            isAudio = true;
+            rl_maike.setBackground(this.getDrawable(R.drawable.common_button_bg));
+            mTRTCCloud.muteLocalAudio(false);
+        }
+    }
+
+    private class TRTCCloudImplListener extends TRTCCloudListener {
+
+        private WeakReference<VideoCallingActivity> mContext;
+
+        public TRTCCloudImplListener(VideoCallingActivity activity) {
+            super();
+            mContext = new WeakReference<>(activity);
+        }
+
+        @Override
+        public void onUserVideoAvailable(String userId, boolean available) {
+            Log.d(TAG, "onUserVideoAvailable userId " + userId + ", mUserCount " + mUserCount + ",available " + available);
+            if (TextUtils.isEmpty(mRemoteUid)) {
+                if (available) {
+                    mRemoteUid = userId;
+                    refreshRemoteVideoViews();
+                } else {
+                    mTRTCCloud.stopRemoteView(userId);
+                    mRemoteUid = "";
+                    refreshRemoteVideoViews();
+                }
+            }
+
+        }
+
+        private void refreshRemoteVideoViews() {
+            mTRTCCloud.startRemoteView(mRemoteUid, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SMALL, mTXCVVLocalTwoView);
+        }
+
+        @Override
+        public void onError(int errCode, String errMsg, Bundle extraInfo) {
+            Log.d(TAG, "sdk callback onError");
+            VideoCallingActivity activity = mContext.get();
+            if (activity != null) {
+                Toast.makeText(activity, "onError: " + errMsg + "[" + errCode + "]", Toast.LENGTH_SHORT).show();
+                if (errCode == TXLiteAVCode.ERR_ROOM_ENTER_FAIL) {
+                    activity.exitRoom();
+                }
+            }
+        }
+    }
+
+}

+ 81 - 0
VideoCall/src/main/java/com/tencent/trtc/videocall/VideoCallingEnterActivity.java

@@ -0,0 +1,81 @@
+package com.tencent.trtc.videocall;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+
+/**
+ * TRTC视频通话的入口页面(可以设置房间id和用户id)
+ *
+ * - 可跳转TRTC视频通话页面{@link VideoCallingActivity}
+ */
+
+/**
+ * Video Call Entrance View (set room ID and user ID)
+ *
+ * - Direct to the video call view: {@link VideoCallingActivity}
+ */
+public class VideoCallingEnterActivity extends AppCompatActivity {
+
+    private EditText mEditInputUserId;
+    private EditText mEditInputRoomId;
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.videocall_activit_enter);
+        mEditInputUserId = findViewById(R.id.et_input_username);
+        mEditInputRoomId = findViewById(R.id.et_input_room_id);
+        findViewById(R.id.btn_enter_room).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                startEnterRoom();
+            }
+        });
+        findViewById(R.id.rl_entrance_main).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                hideInput();
+            }
+        });
+        findViewById(R.id.iv_back).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                finish();
+            }
+        });
+        mEditInputRoomId.setText("1256732");
+        String time = String.valueOf(System.currentTimeMillis());
+        String userId = time.substring(time.length() - 8);
+        mEditInputUserId.setText(userId);
+    }
+
+    private void startEnterRoom() {
+        if (TextUtils.isEmpty(mEditInputUserId.getText().toString().trim())
+                || TextUtils.isEmpty(mEditInputRoomId.getText().toString().trim())) {
+            Toast.makeText(VideoCallingEnterActivity.this, getString(R.string.videocall_room_input_error_tip), Toast.LENGTH_LONG).show();
+            return;
+        }
+        Intent intent = new Intent(VideoCallingEnterActivity.this, VideoCallingActivity.class);
+        intent.putExtra(Constant.ROOM_ID, mEditInputRoomId.getText().toString().trim());
+        intent.putExtra(Constant.USER_ID, mEditInputUserId.getText().toString().trim());
+        startActivity(intent);
+    }
+
+    protected void hideInput() {
+        InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
+        View v = getWindow().peekDecorView();
+        if (null != v) {
+            imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
+        }
+    }
+
+}

+ 11 - 0
VideoCall/src/main/res/drawable/common_button_bg.xml

@@ -0,0 +1,11 @@
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <solid android:color="@color/common_green_bg" />
+
+    <corners
+        android:bottomLeftRadius="5dip"
+        android:bottomRightRadius="5dip"
+        android:topLeftRadius="5dip"
+        android:topRightRadius="5dip" />
+</shape>

+ 11 - 0
VideoCall/src/main/res/drawable/un_button_bg.xml

@@ -0,0 +1,11 @@
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <solid android:color="#33E7E4EC" />
+
+    <corners
+        android:bottomLeftRadius="5dip"
+        android:bottomRightRadius="5dip"
+        android:topLeftRadius="5dip"
+        android:topRightRadius="5dip" />
+</shape>

+ 5 - 0
VideoCall/src/main/res/drawable/videocall_background.xml

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

+ 93 - 0
VideoCall/src/main/res/layout/videocall_activit_enter.xml

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/rl_entrance_main"
+    android:background="@color/rl_main_bg">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <ImageView
+            android:id="@+id/iv_back"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="10dp"
+            android:layout_marginTop="15dp"
+            android:background="@mipmap/common_ic_back" />
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="40dp"
+            android:layout_marginTop="15dp"
+            android:gravity="center_horizontal"
+            android:text="@string/videocall_title"
+            android:textColor="@android:color/white"
+            android:textSize="20sp" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_room_info"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_marginTop="100dp"
+        android:layout_marginRight="60dp"
+        android:layout_marginLeft="60dp"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@android:color/white"
+            android:text="@string/videocall_please_input_roomid" />
+
+        <EditText
+            android:id="@+id/et_input_room_id"
+            android:layout_width="match_parent"
+            android:layout_height="34dp"
+            android:layout_marginTop="5dp"
+            android:inputType="number" />
+
+    </LinearLayout>
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/ll_room_info"
+        android:layout_centerHorizontal="true"
+        android:layout_marginTop="30dp"
+        android:layout_marginLeft="60dp"
+        android:layout_marginRight="60dp"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@android:color/white"
+            android:text="@string/videocall_please_input_userid" />
+
+        <EditText
+            android:id="@+id/et_input_username"
+            android:layout_width="match_parent"
+            android:layout_height="34dp"
+            android:layout_marginTop="5dp"
+            />
+
+    </LinearLayout>
+
+    <Button
+        android:id="@+id/btn_enter_room"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:background="@drawable/common_button_bg"
+        android:textColor="@android:color/white"
+        android:layout_margin="60dp"
+        android:text="@string/videocall_enter_room" />
+
+</RelativeLayout>

+ 84 - 0
VideoCall/src/main/res/layout/videocall_activity_calling.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/rl_main_bg">
+
+    <com.tencent.rtmp.ui.TXCloudVideoView
+        android:id="@+id/trtc_view_2"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <com.tencent.rtmp.ui.TXCloudVideoView
+        android:id="@+id/txcvv_main"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <com.tencent.rtmp.ui.TXCloudVideoView
+        android:id="@+id/trtc_view_1"
+        android:layout_width="180dp"
+        android:layout_height="100dp"
+        android:layout_alignParentEnd="true"
+        android:layout_marginTop="30dp"
+        android:layout_marginEnd="30dp" />
+
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_marginBottom="10dp"
+        android:visibility="visible">
+
+        <RelativeLayout
+            android:id="@+id/rl_maike"
+            android:layout_width="140dp"
+            android:layout_height="60dp"
+            android:layout_gravity="center_horizontal"
+            android:layout_marginStart="80dp"
+            android:background="@drawable/common_button_bg"
+            android:padding="5dp">
+
+            <ImageView
+                android:layout_width="40dp"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:src="@mipmap/icon_maike" />
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:id="@+id/rl_guaduan"
+            android:layout_width="140dp"
+            android:layout_height="60dp"
+            android:layout_centerInParent="true"
+            android:layout_gravity="center_horizontal"
+            android:layout_marginLeft="10dp"
+            android:background="@drawable/un_button_bg"
+            android:padding="5dp">
+
+            <ImageView
+                android:layout_width="40dp"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:src="@mipmap/icon_guaduan" />
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:id="@+id/rl_qiehuan"
+            android:layout_width="140dp"
+            android:layout_height="60dp"
+            android:layout_alignParentEnd="true"
+            android:layout_gravity="center_horizontal"
+            android:layout_marginEnd="80dp"
+            android:background="@drawable/un_button_bg"
+            android:padding="5dp">
+
+            <ImageView
+                android:layout_width="40dp"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:src="@mipmap/icon_qiehuan" />
+        </RelativeLayout>
+    </RelativeLayout>
+
+</RelativeLayout>

+ 18 - 0
VideoCall/src/main/res/layout/videocall_popup_layout.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:background="@drawable/videocall_background"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:id="@+id/iv_return"
+        android:layout_marginTop="2dp"
+        android:layout_marginBottom="2dp"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:padding="2dp"
+        android:src="@mipmap/videocall_home"
+        android:layout_width="25dp"
+        android:layout_height="25dp" />
+</LinearLayout>

+ 12 - 0
VideoCall/src/main/res/layout/videocall_view_floating_default.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="200dp"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:src="@mipmap/videocall_float_logo"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>

BIN
VideoCall/src/main/res/mipmap-xxhdpi/common_ic_back.png


BIN
VideoCall/src/main/res/mipmap-xxhdpi/icon_guaduan.png


BIN
VideoCall/src/main/res/mipmap-xxhdpi/icon_maike.png


BIN
VideoCall/src/main/res/mipmap-xxhdpi/icon_qiehuan.png


BIN
VideoCall/src/main/res/mipmap-xxhdpi/videocall_float_logo.png


BIN
VideoCall/src/main/res/mipmap-xxhdpi/videocall_home.png


+ 18 - 0
VideoCall/src/main/res/values-en/strings.xml

@@ -0,0 +1,18 @@
+<resources>
+    <string name="videocall_title">Video Call</string>
+    <string name="videocall_room_input_error_tip">Enter a room ID and username</string>
+    <string name="videocall_video_item">Video Settings</string>
+    <string name="videocall_audio_item">Audio Settings</string>
+    <string name="videocall_user_back_camera">Use Rear Camera</string>
+    <string name="videocall_user_front_camera">Use Front Camera</string>
+    <string name="videocall_open_camera">Camera On</string>
+    <string name="videocall_close_camera">Camera Off</string>
+    <string name="videocall_mute_audio">Mic On</string>
+    <string name="videocall_close_mute_audio">Mic Off</string>
+    <string name="videocall_use_speaker">Use Speaker</string>
+    <string name="videocall_use_receiver">Use Receiver</string>
+    <string name="videocall_enter_room">Enter Room</string>
+    <string name="videocall_please_input_userid">User ID (Required)</string>
+    <string name="videocall_please_input_roomid">Room ID (Required)</string>
+    <string name="videocall_roomid">Room ID: </string>
+</resources>

+ 7 - 0
VideoCall/src/main/res/values/colors.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="rl_main_bg">#1B1B1B</color>
+    <color name="common_green_bg">#34c759</color>
+    <color name="videocall_green_bg">#00A66B</color>
+    <color name="videocall_title_bg">#B7B7B7</color>
+</resources>

+ 18 - 0
VideoCall/src/main/res/values/strings.xml

@@ -0,0 +1,18 @@
+<resources>
+    <string name="videocall_title">TRTC 视频通话示例</string>
+    <string name="videocall_room_input_error_tip">"房间号和用户名不能为空"</string>
+    <string name="videocall_video_item">视频选项</string>
+    <string name="videocall_audio_item">音频选项</string>
+    <string name="videocall_user_back_camera">使用后置摄像头</string>
+    <string name="videocall_user_front_camera">使用前置摄像头</string>
+    <string name="videocall_open_camera">打开摄像头</string>
+    <string name="videocall_close_camera">关闭摄像头</string>
+    <string name="videocall_mute_audio">打开麦克风</string>
+    <string name="videocall_close_mute_audio">关闭麦克风</string>
+    <string name="videocall_use_speaker">使用扬声器</string>
+    <string name="videocall_use_receiver">使用听筒</string>
+    <string name="videocall_enter_room">进入房间</string>
+    <string name="videocall_please_input_userid">请输入用户名(必填项)</string>
+    <string name="videocall_please_input_roomid">请输入房间号(必填项)</string>
+    <string name="videocall_roomid">房间号:</string>
+</resources>

+ 2 - 2
app/build.gradle

@@ -5,7 +5,7 @@ android {
 
     defaultConfig {
         applicationId "com.qingdaofushan.home"
-        minSdk 24
+        minSdk 22
         targetSdk 29
         versionCode 1
         versionName "1.0"
@@ -30,7 +30,7 @@ android {
 }
 
 dependencies {
-
+    implementation project(':VideoCall')
     implementation 'androidx.appcompat:appcompat:1.2.0'
     implementation 'com.google.android.material:material:1.3.0'
     implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

BIN
app/release/fushan_1.0.0.202110140001.apk


BIN
app/release/fushan_1.0.0.apk


+ 18 - 0
app/release/output-metadata.json

@@ -0,0 +1,18 @@
+{
+  "version": 2,
+  "artifactType": {
+    "type": "APK",
+    "kind": "Directory"
+  },
+  "applicationId": "com.qingdaofushan.home",
+  "variantName": "processReleaseResources",
+  "elements": [
+    {
+      "type": "SINGLE",
+      "filters": [],
+      "versionCode": 1,
+      "versionName": "1.0",
+      "outputFile": "app-release.apk"
+    }
+  ]
+}

+ 14 - 6
app/src/main/AndroidManifest.xml

@@ -8,22 +8,31 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:name="android.hardware.camera.autofocus" />
 
     <application
         android:name=".component.App"
         android:allowBackup="true"
-        android:icon="@mipmap/ic_launcher"
+        android:icon="@mipmap/icon_laoren_logo"
         android:label="@string/app_name"
         android:networkSecurityConfig="@xml/network_security_config"
         android:requestLegacyExternalStorage="true"
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
         android:theme="@style/Theme.HomeCareSAS">
-        <activity android:name=".weiview.WebViewActivity"
-            android:screenOrientation="landscape"/>
+        <activity
+            android:name=".weiview.WebViewActivity"
+            android:screenOrientation="landscape" />
         <activity
             android:name=".activity.MainActivity"
-            android:exported="true">
+            android:exported="true"
+            android:screenOrientation="landscape">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 
@@ -33,8 +42,7 @@
         <!--        <activity-->
         <!--            android:name="com.king.zxing.CaptureActivity"-->
         <!--            android:theme="@style/CaptureTheme"/>-->
-        <activity android:name=".activity.CamActivity">
-        </activity>
+        <activity android:name=".activity.CamActivity"></activity>
         <activity android:name=".zxing.activity.CaptureActivity" />
 
         <service

+ 30 - 12
app/src/main/java/com/qingdaofushan/home/activity/MainActivity.java

@@ -10,6 +10,7 @@ import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.widget.EditText;
+import android.widget.TextView;
 
 import com.google.gson.Gson;
 import com.hjq.permissions.OnPermissionCallback;
@@ -32,15 +33,15 @@ import com.qingdaofushan.home.data.ConstantData;
 import com.qingdaofushan.home.data.JsonCallBack;
 import com.qingdaofushan.home.data.Url;
 import com.qingdaofushan.home.utils.CompressUtil;
+import com.qingdaofushan.home.utils.SharedPreferenceUtil;
 import com.qingdaofushan.home.utils.ToastUtil;
 import com.qingdaofushan.home.view.VersionCheckingUtil;
 import com.qingdaofushan.home.weiview.WebViewActivity;
+import com.tencent.trtc.videocall.VideoCallingEnterActivity;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -50,19 +51,23 @@ public class MainActivity extends AppCompatActivity {
 
     private String mRootUrl;
     private ServerManager mServerManager;
+    private EditText editText;
+    private TextView start;
 
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
+        start = findViewById(R.id.start);
+        editText = findViewById(R.id.ed_text);
         initPermission();
-        EditText editText = findViewById(R.id.ed_text);
-        findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
+        start.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
 //                initApp("https://cq-1253658654.file.myqcloud.com/friday.zip", 1);
 //                mServerManager.startServer();
+                SharedPreferenceUtil.put(MainActivity.this, "webUrl", editText.getText().toString());
                 Intent intent = new Intent(MainActivity.this, WebViewActivity.class);
                 intent.putExtra("url", editText.getText().toString());
 //                intent.putExtra("url", "http://127.0.0.1:8080");
@@ -81,10 +86,21 @@ public class MainActivity extends AppCompatActivity {
                     public void onGranted(List<String> permissions, boolean all) {
                         if (all) {
                             // 初始化HTTP服务
-                            mServerManager = new ServerManager(MainActivity.this);
-                            mServerManager.register();
+//                            mServerManager = new ServerManager(MainActivity.this);
+//                            mServerManager.register();
 //                            getVM();
-                            initApp("https://cq-1253658654.cos.ap-shanghai.myqcloud.com/friday.zip", 1);
+//                            initApp("https://cq-1253658654.cos.ap-shanghai.myqcloud.com/friday.zip", 1);
+//                            if (!TextUtils.isEmpty((String) SharedPreferenceUtil.get(MainActivity.this, "webUrl", ""))) {
+//                                Intent intent = new Intent(MainActivity.this, WebViewActivity.class);
+//                                intent.putExtra("url", (String) SharedPreferenceUtil.get(MainActivity.this, "webUrl", ""));
+////                            intent.putExtra("url", "http://debug.qingdaofushan.com/friday/fsmobile/#/main");
+//                                startActivity(intent);
+//                            } else {
+//                                editText.setVisibility(View.VISIBLE);
+//                                start.setVisibility(View.VISIBLE);
+//                            }
+                            Intent intent=new Intent(MainActivity.this, VideoCallingEnterActivity.class);
+                            startActivity(intent);
                         } else {
                             initPermission();
                             ToastUtil.showToast("获取部分权限成功,但部分权限未正常授予");
@@ -120,7 +136,7 @@ public class MainActivity extends AppCompatActivity {
                     .register(new DownloadListener(appWebUrl) {
                         @Override
                         public void onStart(Progress progress) {
-                            ToastUtil.showToast("开始下载");
+//                            ToastUtil.showToast("开始下载");
                         }
 
                         @Override
@@ -130,7 +146,7 @@ public class MainActivity extends AppCompatActivity {
 
                         @Override
                         public void onError(Progress progress) {
-                            ToastUtil.showToast("错误");
+                            ToastUtil.showToast("下载错误" + progress.exception.toString());
                             Log.e("pwx", "onError: " + progress.exception.toString());
                             WaitDialog.dismiss();
                         }
@@ -138,7 +154,7 @@ public class MainActivity extends AppCompatActivity {
                         @Override
                         public void onFinish(File file, Progress progress) {
                             CompressUtil.unzip(file, Environment.getExternalStorageDirectory().getAbsolutePath() + "/fshome/");
-                            ToastUtil.showToast("下载完成");
+//                            ToastUtil.showToast("下载完成");
                             mServerManager.startServer();
                             Intent intent = new Intent(MainActivity.this, WebViewActivity.class);
                             intent.putExtra("url", "http://127.0.0.1:8080/friday/fsmobile");
@@ -213,7 +229,7 @@ public class MainActivity extends AppCompatActivity {
             List<String> addressList = new LinkedList<>();
             mRootUrl = "http://127.0.0.1:8080/";
             addressList.add(mRootUrl);
-            ToastUtil.showToast("服务器启动");
+//            ToastUtil.showToast("服务器启动");
         } else {
             mRootUrl = null;
         }
@@ -273,6 +289,8 @@ public class MainActivity extends AppCompatActivity {
     @Override
     protected void onDestroy() {
         super.onDestroy();
-        mServerManager.unRegister();
+        if (mServerManager != null) {
+            mServerManager.unRegister();
+        }
     }
 }

+ 6 - 11
app/src/main/java/com/qingdaofushan/home/component/ApiInterceptor.java

@@ -11,9 +11,11 @@ import com.yanzhenjie.andserver.framework.HandlerInterceptor;
 import com.yanzhenjie.andserver.framework.handler.RequestHandler;
 import com.yanzhenjie.andserver.http.HttpRequest;
 import com.yanzhenjie.andserver.http.HttpResponse;
+import com.yanzhenjie.andserver.http.RequestWrapper;
 import com.yanzhenjie.andserver.http.StandardContext;
 import com.yanzhenjie.andserver.http.StandardRequest;
 import com.yanzhenjie.andserver.http.StandardResponse;
+import com.yanzhenjie.andserver.http.multipart.StandardMultipartRequest;
 import com.yanzhenjie.andserver.server.ProxyServer;
 import com.yanzhenjie.andserver.util.IOUtils;
 
@@ -140,25 +142,18 @@ public class ApiInterceptor implements HandlerInterceptor {
 
     @Override
     public boolean onIntercept(@NonNull HttpRequest oRequest, @NonNull HttpResponse oResponse, @NonNull RequestHandler handler) throws Exception {
-        Log.e("curacao: ", oRequest.getPath());
         HttpHost host = findPrefix(oRequest);
         if (host != null) {
-            StandardRequest sRequest = (StandardRequest) oRequest;
-
-            Field mRequestField = StandardRequest.class.getDeclaredField("mRequest");
-            mRequestField.setAccessible(true);
-            org.apache.httpcore.HttpRequest request = (org.apache.httpcore.HttpRequest) mRequestField.get(sRequest);
-
             StandardResponse sResponse = (StandardResponse) oResponse;
             Field mResponseField = StandardResponse.class.getDeclaredField("mResponse");
             mResponseField.setAccessible(true);
             org.apache.httpcore.HttpResponse response = (org.apache.httpcore.HttpResponse) mResponseField.get(sResponse);
 
-            StandardContext sContext = (StandardContext) oRequest.getContext();
-
             Field mContextField = StandardContext.class.getDeclaredField("mContext");
             mContextField.setAccessible(true);
-            HttpContext context = (HttpContext) mContextField.get(sContext);
+            HttpContext context = (HttpContext) mContextField.get(oRequest.getContext());
+
+            org.apache.httpcore.HttpRequest  request = (org.apache.httpcore.HttpRequest)context.getAttribute(HttpCoreContext.HTTP_REQUEST);
 
             for (String name : HOP_BY_HOP) {
                 request.removeHeaders(name);
@@ -177,7 +172,6 @@ public class ApiInterceptor implements HandlerInterceptor {
             mHttpExecutor.preProcess(request, mRequestProcessor, context);
             org.apache.httpcore.HttpResponse outResponse = mHttpExecutor.execute(request, conn, context);
             mHttpExecutor.postProcess(response, mRequestProcessor, context);
-
             for (String name : HOP_BY_HOP) {
                 outResponse.removeHeaders(name);
             }
@@ -193,4 +187,5 @@ public class ApiInterceptor implements HandlerInterceptor {
         }
         return false;
     }
+
 }

+ 29 - 2
app/src/main/java/com/qingdaofushan/home/component/CoreService.java

@@ -33,11 +33,36 @@ import java.util.concurrent.TimeUnit;
 public class CoreService extends Service {
 
     private Server mServer;
+    private Server webServer;
 
     @Override
     public void onCreate() {
-        mServer = AndServer.webServer(this)
-            .port(8080)
+        mServer = AndServer.proxyServer()
+                .addProxy("127.0.0.1", "http://127.0.0.1:8080")
+                .port(8080)
+                .timeout(10, TimeUnit.SECONDS)
+                .listener(new Server.ServerListener() {
+                    @Override
+                    public void onStarted() {
+                        ServerManager.onServerStart(CoreService.this, "127.0.0.1");
+                    }
+
+                    @Override
+                    public void onStopped() {
+                        ServerManager.onServerStop(CoreService.this);
+                    }
+
+                    @Override
+                    public void onException(Exception e) {
+                        e.printStackTrace();
+                        ServerManager.onServerError(CoreService.this, e.getMessage());
+                    }
+                })
+                .build();
+
+
+        webServer = AndServer.webServer(this)
+            .port(8081)
             .timeout(10, TimeUnit.SECONDS)
             .listener(new Server.ServerListener() {
                 @Override
@@ -76,6 +101,7 @@ public class CoreService extends Service {
      */
     private void startServer() {
         mServer.startup();
+        webServer.startup();
     }
 
     /**
@@ -83,6 +109,7 @@ public class CoreService extends Service {
      */
     private void stopServer() {
         mServer.shutdown();
+        webServer.shutdown();
     }
 
     @Nullable

+ 1 - 2
app/src/main/java/com/qingdaofushan/home/view/VersionCheckingUtil.java

@@ -28,12 +28,11 @@ import com.qingdaofushan.home.R;
 import com.qingdaofushan.home.activity.MainActivity;
 import com.qingdaofushan.home.bean.appVMBean;
 import com.qingdaofushan.home.component.App;
-import com.qingdaofushan.home.bean.AppUpDataItem;
 import com.qingdaofushan.home.downloadmanager.DefaultRetryPolicy;
 import com.qingdaofushan.home.downloadmanager.DownloadRequest;
 import com.qingdaofushan.home.downloadmanager.DownloadStatusListener;
 import com.qingdaofushan.home.downloadmanager.ThinDownloadManager;
-import com.qingdaofushan.home.utils.DeviceUtil;
+import com.tencent.trtc.videocall.DeviceUtil;
 import com.qingdaofushan.home.utils.ToastUtil;
 
 import java.io.File;

+ 58 - 58
app/src/main/java/com/qingdaofushan/home/weiview/WebViewActivity.java

@@ -190,14 +190,14 @@ public class WebViewActivity extends AppCompatActivity {
 
     // 2.回调方法触发本地选择文件
     private void openImageChooserActivity() {
-        checkPermissionAndCamera();
+//        checkPermissionAndCamera();
 
-//        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
-//        i.addCategory(Intent.CATEGORY_OPENABLE);
-//        i.setType("image/*");//图片上传
+        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
+        i.addCategory(Intent.CATEGORY_OPENABLE);
+        i.setType("image/*");//图片上传
 //        i.setType("file/*");//文件上传
 //        i.setType("*/*");//文件上传
-//        startActivityForResult(Intent.createChooser(i, "File Chooser"), FILE_CHOOSER_RESULT_CODE);
+        startActivityForResult(Intent.createChooser(i, "File Chooser"), FILE_CHOOSER_RESULT_CODE);
     }
 
     @Override
@@ -218,61 +218,33 @@ public class WebViewActivity extends AppCompatActivity {
 
     }
 
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-        /**
-         * 处理二维码扫描结果
-         */
-        if (resultCode == RESULT_OK) {
-            switch (requestCode) {
-                case 200:
-                    Bundle bundle = data.getExtras();
-                    String scanResult = bundle.getString(Constant.INTENT_EXTRA_KEY_QR_SCAN);
-//                    String result = CameraScan.parseScanResult(data);
-                    mAgentWeb.getJsAccessEntrace().quickCallJs("QRCode", scanResult);
-                    break;
-                case CAMERA_REQUEST_CODE:
-                    if (uploadMessageAboveL != null) {
-                        Uri[] results = new Uri[]{mCameraUri};
-                        uploadMessageAboveL.onReceiveValue(results);
-                        uploadMessageAboveL = null;
-//                        onActivityResultAboveL(requestCode, resultCode, data);
-                    } else if (uploadMessage != null) {
-                        uploadMessage.onReceiveValue(mCameraUri);
-                        uploadMessage = null;
-                    }
-//                    String uploadpath = Uri2PathUtil.getRealPathFromUri(this, mCameraUri);
-//                    mAgentWeb.getJsAccessEntrace().quickCallJs("Camera", uploadpath);
-                    break;
-            }
-        } else {
-            //这里uploadMessage跟uploadMessageAboveL在不同系统版本下分别持有了
-            //WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值
-            //否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效
-            if (uploadMessage != null) {
-                uploadMessage.onReceiveValue(null);
-                uploadMessage = null;
-            } else if (uploadMessageAboveL != null) {
-                uploadMessageAboveL.onReceiveValue(null);
-                uploadMessageAboveL = null;
-            }
-        }
-    }
-//
-//    //    // 3.选择图片后处理
 //    @Override
-//    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+//    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
 //        super.onActivityResult(requestCode, resultCode, data);
-//        if (requestCode == FILE_CHOOSER_RESULT_CODE) {
-//            if (null == uploadMessage && null == uploadMessageAboveL) return;
-//            Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
-//            // Uri result = (((data == null) || (resultCode != RESULT_OK)) ? null : data.getData());
-//            if (uploadMessageAboveL != null) {
-//                onActivityResultAboveL(requestCode, resultCode, data);
-//            } else if (uploadMessage != null) {
-//                uploadMessage.onReceiveValue(result);
-//                uploadMessage = null;
+//        /**
+//         * 处理二维码扫描结果
+//         */
+//        if (resultCode == RESULT_OK) {
+//            switch (requestCode) {
+//                case 200:
+//                    Bundle bundle = data.getExtras();
+//                    String scanResult = bundle.getString(Constant.INTENT_EXTRA_KEY_QR_SCAN);
+////                    String result = CameraScan.parseScanResult(data);
+//                    mAgentWeb.getJsAccessEntrace().quickCallJs("QRCode", scanResult);
+//                    break;
+//                case CAMERA_REQUEST_CODE:
+//                    if (uploadMessageAboveL != null) {
+//                        Uri[] results = new Uri[]{mCameraUri};
+//                        uploadMessageAboveL.onReceiveValue(results);
+//                        uploadMessageAboveL = null;
+////                        onActivityResultAboveL(requestCode, resultCode, data);
+//                    } else if (uploadMessage != null) {
+//                        uploadMessage.onReceiveValue(mCameraUri);
+//                        uploadMessage = null;
+//                    }
+////                    String uploadpath = Uri2PathUtil.getRealPathFromUri(this, mCameraUri);
+////                    mAgentWeb.getJsAccessEntrace().quickCallJs("Camera", uploadpath);
+//                    break;
 //            }
 //        } else {
 //            //这里uploadMessage跟uploadMessageAboveL在不同系统版本下分别持有了
@@ -287,6 +259,34 @@ public class WebViewActivity extends AppCompatActivity {
 //            }
 //        }
 //    }
+//
+    //    // 3.选择图片后处理
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == FILE_CHOOSER_RESULT_CODE) {
+            if (null == uploadMessage && null == uploadMessageAboveL) return;
+            Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
+            // Uri result = (((data == null) || (resultCode != RESULT_OK)) ? null : data.getData());
+            if (uploadMessageAboveL != null) {
+                onActivityResultAboveL(requestCode, resultCode, data);
+            } else if (uploadMessage != null) {
+                uploadMessage.onReceiveValue(result);
+                uploadMessage = null;
+            }
+        } else {
+            //这里uploadMessage跟uploadMessageAboveL在不同系统版本下分别持有了
+            //WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值
+            //否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效
+            if (uploadMessage != null) {
+                uploadMessage.onReceiveValue(null);
+                uploadMessage = null;
+            } else if (uploadMessageAboveL != null) {
+                uploadMessageAboveL.onReceiveValue(null);
+                uploadMessageAboveL = null;
+            }
+        }
+    }
 
     // 4. 选择内容回调到Html页面
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)

+ 6 - 2
app/src/main/res/layout/activity_main.xml

@@ -4,6 +4,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:background="@mipmap/icon_login_bg"
     tools:context=".activity.MainActivity">
 
     <EditText
@@ -11,7 +12,9 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_centerInParent="true"
-        android:text="http://192.168.31.46:8080/friday/fsmobile/" />
+        android:layout_margin="@dimen/dp_10"
+        android:text="http://debug.qingdaofushan.com/friday/fsmobile/#/main"
+        android:visibility="gone" />
 
     <TextView
         android:id="@+id/start"
@@ -20,5 +23,6 @@
         android:layout_below="@id/ed_text"
         android:layout_centerHorizontal="true"
         android:gravity="center"
-        android:text="开整" />
+        android:text="进入"
+        android:visibility="gone" />
 </RelativeLayout>

BIN
app/src/main/res/mipmap-xhdpi/icon_laoren_logo.png


BIN
app/src/main/res/mipmap-xhdpi/icon_login_bg.png



+ 2 - 1
settings.gradle

@@ -14,4 +14,5 @@ dependencyResolutionManagement {
     }
 }
 rootProject.name = "HomeCareSAS"
-include ':app'
+include ':app'
+include ':VideoCall'