Browse Source

引入 janus ok

allen 3 years ago
parent
commit
78fe2e298e
100 changed files with 3108 additions and 5370 deletions
  1. 0 5
      WebRTC/.gitignore
  2. 0 90
      WebRTC/build.gradle
  3. 0 25
      WebRTC/proguard-rules.pro
  4. 0 56
      WebRTC/src/main/AndroidManifest.xml
  5. 0 23
      WebRTC/src/main/java/com/wdkl/core/base/BaseActivity.java
  6. 0 38
      WebRTC/src/main/java/com/wdkl/core/consts/Urls.java
  7. 0 48
      WebRTC/src/main/java/com/wdkl/core/socket/IEvent.java
  8. 0 15
      WebRTC/src/main/java/com/wdkl/core/socket/IUserState.java
  9. 0 519
      WebRTC/src/main/java/com/wdkl/core/socket/MyWebSocket.java
  10. 0 395
      WebRTC/src/main/java/com/wdkl/core/socket/SocketManager.java
  11. 0 42
      WebRTC/src/main/java/com/wdkl/core/ui/user/UserBean.java
  12. 0 53
      WebRTC/src/main/java/com/wdkl/core/ui/user/UserListViewModel.java
  13. 0 131
      WebRTC/src/main/java/com/wdkl/core/util/ActivityStackManager.java
  14. 0 58
      WebRTC/src/main/java/com/wdkl/core/util/CrashHandler.java
  15. 0 25
      WebRTC/src/main/java/com/wdkl/core/util/StringUtil.java
  16. 0 52
      WebRTC/src/main/java/com/wdkl/core/util/Utils.java
  17. 0 187
      WebRTC/src/main/java/com/wdkl/core/voip/AsyncPlayer.java
  18. 0 129
      WebRTC/src/main/java/com/wdkl/core/voip/CallForegroundNotification.java
  19. 0 198
      WebRTC/src/main/java/com/wdkl/core/voip/CallMultiActivity.java
  20. 0 394
      WebRTC/src/main/java/com/wdkl/core/voip/CallSingleActivity.java
  21. 0 118
      WebRTC/src/main/java/com/wdkl/core/voip/FragmentMeeting.java
  22. 0 73
      WebRTC/src/main/java/com/wdkl/core/voip/NineGridView.java
  23. 0 153
      WebRTC/src/main/java/com/wdkl/core/voip/RomUtil.java
  24. 0 265
      WebRTC/src/main/java/com/wdkl/core/voip/SettingsCompat.java
  25. 0 7
      WebRTC/src/main/java/com/wdkl/core/voip/Utils.java
  26. 0 111
      WebRTC/src/main/java/com/wdkl/core/voip/VoipEvent.java
  27. 0 237
      WebRTC/src/main/java/com/wdkl/core/voip/VoipReceiver.java
  28. 0 37
      WebRTC/src/main/java/com/wdkl/net/HttpRequest.java
  29. 0 47
      WebRTC/src/main/java/com/wdkl/net/HttpRequestPresenter.java
  30. 0 12
      WebRTC/src/main/java/com/wdkl/net/ICallback.java
  31. 0 54
      WebRTC/src/main/java/com/wdkl/net/urlconn/UrlConnRequest.java
  32. 0 263
      WebRTC/src/main/java/com/wdkl/net/urlconn/UrlConnUtils.java
  33. 0 18
      WebRTC/src/main/java/com/wdkl/permission/Consumer.java
  34. 0 144
      WebRTC/src/main/java/com/wdkl/permission/Permissions.java
  35. 0 20
      WebRTC/src/main/res/drawable-xhdpi/bg_btn_white.xml
  36. 0 52
      WebRTC/src/main/res/layout/activity_launcher.xml
  37. 0 29
      WebRTC/src/main/res/layout/activity_main.xml
  38. 0 112
      WebRTC/src/main/res/layout/av_p2p_meeting_action.xml
  39. 0 39
      WebRTC/src/main/res/layout/av_voip_float_view.xml
  40. 0 28
      WebRTC/src/main/res/layout/fragment_home.xml
  41. 0 12
      WebRTC/src/main/res/layout/fragment_meeting.xml
  42. 0 27
      WebRTC/src/main/res/layout/fragment_room.xml
  43. 0 25
      WebRTC/src/main/res/layout/fragment_setting.xml
  44. 0 40
      WebRTC/src/main/res/layout/item_rooms.xml
  45. 0 48
      WebRTC/src/main/res/layout/item_users.xml
  46. 0 19
      WebRTC/src/main/res/menu/bottom_nav_menu.xml
  47. 0 12
      WebRTC/src/main/res/menu/menu_room.xml
  48. BIN
      WebRTC/src/main/res/mipmap-hdpi/ic_launcher.png
  49. BIN
      WebRTC/src/main/res/mipmap-mdpi/ic_launcher.png
  50. BIN
      WebRTC/src/main/res/mipmap-xhdpi/ic_launcher.png
  51. BIN
      WebRTC/src/main/res/mipmap-xxhdpi/ic_launcher.png
  52. BIN
      WebRTC/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  53. BIN
      WebRTC/src/main/res/raw/incoming_call_ring.mp3
  54. BIN
      WebRTC/src/main/res/raw/outgoing_call_ring.mp3
  55. BIN
      WebRTC/src/main/res/raw/wr_ringback.wav
  56. 0 9
      WebRTC/src/main/res/values/colors.xml
  57. 0 6
      WebRTC/src/main/res/values/dimens.xml
  58. 0 15
      WebRTC/src/main/res/values/strings.xml
  59. 0 23
      WebRTC/src/main/res/values/styles.xml
  60. 2 2
      build.gradle
  61. 1 1
      common/build.gradle
  62. 0 7
      home/build.gradle
  63. 6 38
      home/src/main/code/com/wdkl/ncs/android/component/home/activity/WatchHome2Activity.kt
  64. 0 1
      home/src/main/code/com/wdkl/ncs/android/component/home/adapter/TakeoverItemAdapter.kt
  65. 2 9
      home/src/main/code/com/wdkl/ncs/android/component/home/service/WdKeepAliveService.kt
  66. 1 16
      home/src/main/code/com/wdkl/ncs/android/component/home/util/HandleTcpConnect.kt
  67. 0 1
      home/src/main/code/com/wdkl/ncs/android/component/home/util/NetWorkChangeReceiver.kt
  68. 1 0
      janus/.gitignore
  69. 48 0
      janus/build.gradle
  70. 1 1
      libwebrtc/proguard-rules.pro
  71. 26 0
      janus/src/androidTest/java/com/wdkl/rtc/ExampleInstrumentedTest.java
  72. 37 0
      janus/src/main/AndroidManifest.xml
  73. 92 0
      janus/src/main/java/com/wdkl/rtc/MainActivity.java
  74. 1 1
      WebRTC/src/main/java/com/wdkl/core/ui/event/MsgEvent.java
  75. 54 0
      janus/src/main/java/com/wdkl/rtc/entity/Publisher.java
  76. 68 0
      janus/src/main/java/com/wdkl/rtc/entity/Room.java
  77. 820 0
      janus/src/main/java/com/wdkl/rtc/janus/JanusClient.java
  78. 33 0
      janus/src/main/java/com/wdkl/rtc/janus/JanusMessageType.java
  79. 19 0
      janus/src/main/java/com/wdkl/rtc/janus/PluginHandle.java
  80. 47 0
      janus/src/main/java/com/wdkl/rtc/janus/Transaction.java
  81. 358 0
      janus/src/main/java/com/wdkl/rtc/janus/VideoRoomCallback.java
  82. 110 0
      janus/src/main/java/com/wdkl/rtc/janus/WebSocketChannel.java
  83. 1 5
      rtc-chat/src/main/java/com/wdkl/skywebrtc/render/ProxyVideoSink.java
  84. 1 1
      rtc-chat/src/main/java/com/wdkl/skywebrtc/render/VideoFileRenderer.java
  85. 1 1
      rtc-chat/src/main/java/com/wdkl/skywebrtc/engine/AudioFocusManager.java
  86. 188 0
      janus/src/main/java/com/wdkl/rtc/rtc/Peer.java
  87. 497 521
      rtc-chat/src/main/java/com/wdkl/skywebrtc/engine/webrtc/WebRTCEngine.java
  88. 71 0
      janus/src/main/java/com/wdkl/rtc/rtc/observer/AnswerSdpObserver.java
  89. 9 0
      janus/src/main/java/com/wdkl/rtc/rtc/observer/CreateAnswerCallback.java
  90. 9 0
      janus/src/main/java/com/wdkl/rtc/rtc/observer/CreateOfferCallback.java
  91. 20 0
      janus/src/main/java/com/wdkl/rtc/rtc/observer/CreatePeerConnectionCallback.java
  92. 128 0
      janus/src/main/java/com/wdkl/rtc/rtc/observer/CustomPCObserver.java
  93. 78 0
      janus/src/main/java/com/wdkl/rtc/rtc/observer/OfferSdpObserver.java
  94. 222 0
      janus/src/main/java/com/wdkl/rtc/ui/CallSingleActivity.java
  95. 39 50
      WebRTC/src/main/java/com/wdkl/core/voip/FragmentAudio.java
  96. 46 95
      WebRTC/src/main/java/com/wdkl/core/voip/FragmentVideo.java
  97. 55 77
      WebRTC/src/main/java/com/wdkl/core/voip/SingleCallFragment.java
  98. 15 0
      janus/src/main/java/com/wdkl/rtc/util/Constant.java
  99. 1 5
      rtc-chat/src/main/java/com/wdkl/skywebrtc/EnumType.java
  100. 0 0
      WebRTC/src/main/java/com/wdkl/core/util/OSUtils.java

+ 0 - 5
WebRTC/.gitignore

@@ -1,5 +0,0 @@
-/build
-*.iml
-.DS_Store
-/.idea
-/gradle

+ 0 - 90
WebRTC/build.gradle

@@ -1,90 +0,0 @@
-apply plugin: 'com.android.library'
-
-android {
-    compileSdkVersion target_sdk_version
-    buildToolsVersion build_tools_version
-
-    defaultConfig {
-        minSdkVersion min_sdk_version
-        targetSdkVersion target_sdk_version
-        versionCode app_version_code
-        versionName app_version
-
-        compileOptions {
-            sourceCompatibility JavaVersion.VERSION_1_8
-            targetCompatibility JavaVersion.VERSION_1_8
-        }
-        vectorDrawables.useSupportLibrary = true
-
-        //ndk {
-            // 设置支持的SO库架构
-        //    abiFilters 'armeabi-v7a', 'x86'//, 'arm64-v8a'
-        //}
-    }
-
-    buildTypes {
-        release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
-        }
-
-        debug {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-
-}
-
-dependencies {
-    implementation fileTree(include: ['*.jar'], dir: 'libs')
-
-    //implementation 'androidx.appcompat:appcompat:1.2.0'
-    //implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
-    //implementation 'androidx.legacy:legacy-support-v4:1.0.0'
-    //implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
-    // navigation
-    //implementation 'androidx.navigation:navigation-fragment:2.3.0'
-    //implementation 'androidx.navigation:navigation-ui:2.3.0'
-
-    //implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
-
-    implementation 'com.google.android.material:material:1.1.0'
-    /**
-     *  Android基础依赖库
-     */
-    //noinspection GradleCompatible
-    implementation "com.android.support:design:$support_library_version"
-    implementation "com.android.support:support-v4:$support_library_version"
-    implementation "com.android.support:cardview-v7:$support_library_version"
-    implementation "com.android.support:appcompat-v7:$support_library_version"
-
-    implementation "com.android.support.constraint:constraint-layout:1.1.0-beta5"
-    implementation "com.android.support:support-vector-drawable:$support_library_version"
-    implementation "android.arch.lifecycle:extensions:1.0.0-alpha4"
-
-    // 内存泄漏检测
-    debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.1'
-
-    implementation project(path: ':rtc-chat')
-    // java
-    implementation 'org.java-websocket:Java-WebSocket:1.4.0'
-
-    compile 'com.alibaba:fastjson:1.2.23'
-    //强大的弹窗库
-    implementation 'com.lxj:xpopup:2.2.0'
-    //eventbus
-    //compile 'org.greenrobot:eventbus:3.1.1'
-
-    compile 'com.blankj:utilcodex:1.30.5'
-
-    compile project(':middleware')
-
-    //通知提示弹出库
-    api 'com.tapadoo.android:alerter:6.2.1'
-    implementation group: 'org.webrtc', name: 'google-webrtc', version: '1.0.32006'
-}

+ 0 - 25
WebRTC/proguard-rules.pro

@@ -1,25 +0,0 @@
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in /Users/dongxiangjun/Library/Android/sdk/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the proguardFiles
-# directive in build.gradle.
-#
-# For more details, see
-#   http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# 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

+ 0 - 56
WebRTC/src/main/AndroidManifest.xml

@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    package="com.wdkl.webrtc">
-    <!-- 设置视频直播权限 -->
-    <uses-feature android:name="android.hardware.camera" />
-    <uses-feature android:name="android.hardware.camera.autofocus" />
-    <uses-feature
-        android:glEsVersion="0x00020000"
-        android:required="true" />
-
-    <uses-permission android:name="android.permission.CAMERA" />
-    <uses-permission android:name="android.permission.RECORD_AUDIO" />
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 悬浮窗显示 -->
-    <uses-permission android:name="android.permission.VIBRATE" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
-
-    <application
-        android:allowBackup="true"
-        android:supportsRtl="true">
-
-        <!-- ======================java====================== -->
-        <activity
-            android:name="com.wdkl.core.voip.CallSingleActivity"
-            android:screenOrientation="landscape"
-            android:showOnLockScreen="true"
-            android:showWhenLocked="true"
-            android:theme="@style/AppTheme.NoActionBar"
-            tools:ignore="UnusedAttribute">
-            <intent-filter>
-                <action android:name="${applicationId}.kit.voip.single" />
-
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
-        <activity
-            android:name="com.wdkl.core.voip.CallMultiActivity"
-            android:screenOrientation="landscape"
-            android:showOnLockScreen="true"
-            android:theme="@style/AppTheme.NoActionBar" />
-
-        <receiver android:name="com.wdkl.core.voip.VoipReceiver">
-            <intent-filter>
-                <action android:name="${applicationId}.voip.Receiver" />
-            </intent-filter>
-        </receiver>
-    </application>
-
-</manifest>

+ 0 - 23
WebRTC/src/main/java/com/wdkl/core/base/BaseActivity.java

@@ -1,23 +0,0 @@
-package com.wdkl.core.base;
-
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-
-
-import com.wdkl.core.util.ActivityStackManager;
-
-public class BaseActivity extends AppCompatActivity {
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        // 添加Activity到堆栈
-        ActivityStackManager.getInstance().onCreated(this);
-        super.onCreate(savedInstanceState);
-    }
-
-    @Override
-    protected void onDestroy() {
-        ActivityStackManager.getInstance().onDestroyed(this);
-        super.onDestroy();
-    }
-}

+ 0 - 38
WebRTC/src/main/java/com/wdkl/core/consts/Urls.java

@@ -1,38 +0,0 @@
-package com.wdkl.core.consts;
-
-import com.wdkl.ncs.android.middleware.config.WdklNcsConfigCenter;
-
-/**
- * Created by dds on 2020/4/19.
- * ddssingsong@163.com
- */
-public class Urls {
-
-    public static String IP = "8.129.220.143:5000";
-    //public final static String IP = "120.76.246.253:5000";
-    static {
-        if (WdklNcsConfigCenter.getINSTANCE().getAPP_DEV()){
-            IP = "8.129.220.143:5000";
-        } else {
-            IP = "120.76.246.253:5000";
-        }
-    }
-
-    private final static String HOST = "http://" + IP + "/";
-
-    // 信令地址
-    public final static String WS = "ws://" + IP + "/ws";
-
-    //用户名称
-    public static String USER_ID;
-
-    // 获取用户列表
-    public static String getUserList() {
-        return HOST + "userList";
-    }
-
-    // 获取房间列表
-    public static String getRoomList() {
-        return HOST + "roomList";
-    }
-}

+ 0 - 48
WebRTC/src/main/java/com/wdkl/core/socket/IEvent.java

@@ -1,48 +0,0 @@
-package com.wdkl.core.socket;
-
-/**
- * Created by dds on 2019/7/26.
- * ddssingsong@163.com
- */
-public interface IEvent {
-
-
-    void onOpen();
-
-    void loginSuccess(String userId, String avatar);
-
-
-    void onInvite(String room, boolean audioOnly, String inviteId, String userList);
-
-
-    void onCancel(String inviteId);
-
-    void onRing(String userId);
-
-
-    void onPeers(String myId, String userList, int roomSize);
-
-    void onNewPeer(String myId);
-
-    void onReject(String userId, int type,String room);
-
-    // onOffer
-    void onOffer(String userId, String sdp);
-
-    // onAnswer
-    void onAnswer(String userId, String sdp);
-
-    // ice-candidate
-    void onIceCandidate(String userId, String id, int label, String candidate);
-
-    void onLeave(String room, String userId);
-
-    void logout(String str);
-
-    void onTransAudio(String userId);
-
-    void onDisConnect(String userId);
-
-    void reConnect();
-
-}

+ 0 - 15
WebRTC/src/main/java/com/wdkl/core/socket/IUserState.java

@@ -1,15 +0,0 @@
-package com.wdkl.core.socket;
-
-/**
- * Created by dds on 2019/8/2.
- * android_shuai@163.com
- */
-public interface IUserState {
-
-
-    void userLogin();
-
-    void userLogout();
-
-
-}

+ 0 - 519
WebRTC/src/main/java/com/wdkl/core/socket/MyWebSocket.java

@@ -1,519 +0,0 @@
-package com.wdkl.core.socket;
-
-import android.annotation.SuppressLint;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.wdkl.core.util.StringUtil;
-import com.wdkl.ncs.android.lib.utils.AppTool;
-
-import org.java_websocket.client.WebSocketClient;
-import org.java_websocket.handshake.ServerHandshake;
-
-import java.net.URI;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.net.ssl.X509TrustManager;
-
-/**
- * Created by dds on 2019/7/26.
- * android_shuai@163.com
- */
-public class MyWebSocket extends WebSocketClient {
-    private final static String TAG = "dds_WebSocket";
-    private final IEvent iEvent;
-    private boolean connectFlag = false;
-
-
-
-    public MyWebSocket(URI serverUri, IEvent event) {
-        super(serverUri);
-        this.iEvent = event;
-    }
-
-    @Override
-    public void onClose(int code, String reason, boolean remote) {
-        Log.e("dds_error", "onClose:" + reason + "remote:" + remote);
-        if (connectFlag) {
-            new Thread(new Runnable() {
-                @Override
-                public void run() {
-                    try{
-                        Thread.sleep(1000);
-                    }catch (Exception ignored){
-                    }
-                    reconnect();
-                }
-            }).start();
-        } else {
-            this.iEvent.logout("onClose");
-        }
-
-    }
-
-    @Override
-    public void onError(Exception ex) {
-        Log.e("dds_error", "onError:" + ex.toString());
-        this.iEvent.logout("onError");
-        connectFlag = false;
-    }
-
-    @Override
-    public void onOpen(ServerHandshake handshakedata) {
-        Log.e("dds_info", "onOpen");
-        this.iEvent.onOpen();
-        connectFlag = true;
-    }
-
-    @Override
-    public void onMessage(String message) {
-        Log.d(TAG, message);
-        handleMessage(message);
-    }
-
-    public void setConnectFlag(boolean flag) {
-        connectFlag = flag;
-    }
-
-    public boolean isConnectFlag() {
-        return connectFlag;
-    }
-
-    // ---------------------------------------处理接收消息-------------------------------------
-
-    private void handleMessage(String message) {
-        Log.i(TAG," ws msg : " + message);
-        Map map = JSON.parseObject(message, Map.class);
-        String eventName = (String) map.get("eventName");
-        if (eventName == null) return;
-        // 登录成功
-        if (eventName.equals("__login_success")) {
-            handleLogin(map);
-            return;
-        }
-        // 被邀请
-        if (eventName.equals("__invite")) {
-            handleInvite(map);
-            return;
-        }
-        // 取消拨出
-        if (eventName.equals("__cancel")) {
-            handleCancel(map);
-            return;
-        }
-        // 响铃
-        if (eventName.equals("__ring")) {
-            handleRing(map);
-            return;
-        }
-        // 进入房间
-        if (eventName.equals("__peers")) {
-            handlePeers(map);
-            return;
-        }
-        // 新人入房间
-        if (eventName.equals("__new_peer")) {
-            handleNewPeer(map);
-            return;
-        }
-        // 拒绝接听
-        if (eventName.equals("__reject")) {
-            handleReject(map);
-            return;
-        }
-        // offer
-        if (eventName.equals("__offer")) {
-            handleOffer(map);
-            return;
-        }
-        // answer
-        if (eventName.equals("__answer")) {
-            handleAnswer(map);
-            return;
-        }
-        // ice-candidate
-        if (eventName.equals("__ice_candidate")) {
-            handleIceCandidate(map);
-        }
-        // 离开房间
-        if (eventName.equals("__leave")) {
-            handleLeave(map);
-        }
-        // 切换到语音
-        if (eventName.equals("__audio")) {
-            handleTransAudio(map);
-        }
-        // 意外断开
-        if (eventName.equals("__disconnect")) {
-            handleDisConnect(map);
-        }
-    }
-
-    private void handleDisConnect(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String fromId = (String) data.get("fromID");
-            this.iEvent.onDisConnect(fromId);
-        }
-    }
-
-    private void handleTransAudio(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String fromId = (String) data.get("fromID");
-            this.iEvent.onTransAudio(fromId);
-        }
-    }
-
-    private void handleLogin(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String userID = (String) data.get("userID");
-            String avatar = (String) data.get("avatar");
-            this.iEvent.loginSuccess(userID, avatar);
-        }
-
-
-    }
-
-    private void handleIceCandidate(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String userID = (String) data.get("fromID");
-            String id = (String) data.get("id");
-            int label = (int) data.get("label");
-            String candidate = (String) data.get("candidate");
-            this.iEvent.onIceCandidate(userID, id, label, candidate);
-        }
-    }
-
-    private void handleAnswer(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String sdp = (String) data.get("sdp");
-            String userID = (String) data.get("fromID");
-            this.iEvent.onAnswer(userID, sdp);
-        }
-    }
-
-    private void handleOffer(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String sdp = (String) data.get("sdp");
-            String userID = (String) data.get("fromID");
-            this.iEvent.onOffer(userID, sdp);
-        }
-    }
-
-    private void handleReject(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String fromID = (String) data.get("fromID");
-            int rejectType = Integer.parseInt(String.valueOf(data.get("refuseType")));
-            String room = (String) data.get("room");
-            this.iEvent.onReject(fromID, rejectType,room);
-        }
-    }
-
-    private void handlePeers(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String you = (String) data.get("you");
-            String connections = (String) data.get("connections");
-            int roomSize = (int) data.get("roomSize");
-            this.iEvent.onPeers(you, connections, roomSize);
-        }
-    }
-
-    private void handleNewPeer(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String userID = (String) data.get("userID");
-            this.iEvent.onNewPeer(userID);
-        }
-    }
-
-    private void handleRing(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String fromId = (String) data.get("fromID");
-            this.iEvent.onRing(fromId);
-        }
-    }
-
-    private void handleCancel(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String inviteID = (String) data.get("inviteID");
-            String userList = (String) data.get("userList");
-            this.iEvent.onCancel(inviteID);
-        }
-    }
-
-    private void handleInvite(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String room = (String) data.get("room");
-            boolean audioOnly = (boolean) data.get("audioOnly");
-            String inviteID = (String) data.get("inviteID");
-            String userList = (String) data.get("userList");
-            this.iEvent.onInvite(room, audioOnly, inviteID, userList);
-        }
-    }
-
-    private void handleLeave(Map map) {
-        Map data = (Map) map.get("data");
-        if (data != null) {
-            String room = (String) data.get("room");
-            String fromID = (String) data.get("fromID");
-            this.iEvent.onLeave(room, fromID);
-        }
-    }
-
-    /**
-     * ------------------------------发送消息----------------------------------------
-     * 返回得到__peer
-     */
-    public void createRoom(String room, int roomSize, String myId) {
-        Map<String, Object> map = new HashMap<>();
-        map.put("eventName", "__create");
-
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("room", room);
-        childMap.put("roomSize", roomSize);
-        childMap.put("userID", myId);
-
-        map.put("data", childMap);
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        send(jsonString);
-    }
-
-    // 发送邀请
-    public void sendInvite(String room, String myId, List<String> users, boolean audioOnly) {
-        Map<String, Object> map = new HashMap<>();
-        map.put("eventName", "__invite");
-
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("room", room);
-        childMap.put("audioOnly", audioOnly);
-        childMap.put("inviteID", myId);
-
-        String join = StringUtil.listToString(users);
-        childMap.put("userList", join);
-
-        map.put("data", childMap);
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        if (!isOpen()) {
-            reconnect();
-        }
-        send(jsonString);
-    }
-
-    // 取消邀请
-    public void sendCancel(String mRoomId, String useId, List<String> users) {
-        Map<String, Object> map = new HashMap<>();
-        map.put("eventName", "__cancel");
-
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("inviteID", useId);
-        childMap.put("room", mRoomId);
-
-        String join = StringUtil.listToString(users);
-        childMap.put("userList", join);
-
-
-        map.put("data", childMap);
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        send(jsonString);
-    }
-
-    // 发送响铃通知
-    public void sendRing(String myId, String toId, String room) {
-        Map<String, Object> map = new HashMap<>();
-        map.put("eventName", "__ring");
-
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("fromID", myId);
-        childMap.put("toID", toId);
-        childMap.put("room", room);
-
-
-        map.put("data", childMap);
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        send(jsonString);
-    }
-
-    //加入房间
-    public void sendJoin(String room, String myId) {
-        Map<String, Object> map = new HashMap<>();
-        map.put("eventName", "__join");
-
-        Map<String, String> childMap = new HashMap<>();
-        childMap.put("room", room);
-        childMap.put("userID", myId);
-
-
-        map.put("data", childMap);
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        if (!isOpen()) {
-            reconnect();
-        }
-        send(jsonString);
-    }
-
-    // 拒接接听
-    public void sendRefuse(String room, String inviteID, String myId, int refuseType) {
-        Map<String, Object> map = new HashMap<>();
-        map.put("eventName", "__reject");
-
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("room", room);
-        childMap.put("toID", inviteID);
-        childMap.put("fromID", myId);
-        childMap.put("refuseType", String.valueOf(refuseType));
-
-        map.put("data", childMap);
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        send(jsonString);
-    }
-
-    // 离开房间
-    public void sendLeave(String myId, String room, String userId) {
-        Map<String, Object> map = new HashMap<>();
-        map.put("eventName", "__leave");
-
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("room", room);
-        childMap.put("fromID", myId);
-        childMap.put("userID", userId);
-
-        map.put("data", childMap);
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        if (isOpen()) {
-            send(jsonString);
-        }
-    }
-
-    // send offer
-    public void sendOffer(String myId, String userId, String sdp) {
-        Map<String, Object> map = new HashMap<>();
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("sdp", sdp);
-        childMap.put("userID", userId);
-        childMap.put("fromID", myId);
-        map.put("data", childMap);
-        map.put("eventName", "__offer");
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        send(jsonString);
-    }
-
-    // send answer
-    public void sendAnswer(String myId, String userId, String sdp) {
-        Map<String, Object> map = new HashMap<>();
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("sdp", sdp);
-        childMap.put("fromID", myId);
-        childMap.put("userID", userId);
-        map.put("data", childMap);
-        map.put("eventName", "__answer");
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        send(jsonString);
-    }
-
-    // send ice-candidate
-    public void sendIceCandidate(String myId, String userId, String id, int label, String candidate) {
-        Map<String, Object> map = new HashMap<>();
-        map.put("eventName", "__ice_candidate");
-
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("userID", userId);
-        childMap.put("fromID", myId);
-        childMap.put("id", id);
-        childMap.put("label", label);
-        childMap.put("candidate", candidate);
-
-        map.put("data", childMap);
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        if (isOpen()) {
-            send(jsonString);
-        }
-    }
-
-    // 切换到语音
-    public void sendTransAudio(String myId, String userId) {
-        Map<String, Object> map = new HashMap<>();
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("fromID", myId);
-        childMap.put("userID", userId);
-        map.put("data", childMap);
-        map.put("eventName", "__audio");
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        send(jsonString);
-    }
-
-    // 断开重连
-    public void sendDisconnect(String room, String myId, String userId) {
-        Map<String, Object> map = new HashMap<>();
-        Map<String, Object> childMap = new HashMap<>();
-        childMap.put("fromID", myId);
-        childMap.put("userID", userId);
-        childMap.put("room", room);
-        map.put("data", childMap);
-        map.put("eventName", "__disconnect");
-        JSONObject object = new JSONObject(map);
-        final String jsonString = object.toString();
-        Log.d(TAG, "send-->" + jsonString);
-        send(jsonString);
-    }
-
-    // 忽略证书
-    public static class TrustManagerTest implements X509TrustManager {
-
-        @SuppressLint("TrustAllX509TrustManager")
-        @Override
-        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
-
-        }
-
-        @SuppressLint("TrustAllX509TrustManager")
-        @Override
-        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
-
-        }
-
-        @Override
-        public X509Certificate[] getAcceptedIssuers() {
-            return new X509Certificate[0];
-        }
-    }
-
-}

+ 0 - 395
WebRTC/src/main/java/com/wdkl/core/socket/SocketManager.java

@@ -1,395 +0,0 @@
-package com.wdkl.core.socket;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-
-import com.wdkl.core.voip.Utils;
-import com.wdkl.core.voip.VoipReceiver;
-import com.wdkl.skywebrtc.CallSession;
-import com.wdkl.skywebrtc.EnumType;
-import com.wdkl.skywebrtc.SkyEngineKit;
-
-import org.greenrobot.eventbus.EventBus;
-
-import java.lang.ref.WeakReference;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.SecureRandom;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-
-
-/**
- * Created by dds on 2019/7/26.
- * ddssignsong@163.com
- */
-public class SocketManager implements IEvent {
-    private final static String TAG = "dds_SocketManager";
-    private MyWebSocket webSocket;
-    private int userState;
-    private String myId;
-    private Context mContext;
-
-    private final Handler handler = new Handler(Looper.getMainLooper());
-
-    private SocketManager() {
-
-    }
-
-    public void init(Context context) {
-        mContext = context;
-    }
-
-    private static class Holder {
-        private static final SocketManager socketManager = new SocketManager();
-    }
-
-    public static SocketManager getInstance() {
-        return Holder.socketManager;
-    }
-
-    public boolean getConnectFlag() {
-        if (webSocket==null||!webSocket.isOpen())
-        {
-            return false;
-        }
-        return webSocket.isConnectFlag();
-    }
-
-    public void connect(String url, String userId, int device) {
-        if (webSocket == null || !webSocket.isOpen()) {
-            URI uri;
-            try {
-                String urls = url + "/" + userId + "/" + device;
-                uri = new URI(urls);
-            } catch (URISyntaxException e) {
-                e.printStackTrace();
-                return;
-            }
-            webSocket = new MyWebSocket(uri, this);
-            // 设置wss
-            if (url.startsWith("wss")) {
-                try {
-                    SSLContext sslContext = SSLContext.getInstance("TLS");
-                    if (sslContext != null) {
-                        sslContext.init(null, new TrustManager[]{new MyWebSocket.TrustManagerTest()}, new SecureRandom());
-                    }
-
-                    SSLSocketFactory factory = null;
-                    if (sslContext != null) {
-                        factory = sslContext.getSocketFactory();
-                    }
-
-                    if (factory != null) {
-                        webSocket.setSocket(factory.createSocket());
-                    }
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-            // 开始connect
-            webSocket.connect();
-        }
-
-
-    }
-
-    public void unConnect() {
-        if (webSocket != null) {
-            if (webSocket.isOpen()){
-                webSocket.close();
-            }
-            webSocket.setConnectFlag(false);
-            webSocket = null;
-        }
-
-    }
-
-    public Context getContext() {
-        return mContext;
-    }
-
-    @Override
-    public void onOpen() {
-        Log.i(TAG, "socket is open!");
-
-    }
-
-    @Override
-    public void loginSuccess(String userId, String avatar) {
-        Log.i(TAG, "loginSuccess:" + userId);
-        myId = userId;
-        userState = 1;
-        if (iUserState != null && iUserState.get() != null) {
-            iUserState.get().userLogin();
-        }
-    }
-
-
-    // ======================================================================================
-    public void createRoom(String room, int roomSize) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.createRoom(room, roomSize, myId);
-        }
-
-    }
-
-    public void sendInvite(String room, List<String> users, boolean audioOnly) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendInvite(room, myId, users, audioOnly);
-        }
-    }
-
-    public void sendLeave(String room, String userId) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendLeave(myId, room, userId);
-        }
-
-        //EventBus.getDefault().post(new MessageEvent("handoff", EVENT_CALL_STATE));
-    }
-
-    public void sendRingBack(String targetId, String room) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendRing(myId, targetId, room);
-        }
-    }
-
-    public void sendRefuse(String room, String inviteId, int refuseType) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendRefuse(room, inviteId, myId, refuseType);
-        }
-
-        //EventBus.getDefault().post(new MessageEvent("reject", EVENT_CALL_STATE));
-    }
-
-    public void sendCancel(String mRoomId, List<String> userIds) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendCancel(mRoomId, myId, userIds);
-        }
-
-        //EventBus.getDefault().post(new MessageEvent("cancel", EVENT_CALL_STATE));
-    }
-
-    public void sendJoin(String room) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendJoin(room, myId);
-        }
-
-        //EventBus.getDefault().post(new MessageEvent("accept", EVENT_CALL_STATE));
-    }
-
-    public void sendMeetingInvite(String userList) {
-
-    }
-
-    public void sendOffer(String userId, String sdp) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendOffer(myId, userId, sdp);
-        }
-    }
-
-    public void sendAnswer(String userId, String sdp) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendAnswer(myId, userId, sdp);
-        }
-    }
-
-    public void sendIceCandidate(String userId, String id, int label, String candidate) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendIceCandidate(myId, userId, id, label, candidate);
-        }
-    }
-
-    public void sendTransAudio(String userId) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendTransAudio(myId, userId);
-        }
-    }
-
-    public void sendDisconnect(String room, String userId) {
-        if (webSocket != null && webSocket.isOpen()) {
-            webSocket.sendDisconnect(room, myId, userId);
-        }
-    }
-
-
-    // ========================================================================================
-    @Override
-    public void onInvite(String room, boolean audioOnly, String inviteId, String userList) {
-        //todo: 待处理
-        Intent intent = new Intent();
-        intent.putExtra("room", room);
-        intent.putExtra("audioOnly", audioOnly);
-        intent.putExtra("inviteId", inviteId);
-        intent.putExtra("userList", userList);
-        intent.setAction(Utils.ACTION_VOIP_RECEIVER);
-        intent.setComponent(new ComponentName(mContext.getPackageName(), VoipReceiver.class.getName()));
-        // 发送广播
-        mContext.sendBroadcast(intent);
-
-    }
-
-    @Override
-    public void onCancel(String inviteId) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.onCancel(inviteId);
-            }
-        });
-
-    }
-
-    @Override
-    public void onRing(String fromId) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.onRingBack(fromId);
-            }
-        });
-
-
-    }
-
-    @Override  // 加入房间
-    public void onPeers(String myId, String connections, int roomSize) {
-        handler.post(() -> {
-            //自己进入了房间,然后开始发送offer
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.onJoinHome(myId, connections, roomSize);
-            }
-        });
-
-    }
-
-    @Override
-    public void onNewPeer(String userId) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.newPeer(userId);
-            }
-        });
-
-    }
-
-    @Override
-    public void onReject(String userId, int type,String room) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            Log.i(TAG,"current RoomId:"+currentSession.getRoomId()+",reject:"+room);
-            if (currentSession != null) {
-                if(currentSession.getRoomId().equals(room)&&myId.equals(userId)) {
-                    currentSession.onRefuse(userId, type);
-                }
-            }
-        });
-
-    }
-
-    @Override
-    public void onOffer(String userId, String sdp) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.onReceiveOffer(userId, sdp);
-            }
-        });
-
-
-    }
-
-    @Override
-    public void onAnswer(String userId, String sdp) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.onReceiverAnswer(userId, sdp);
-            }
-        });
-
-    }
-
-    @Override
-    public void onIceCandidate(String userId, String id, int label, String candidate) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.onRemoteIceCandidate(userId, id, label, candidate);
-            }
-        });
-
-    }
-
-    @Override
-    public void onLeave(String room, String userId) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null && currentSession.getRoomId().equals(room)) {
-                currentSession.onLeave(userId);
-            }
-        });
-    }
-
-    @Override
-    public void logout(String str) {
-        Log.i(TAG, "logout:" + str);
-        userState = 0;
-        if (iUserState != null && iUserState.get() != null) {
-            iUserState.get().userLogout();
-        }
-    }
-
-    @Override
-    public void onTransAudio(String userId) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.onTransAudio(userId);
-            }
-        });
-    }
-
-    @Override
-    public void onDisConnect(String userId) {
-        handler.post(() -> {
-            CallSession currentSession = SkyEngineKit.Instance().getCurrentSession();
-            if (currentSession != null) {
-                currentSession.onDisConnect(userId, EnumType.CallEndReason.RemoteSignalError);
-            }
-        });
-    }
-
-    @Override
-    public void reConnect() {
-        Log.w(TAG,"重连RTC");
-        handler.post(() -> {
-            if (webSocket!=null) {
-                webSocket.reconnect();
-            }
-        });
-    }
-    //===========================================================================================
-
-
-    public int getUserState() {
-        return userState;
-    }
-
-    private WeakReference<IUserState> iUserState;
-
-    public void addUserStateCallback(IUserState userState) {
-        iUserState = new WeakReference<>(userState);
-    }
-
-}

+ 0 - 42
WebRTC/src/main/java/com/wdkl/core/ui/user/UserBean.java

@@ -1,42 +0,0 @@
-package com.wdkl.core.ui.user;
-
-import android.text.TextUtils;
-
-/**
- * Created by dds on 2020/4/13.
- * android_shuai@163.com
- */
-public class UserBean {
-    private String userId;
-    private String avatar;
-    private String nickName;
-
-    public String getUserId() {
-        return userId;
-    }
-
-    public void setUserId(String userId) {
-        this.userId = userId;
-    }
-
-    public String getAvatar() {
-        return avatar;
-    }
-
-    public void setAvatar(String avatar) {
-        this.avatar = avatar;
-    }
-
-    public String getNickName() {
-        if (TextUtils.isEmpty(nickName)) {
-            return userId;
-        }
-        return nickName;
-    }
-
-    public void setNickName(String nickName) {
-        this.nickName = nickName;
-    }
-
-
-}

+ 0 - 53
WebRTC/src/main/java/com/wdkl/core/ui/user/UserListViewModel.java

@@ -1,53 +0,0 @@
-package com.wdkl.core.ui.user;
-
-import android.util.Log;
-
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.ViewModel;
-
-import com.alibaba.fastjson.JSON;
-import com.wdkl.core.consts.Urls;
-import com.wdkl.net.HttpRequestPresenter;
-import com.wdkl.net.ICallback;
-
-import java.util.List;
-
-public class UserListViewModel extends ViewModel {
-
-    private MutableLiveData<List<UserBean>> mList;
-
-    public LiveData<List<UserBean>> getUserList() {
-        if (mList == null) {
-            mList = new MutableLiveData<>();
-            loadUsers();
-        }
-        return mList;
-    }
-
-
-    // 获取远程用户列表
-    public void loadUsers() {
-        Thread thread = new Thread(() -> {
-            String url = Urls.getUserList();
-            HttpRequestPresenter.getInstance()
-                    .get(url, null, new ICallback() {
-                        @Override
-                        public void onSuccess(String result) {
-                            Log.d("dds_test", result);
-                            List<UserBean> userBeans = JSON.parseArray(result, UserBean.class);
-                            mList.postValue(userBeans);
-                        }
-
-                        @Override
-                        public void onFailure(int code, Throwable t) {
-                            Log.d("dds_test", "code:" + code + ",msg:" + t.toString());
-                        }
-                    });
-        });
-        thread.start();
-
-
-    }
-
-}

+ 0 - 131
WebRTC/src/main/java/com/wdkl/core/util/ActivityStackManager.java

@@ -1,131 +0,0 @@
-package com.wdkl.core.util;
-
-import android.app.Activity;
-import android.app.Application;
-import android.util.Log;
-
-import androidx.collection.ArrayMap;
-
-/**
- * 应用程序Activity管理类,用于Activity管理和应用程序退出
- *
- * @author gong
- */
-public class ActivityStackManager {
-    private static final String TAG = "ActivityStackManager";
-    private static volatile ActivityStackManager sInstance;
-
-    private final ArrayMap<String, Activity> mActivitySet = new ArrayMap<>();
-
-    /**
-     * 当前 Activity 对象标记
-     */
-    private String mCurrentTag;
-
-    private ActivityStackManager() {
-    }
-
-    public static ActivityStackManager getInstance() {
-        // 加入双重校验锁
-        if (sInstance == null) {
-            synchronized (ActivityStackManager.class) {
-                if (sInstance == null) {
-                    sInstance = new ActivityStackManager();
-                }
-            }
-        }
-        return sInstance;
-    }
-
-    /**
-     * 获取 Application 对象
-     */
-    public Application getApplication() {
-        return getTopActivity().getApplication();
-    }
-
-    /**
-     * 获取栈顶的 Activity
-     */
-    public Activity getTopActivity() {
-        return mActivitySet.get(mCurrentTag);
-    }
-
-    /**
-     * 销毁所有的 Activity
-     */
-    public void finishAllActivities() {
-        finishAllActivities((Class<? extends Activity>) null);
-    }
-
-
-    /**
-     * 获取栈底部的Activity
-     */
-    public Activity getBottomActivity() {
-        Log.d(TAG, "getBottomActivity mActivitySet.size() = " + mActivitySet.size());
-        if (mActivitySet.size() > 0) {
-            return mActivitySet.get(mActivitySet.keyAt(0));
-        } else {
-            return getTopActivity();
-        }
-
-    }
-    /**
-     * 销毁所有的 Activity,除这些 Class 之外的 Activity
-     */
-    @SafeVarargs
-    public final void finishAllActivities(Class<? extends Activity>... classArray) {
-        String[] keys = mActivitySet.keySet().toArray(new String[]{});
-        for (String key : keys) {
-            Activity activity = mActivitySet.get(key);
-            if (activity != null && !activity.isFinishing()) {
-                boolean whiteClazz = false;
-                if (classArray != null) {
-                    for (Class<? extends Activity> clazz : classArray) {
-                        if (activity.getClass() == clazz) {
-                            whiteClazz = true;
-                        }
-                    }
-                }
-                // 如果不是白名单上面的 Activity 就销毁掉
-                if (!whiteClazz) {
-                    activity.finish();
-                    mActivitySet.remove(key);
-                }
-            }
-        }
-    }
-
-    /**
-     * Activity 同名方法回调
-     */
-    public void onCreated(Activity activity) {
-        mCurrentTag = getObjectTag(activity);
-        mActivitySet.put(getObjectTag(activity), activity);
-    }
-
-    /**
-     * Activity 同名方法回调
-     */
-    public void onDestroyed(Activity activity) {
-        mActivitySet.remove(getObjectTag(activity));
-        // 如果当前的 Activity 是最后一个的话
-        if (getObjectTag(activity).equals(mCurrentTag)) {
-            // 清除当前标记
-            mCurrentTag = null;
-        }
-        if (mActivitySet.size() != 0) {
-            mCurrentTag = mActivitySet.keyAt(mActivitySet.size() - 1);
-        }
-    }
-
-    /**
-     * 获取一个对象的独立无二的标记
-     */
-    private static String getObjectTag(Object object) {
-        // 对象所在的包名 + 对象的内存地址
-        return object.getClass().getName() + Integer.toHexString(object.hashCode());
-    }
-
-}

+ 0 - 58
WebRTC/src/main/java/com/wdkl/core/util/CrashHandler.java

@@ -1,58 +0,0 @@
-package com.wdkl.core.util;
-
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import com.wdkl.skywebrtc.CallSession;
-import com.wdkl.skywebrtc.SkyEngineKit;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.Writer;
-
-public class CrashHandler implements Thread.UncaughtExceptionHandler {
-    private static final String TAG = "MyUncaughtExceptionHand";
-
-    private Context appContext;
-
-    public CrashHandler(Context context) {
-        appContext = context;
-    }
-
-    @Override
-    public void uncaughtException(@NotNull Thread thread, @NotNull Throwable ex) {
-        SkyEngineKit gEngineKit = SkyEngineKit.Instance();
-        CallSession session = gEngineKit.getCurrentSession();
-
-        Log.d(TAG, "uncaughtException session = " + session);
-        if (session != null) {
-            gEngineKit.endCall();
-        } else {
-            //gEngineKit.sendDisconnected(App.getInstance().getRoomId(), App.getInstance().getOtherUserId(),true);
-        }
-        final Writer result = new StringWriter();
-        final PrintWriter printWriter = new PrintWriter(result);
-        //如果异常时在AsyncTask里面的后台线程抛出的
-        //那么实际的异常仍然可以通过getCause获得
-        Throwable cause = ex;
-        while (null != cause) {
-            cause.printStackTrace(printWriter);
-            cause = cause.getCause();
-        }
-        //stacktraceAsString就是获取的carsh堆栈信息
-        final String stacktraceAsString = result.toString();
-        printWriter.close();
-        restartApp();
-    }
-
-    private void restartApp() {
-        /*Intent i = new Intent(appContext, LauncherActivity.class);
-        i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
-        appContext.startActivity(i);*/
-    }
-
-
-}

+ 0 - 25
WebRTC/src/main/java/com/wdkl/core/util/StringUtil.java

@@ -1,25 +0,0 @@
-package com.wdkl.core.util;
-
-import java.util.List;
-
-/**
- * Created by dds on 2020/5/4.
- * ddssingsong@163.com
- */
-public class StringUtil {
-
-    public static String listToString(List<String> mList) {
-        final String SEPARATOR = ",";
-        StringBuilder sb = new StringBuilder();
-        String convertedListStr;
-        if (null != mList && mList.size() > 0) {
-            for (String item : mList) {
-                sb.append(item);
-                sb.append(SEPARATOR);
-            }
-            convertedListStr = sb.toString();
-            convertedListStr = convertedListStr.substring(0, convertedListStr.length() - SEPARATOR.length());
-            return convertedListStr;
-        } else return "";
-    }
-}

+ 0 - 52
WebRTC/src/main/java/com/wdkl/core/util/Utils.java

@@ -1,52 +0,0 @@
-package com.wdkl.core.util;
-
-import android.app.ActivityManager;
-import android.app.Application;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.os.Build;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-
-import java.util.List;
-
-public class Utils {
-    //设置界面全屏
-    public static void setFullScreenWindowLayout(Window window) {
-        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.
-                SYSTEM_UI_FLAG_LAYOUT_STABLE);
-        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            window.setStatusBarColor(Color.TRANSPARENT);
-        }
-        //设置页面全屏显示
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
-            WindowManager.LayoutParams layoutParams = window.getAttributes();
-            layoutParams.layoutInDisplayCutoutMode =
-                    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
-            window.setAttributes(layoutParams);
-        }
-    }
-
-    public static int getStatusBarHeight(Context context) {
-        Resources resources = context.getResources();
-        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
-        return resources.getDimensionPixelSize(resourceId);
-    }
-
-
-    public static boolean isAppRunningForeground(Context context) {
-        ActivityManager activityManager =
-                (ActivityManager) context.getSystemService(Application.ACTIVITY_SERVICE);
-        List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
-        for (ActivityManager.RunningAppProcessInfo appProcessInfo : runningAppProcesses) {
-            if (appProcessInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
-                if (appProcessInfo.processName.equals(context.getApplicationInfo().processName))
-                    return true;
-            }
-        }
-        return false;
-    }
-}

+ 0 - 187
WebRTC/src/main/java/com/wdkl/core/voip/AsyncPlayer.java

@@ -1,187 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.content.Context;
-import android.media.AudioDeviceInfo;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.net.Uri;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.util.Log;
-
-import java.io.IOException;
-import java.util.LinkedList;
-
-/**
- * 响铃相关类
- */
-public class AsyncPlayer {
-    private static final int PLAY = 1;
-    private static final int STOP = 2;
-    private AudioManager audioManager;
-
-    private static final class Command {
-        int code;
-        Context context;
-        int resId;
-        boolean looping;
-        int stream;
-        long requestTime;
-
-        public String toString() {
-            return "{ code=" + code + " looping=" + looping + " stream=" + stream + " resId=" + resId + " }";
-        }
-    }
-
-    private final LinkedList mCmdQueue = new LinkedList();
-
-    private void startSound(Command cmd) {
-
-        try {
-            //MediaPlayer player = new MediaPlayer();
-            MediaPlayer player = MediaPlayer.create(cmd.context, cmd.resId);
-            player.setAudioStreamType(cmd.stream);
-            //player.setDataSource(cmd.context, cmd.uri);
-            player.setLooping(cmd.looping);
-            player.setVolume(1.0f, 1.0f);
-            //player.prepare();
-            player.start();
-            if (mPlayer != null) {
-                mPlayer.release();
-            }
-            mPlayer = player;
-            Log.w(mTag, "start sound " + cmd.resId);
-        } catch (Exception e) {
-            Log.w(mTag, "error loading sound for " + cmd.resId, e);
-        }
-    }
-
-    private final class Thread extends java.lang.Thread {
-        Thread() {
-            super("AsyncPlayer-" + mTag);
-        }
-
-        public void run() {
-            while (true) {
-                Command cmd = null;
-
-                synchronized (mCmdQueue) {
-
-                    cmd = (Command) mCmdQueue.removeFirst();
-                }
-
-                switch (cmd.code) {
-                    case PLAY:
-                        startSound(cmd);
-                        break;
-                    case STOP:
-                        if (mPlayer != null) {
-                            mPlayer.stop();
-                            mPlayer.release();
-                            mPlayer = null;
-                        } else {
-                            Log.w(mTag, "STOP command without a player");
-                        }
-                        break;
-                }
-
-                synchronized (mCmdQueue) {
-                    if (mCmdQueue.size() == 0) {
-
-                        mThread = null;
-                        releaseWakeLock();
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    private String mTag;
-    private Thread mThread;
-    private MediaPlayer mPlayer;
-    private PowerManager.WakeLock mWakeLock;
-
-    private int mState = STOP;
-
-    public AsyncPlayer(String tag) {
-        if (tag != null) {
-            mTag = tag;
-        } else {
-            mTag = "AsyncPlayer";
-        }
-    }
-
-    public void play(Context context, int res, boolean looping, int stream) {
-        Command cmd = new Command();
-        cmd.requestTime = SystemClock.uptimeMillis();
-        cmd.code = PLAY;
-        cmd.context = context;
-        cmd.resId = res;
-        cmd.looping = looping;
-        cmd.stream = stream;
-        synchronized (mCmdQueue) {
-            enqueueLocked(cmd);
-            mState = PLAY;
-        }
-    }
-
-    public void stop() {
-        synchronized (mCmdQueue) {
-            if (mState != STOP) {
-                Command cmd = new Command();
-                cmd.requestTime = SystemClock.uptimeMillis();
-                cmd.code = STOP;
-                enqueueLocked(cmd);
-                mState = STOP;
-            }
-        }
-    }
-
-    private void enqueueLocked(Command cmd) {
-        mCmdQueue.add(cmd);
-        if (mThread == null) {
-            acquireWakeLock();
-            mThread = new Thread();
-            mThread.start();
-        }
-    }
-
-    public void setUsesWakeLock(Context context) {
-        if (mWakeLock != null || mThread != null) {
-            throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock + " mThread=" + mThread);
-        }
-        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
-    }
-
-    private void acquireWakeLock() {
-        if (mWakeLock != null) {
-            mWakeLock.acquire();
-        }
-    }
-
-    private void releaseWakeLock() {
-        if (mWakeLock != null) {
-            mWakeLock.release();
-        }
-    }
-
-    private boolean isHeadphonesPlugged(Context context) {
-        if (audioManager == null) {
-            audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        }
-        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
-            AudioDeviceInfo[] audioDevices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
-            for (AudioDeviceInfo deviceInfo : audioDevices) {
-                if (deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
-                        || deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
-                    return true;
-                }
-            }
-            return false;
-        } else {
-            return audioManager.isWiredHeadsetOn();
-        }
-    }
-}

+ 0 - 129
WebRTC/src/main/java/com/wdkl/core/voip/CallForegroundNotification.java

@@ -1,129 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.os.Build;
-import android.util.Log;
-
-import androidx.annotation.RequiresApi;
-import androidx.core.app.NotificationCompat;
-
-import com.wdkl.core.util.ActivityStackManager;
-import com.wdkl.webrtc.R;
-
-import java.util.Random;
-
-/**
- * <pre>
- *     author : Jasper
- *     e-mail : 229605030@qq.com
- *     time   : 2021/02/01
- *     desc   :
- * </pre>
- */
-public class CallForegroundNotification extends ContextWrapper {
-    private static final String TAG = "CallForegroundNotificat";
-    private static final String id = "channel1";
-    private static final String name = "voip";
-    private NotificationManager manager;
-
-    public CallForegroundNotification(Context base) {
-        super(base);
-        manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-    }
-
-    @RequiresApi(api = 26)
-    public void createNotificationChannel() {
-        NotificationChannel channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH);
-        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-        manager.createNotificationChannel(channel);
-    }
-
-    public void sendRequestIncomingPermissionsNotification(
-            Context context, String room, String userList, String inviteId, String inviteUserName, Boolean isAudioOnly
-    ) {
-        clearAllNotification();
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            createNotificationChannel();
-        }
-        //发送广播,调起接听界面
-        Intent intent = new Intent(context, ActivityStackManager.getInstance().getBottomActivity().getClass()); //栈底是MainActivity
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra("room", room);
-        intent.putExtra("isFromCall", true);
-        intent.putExtra("audioOnly", isAudioOnly);
-        intent.putExtra("inviteUserName", inviteUserName);
-        intent.putExtra("inviteId", inviteId);
-        intent.putExtra("userList", userList);
-        PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, new Random().nextInt(100), intent, PendingIntent.FLAG_UPDATE_CURRENT);
-        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, id)
-                .setSmallIcon(R.mipmap.ic_launcher)
-                .setContentTitle(getResources().getString(R.string.app_name))
-                .setTicker(
-                        "您收到" + inviteUserName + "的来电邀请,请允许"
-                                + (isAudioOnly ? "录音" :
-                                "录音和相机") + "权限来通话"
-                )
-                .setContentText("您收到" + inviteUserName + "的来电邀请,请允许"
-                        + (isAudioOnly ? "录音" :
-                        "录音和相机") + "权限来通话"
-                )
-                .setAutoCancel(true)
-                .setDefaults(Notification.DEFAULT_ALL)
-                .setPriority(NotificationCompat.PRIORITY_MAX)
-                .setCategory(Notification.CATEGORY_CALL);
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            notificationBuilder.setFullScreenIntent(fullScreenPendingIntent, true);
-        } else {
-            notificationBuilder.setContentIntent(fullScreenPendingIntent);
-        }
-//
-        manager.notify(10086, notificationBuilder.build());
-    }
-
-    public void sendIncomingCallNotification(
-            Context context, String targetId, Boolean isOutgoing, String inviteUserName,
-            Boolean isAudioOnly, Boolean isClearTop
-    ) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            clearAllNotification();
-            createNotificationChannel();
-            Notification notification = getChannelNotificationQ(context, targetId, isOutgoing, inviteUserName, isAudioOnly, isClearTop);
-            manager.notify(10086, notification);
-        }
-    }
-
-    private void clearAllNotification() {
-        manager.cancelAll();
-    }
-
-    private Notification getChannelNotificationQ(
-            Context context, String targetId, Boolean isOutgoing, String inviteUserName,
-            Boolean isAudioOnly, Boolean isClearTop
-    ) {
-        Intent fullScreenIntent = CallSingleActivity.getCallIntent(context, targetId, isOutgoing, inviteUserName, isAudioOnly, isClearTop);
-        fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, new Random().nextInt(100), fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, id)
-                .setSmallIcon(R.mipmap.ic_launcher)
-                .setContentTitle(getResources().getString(R.string.app_name))
-                .setTicker(inviteUserName + "来电")
-                .setContentText(inviteUserName + "来电")
-                .setAutoCancel(true)
-                .setDefaults(Notification.DEFAULT_ALL)
-                .setPriority(NotificationCompat.PRIORITY_MAX)
-                .setCategory(Notification.CATEGORY_CALL)
-                .setFullScreenIntent(fullScreenPendingIntent, true);
-
-        Log.d(TAG, "getChannelNotificationQ");
-        return notificationBuilder.build();
-    }
-
-
-}

+ 0 - 198
WebRTC/src/main/java/com/wdkl/core/voip/CallMultiActivity.java

@@ -1,198 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.Manifest;
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.ImageView;
-
-import com.wdkl.core.base.BaseActivity;
-import com.wdkl.permission.Permissions;
-import com.wdkl.skywebrtc.CallSession;
-import com.wdkl.skywebrtc.EnumType;
-import com.wdkl.skywebrtc.SkyEngineKit;
-import com.wdkl.skywebrtc.except.NotInitializedException;
-import com.wdkl.webrtc.R;
-
-import java.util.UUID;
-
-/**
- * Created by dds on 2018/7/26.
- * 多人通话界面
- */
-public class CallMultiActivity extends BaseActivity implements CallSession.CallSessionCallback, View.OnClickListener {
-    private SkyEngineKit gEngineKit;
-    private final Handler handler = new Handler(Looper.getMainLooper());
-    private ImageView meetingHangupImageView;
-    private CallSession.CallSessionCallback currentFragment;
-    public static final String EXTRA_MO = "isOutGoing";
-    private boolean isOutgoing;
-
-
-    public static void openActivity(Activity activity, String room, boolean isOutgoing) {
-        Intent intent = new Intent(activity, CallMultiActivity.class);
-        intent.putExtra("room", room);
-        intent.putExtra(EXTRA_MO, isOutgoing);
-        activity.startActivity(intent);
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
-                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
-                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
-                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
-        getWindow().getDecorView().setSystemUiVisibility(getSystemUiVisibility());
-        setContentView(R.layout.activity_multi_call);
-        initView();
-        initListener();
-        initData();
-    }
-
-
-    private void initView() {
-        meetingHangupImageView = findViewById(R.id.meetingHangupImageView);
-        Fragment fragment = new FragmentMeeting();
-        FragmentManager fragmentManager = getSupportFragmentManager();
-        fragmentManager.beginTransaction()
-                .add(R.id.meeting_container, fragment)
-                .commit();
-        currentFragment = (CallSession.CallSessionCallback) fragment;
-    }
-
-    private void initListener() {
-        meetingHangupImageView.setOnClickListener(this);
-    }
-
-    private void initData() {
-        Intent intent = getIntent();
-        String room = intent.getStringExtra("room");
-        isOutgoing = intent.getBooleanExtra(EXTRA_MO, false);
-        try {
-            gEngineKit = SkyEngineKit.Instance();
-        } catch (NotInitializedException e) {
-            finish();
-        }
-        String[] per = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};
-        Permissions.request(this, per, integer -> {
-            if (integer == 0) {
-                // 权限同意
-                init(room, isOutgoing);
-            } else {
-                // 权限拒绝
-                CallMultiActivity.this.finish();
-            }
-        });
-
-
-    }
-
-    private void init(String room, boolean isOutgoing) {
-        SkyEngineKit.init(new VoipEvent());
-        if (isOutgoing) {
-            // 创建一个房间并进入
-            gEngineKit.createAndJoinRoom(this,
-                    "room-" + UUID.randomUUID().toString().substring(0, 16));
-        } else {
-            // 加入房间
-            gEngineKit.joinRoom(this, room);
-        }
-
-
-        CallSession session = gEngineKit.getCurrentSession();
-        if (session == null) {
-            this.finish();
-        } else {
-            session.setSessionCallback(this);
-
-        }
-
-
-    }
-
-
-    public SkyEngineKit getEngineKit() {
-        return gEngineKit;
-    }
-
-
-    @TargetApi(19)
-    private static int getSystemUiVisibility() {
-        int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-        }
-        return flags;
-    }
-
-
-    //-------------------------------------------------回调相关------------------------------------
-    @Override
-    public void didCallEndWithReason(EnumType.CallEndReason var1) {
-        finish();
-    }
-
-    @Override
-    public void didChangeState(EnumType.CallState callState) {
-        handler.post(() -> currentFragment.didChangeState(callState));
-    }
-
-    @Override
-    public void didChangeMode(boolean var1) {
-        handler.post(() -> currentFragment.didChangeMode(var1));
-    }
-
-    @Override
-    public void didCreateLocalVideoTrack() {
-        handler.post(() -> currentFragment.didCreateLocalVideoTrack());
-    }
-
-    @Override
-    public void didReceiveRemoteVideoTrack(String userId) {
-        handler.post(() -> currentFragment.didReceiveRemoteVideoTrack(userId));
-    }
-
-    @Override
-    public void didUserLeave(String userId) {
-        handler.post(() -> currentFragment.didUserLeave(userId));
-    }
-
-    @Override
-    public void didError(String var1) {
-        finish();
-    }
-
-    @Override
-    public void didDisconnected(String userId) {
-
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (v.getId() == R.id.meetingHangupImageView) {
-            handleHangup();
-        }
-
-        /*switch (v.getId()) {
-            case R.id.meetingHangupImageView:
-                handleHangup();
-                break;
-        }*/
-
-    }
-
-    // 处理挂断事件
-    private void handleHangup() {
-        SkyEngineKit.Instance().leaveRoom();
-        this.finish();
-    }
-}

+ 0 - 394
WebRTC/src/main/java/com/wdkl/core/voip/CallSingleActivity.java

@@ -1,394 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.Manifest;
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Color;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.v4.app.FragmentManager;
-import android.util.Log;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.Toast;
-
-
-import com.wdkl.core.base.BaseActivity;
-import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil;
-import com.wdkl.permission.Permissions;
-import com.wdkl.skywebrtc.CallSession;
-import com.wdkl.skywebrtc.EnumType;
-import com.wdkl.skywebrtc.SkyEngineKit;
-import com.wdkl.skywebrtc.except.NotInitializedException;
-import com.wdkl.webrtc.R;
-
-import java.util.UUID;
-
-
-/**
- * Created by dds on 2018/7/26.
- * 单人通话界面
- */
-public class CallSingleActivity extends BaseActivity implements CallSession.CallSessionCallback {
-
-    public static final String EXTRA_TARGET = "targetId";
-    public static final String EXTRA_MO = "isOutGoing";
-    public static final String EXTRA_AUDIO_ONLY = "audioOnly";
-    public static final String EXTRA_USER_NAME = "userName";
-    public static final String EXTRA_FROM_FLOATING_VIEW = "fromFloatingView";
-    private static final String TAG = "CallSingleActivity";
-
-    private Handler handler = new Handler(Looper.getMainLooper());
-    private boolean isOutgoing;
-    private String targetId;
-    boolean isAudioOnly;
-    private boolean isFromFloatingView;
-
-    private SkyEngineKit gEngineKit;
-
-    private SingleCallFragment currentFragment;
-    private String room;
-
-    public static Intent getCallIntent(Context context, String targetId, boolean isOutgoing, String inviteUserName,
-                                       boolean isAudioOnly, boolean isClearTop) {
-        Intent voip = new Intent(context, CallSingleActivity.class);
-        voip.putExtra(CallSingleActivity.EXTRA_MO, isOutgoing);
-        voip.putExtra(CallSingleActivity.EXTRA_TARGET, targetId);
-        voip.putExtra(CallSingleActivity.EXTRA_USER_NAME, inviteUserName);
-        voip.putExtra(CallSingleActivity.EXTRA_AUDIO_ONLY, isAudioOnly);
-        voip.putExtra(CallSingleActivity.EXTRA_FROM_FLOATING_VIEW, false);
-        if (isClearTop) {
-            voip.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        }
-        return voip;
-    }
-
-
-    public static void openActivity(Context context, String targetId, boolean isOutgoing, String inviteUserName,
-                                    boolean isAudioOnly, boolean isClearTop) {
-        Intent intent = getCallIntent(context, targetId, isOutgoing, inviteUserName, isAudioOnly, isClearTop);
-        //if (context instanceof Activity) {
-        //    context.startActivity(intent);
-        //} else {
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            context.startActivity(intent);
-        //}
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setStatusBarOrScreenStatus(this);
-        setContentView(R.layout.activity_single_call);
-
-        try {
-            gEngineKit = SkyEngineKit.Instance();
-        } catch (NotInitializedException e) {
-            SkyEngineKit.init(new VoipEvent()); //重新初始化
-            try {
-                gEngineKit = SkyEngineKit.Instance();
-            } catch (NotInitializedException ex) {
-                finish();
-            }
-        }
-        final Intent intent = getIntent();
-        targetId = intent.getStringExtra(EXTRA_TARGET);
-        isFromFloatingView = intent.getBooleanExtra(EXTRA_FROM_FLOATING_VIEW, false);
-        isOutgoing = intent.getBooleanExtra(EXTRA_MO, false);
-        isAudioOnly = intent.getBooleanExtra(EXTRA_AUDIO_ONLY, false);
-
-        if (isFromFloatingView) {
-            //Intent serviceIntent = new Intent(this, FloatingVoipService.class);
-            //stopService(serviceIntent);
-            //init(targetId, false, isAudioOnly, false);
-        } else {
-            // 权限检测
-            String[] per;
-            if (isAudioOnly) {
-                per = new String[]{Manifest.permission.RECORD_AUDIO};
-            } else {
-                per = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};
-            }
-            Permissions.request(this, per, integer -> {
-                Log.d(TAG, "Permissions.request integer = " + integer);
-                if (integer == 0) {
-                    // 权限同意
-                    init(targetId, isOutgoing, isAudioOnly);
-                } else {
-                    Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
-                    // 权限拒绝
-                    finish();
-                }
-            });
-        }
-
-
-    }
-
-    @Override
-    public void onBackPressed() {
-        //通话时不能按返回键,跟微信同现象,只能挂断结束或者接听
-//        super.onBackPressed();
-//        if (currentFragment != null) {
-//            if (currentFragment instanceof FragmentAudio) {
-//                ((FragmentAudio) currentFragment).onBackPressed();
-//            } else if (currentFragment instanceof FragmentVideo) {
-//                ((FragmentVideo) currentFragment).onBackPressed();
-//            }
-//        }
-
-    }
-
-    private void init(String targetId, boolean outgoing, boolean audioOnly) {
-        SingleCallFragment fragment;
-        if (audioOnly) {
-            fragment = new FragmentAudio();
-        } else {
-            fragment = new FragmentVideo();
-        }
-        FragmentManager fragmentManager = getSupportFragmentManager();
-        currentFragment = fragment;
-        fragmentManager.beginTransaction()
-                    .replace(android.R.id.content, fragment)
-                    .commit();
-
-        if (outgoing) {
-            // 创建会话
-            room = UUID.randomUUID().toString() + System.currentTimeMillis();
-            boolean b = gEngineKit.startOutCall(getApplicationContext(), room, targetId, audioOnly);
-            if (!b) {
-                finish();
-                return;
-            }
-            CallSession session = gEngineKit.getCurrentSession();
-            if (session == null) {
-                finish();
-            } else {
-                session.setSessionCallback(this);
-                session.toggleSpeaker(true);
-            }
-        } else {
-            CallSession session = gEngineKit.getCurrentSession();
-            if (session == null) {
-                finish();
-            } else {
-                /*if (session.isAudioOnly() && !audioOnly) { //这种情况是,对方切换成音频的时候,activity还没启动,这里启动后需要切换一下
-                    isAudioOnly = session.isAudioOnly();
-                    fragment.didChangeMode(true);
-                }*/
-                Log.d(TAG, "session = " + session + "; session.getState() = " + session.getState());
-                session.setSessionCallback(this);
-                session.toggleSpeaker(true);
-
-                //之前已经通过tcp接受了,此时sip通话建立,直接接通
-                if (session.getState() == EnumType.CallState.Incoming) {
-                    session.joinHome(session.getRoomId());
-                } else {
-                    session.sendRefuse();
-                }
-            }
-        }
-
-    }
-
-    private void init(String targetId, boolean outgoing, boolean audioOnly, boolean isReplace) {
-        SingleCallFragment fragment;
-        if (audioOnly) {
-            fragment = new FragmentAudio();
-        } else {
-            fragment = new FragmentVideo();
-        }
-        FragmentManager fragmentManager = getSupportFragmentManager();
-        currentFragment = fragment;
-        if (isReplace) {
-            fragmentManager.beginTransaction()
-                    .replace(android.R.id.content, fragment)
-                    .commit();
-        } else {
-            fragmentManager.beginTransaction()
-                    .add(android.R.id.content, fragment)
-                    .commit();
-        }
-        if (outgoing && !isReplace) {
-            // 创建会话
-            room = UUID.randomUUID().toString() + System.currentTimeMillis();
-            boolean b = gEngineKit.startOutCall(getApplicationContext(), room, targetId, audioOnly);
-            if (!b) {
-                finish();
-                return;
-            }
-            //App.getInstance().setRoomId(room);
-            //App.getInstance().setOtherUserId(targetId);
-            CallSession session = gEngineKit.getCurrentSession();
-            if (session == null) {
-                finish();
-            } else {
-                session.setSessionCallback(this);
-            }
-        } else {
-            CallSession session = gEngineKit.getCurrentSession();
-            if (session == null) {
-                finish();
-            } else {
-                //if (session.isAudioOnly() && !audioOnly) { //这种情况是,对方切换成音频的时候,activity还没启动,这里启动后需要切换一下
-                //    isAudioOnly = session.isAudioOnly();
-                //    fragment.didChangeMode(true);
-                //}
-                session.setSessionCallback(this);
-            }
-        }
-
-    }
-
-    public SkyEngineKit getEngineKit() {
-        return gEngineKit;
-    }
-
-    public boolean isOutgoing() {
-        return isOutgoing;
-    }
-
-
-    public boolean isFromFloatingView() {
-        return isFromFloatingView;
-    }
-
-    // 显示小窗
-    /*public void showFloatingView() {
-        if (!checkOverlayPermission()) {
-            return;
-        }
-        Intent intent = new Intent(this, FloatingVoipService.class);
-        intent.putExtra(EXTRA_TARGET, targetId);
-        intent.putExtra(EXTRA_AUDIO_ONLY, isAudioOnly);
-        intent.putExtra(EXTRA_MO, isOutgoing);
-        startService(intent);
-        finish();
-    }*/
-
-    // 切换到语音通话
-    public void switchAudio() {
-        //init(targetId, isOutgoing, true, true);
-    }
-
-    public String getRoomId() {
-        return room;
-    }
-
-    // ======================================界面回调================================
-    @Override
-    public void didCallEndWithReason(EnumType.CallEndReason reason) {
-        //App.getInstance().setOtherUserId("0");
-        //交给fragment去finish
-//        finish();
-        handler.post(() -> currentFragment.didCallEndWithReason(reason));
-    }
-
-    @Override
-    public void didChangeState(EnumType.CallState callState) {
-        if (callState == EnumType.CallState.Connected) {
-            isOutgoing = false;
-        }
-        handler.post(() -> currentFragment.didChangeState(callState));
-    }
-
-    @Override
-    public void didChangeMode(boolean var1) {
-        handler.post(() -> currentFragment.didChangeMode(var1));
-    }
-
-    @Override
-    public void didCreateLocalVideoTrack() {
-        handler.post(() -> currentFragment.didCreateLocalVideoTrack());
-    }
-
-    @Override
-    public void didReceiveRemoteVideoTrack(String userId) {
-        handler.post(() -> currentFragment.didReceiveRemoteVideoTrack(userId));
-    }
-
-    @Override
-    public void didUserLeave(String userId) {
-        handler.post(() -> currentFragment.didUserLeave(userId));
-    }
-
-    @Override
-    public void didError(String var1) {
-        handler.post(() -> currentFragment.didError(var1));
-//        finish();
-    }
-
-    @Override
-    public void didDisconnected(String userId) {
-        handler.post(() -> currentFragment.didDisconnected(userId));
-    }
-
-
-    // ========================================================================================
-
-    private boolean checkOverlayPermission() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            SettingsCompat.setDrawOverlays(this, true);
-            if (!SettingsCompat.canDrawOverlays(this)) {
-                Toast.makeText(this, "需要悬浮窗权限", Toast.LENGTH_LONG).show();
-                SettingsCompat.manageDrawOverlays(this);
-                return false;
-            }
-        }
-        return true;
-    }
-
-
-    @TargetApi(19)
-    private static int getSystemUiVisibility() {
-        int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN |
-                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-        }
-        return flags;
-    }
-
-    /**
-     * 设置状态栏透明
-     */
-    @TargetApi(19)
-    public void setStatusBarOrScreenStatus(Activity activity) {
-        Window window = activity.getWindow();
-        //全屏+锁屏+常亮显示
-        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
-                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
-                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
-                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
-        window.getDecorView().setSystemUiVisibility(getSystemUiVisibility());
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
-            WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
-            layoutParams.layoutInDisplayCutoutMode =
-                    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
-            window.setAttributes(layoutParams);
-        }
-        // 5.0以上系统状态栏透明
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            //清除透明状态栏
-            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
-            //设置状态栏颜色必须添加
-            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
-            window.setStatusBarColor(Color.TRANSPARENT);//设置透明
-        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //19
-            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        //todo 自己下逻辑
-//        Constant.CALL_STATE = Constant.CALL_STANDBY;
-//        VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, Constant.fromId, Constant.interactionId);
-    }
-}

+ 0 - 118
WebRTC/src/main/java/com/wdkl/core/voip/FragmentMeeting.java

@@ -1,118 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.wdkl.skywebrtc.CallSession;
-import com.wdkl.skywebrtc.EnumType;
-import com.wdkl.skywebrtc.SkyEngineKit;
-import com.wdkl.webrtc.R;
-
-/**
- * Created by dds on 2020/5/24.
- * ddssingsong@163.com
- */
-public class FragmentMeeting extends Fragment implements CallSession.CallSessionCallback, View.OnClickListener {
-    private SkyEngineKit gEngineKit;
-    private CallMultiActivity activity;
-    private NineGridView grid_view;
-
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setRetainInstance(true);
-    }
-
-    @Override
-    public void onAttach(@NonNull Context context) {
-        super.onAttach(context);
-        activity = (CallMultiActivity) getActivity();
-        if (activity != null) {
-
-        }
-
-    }
-
-    @Override
-    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
-                             Bundle savedInstanceState) {
-        View view = inflater.inflate(R.layout.fragment_meeting, container, false);
-        initView(view);
-        init();
-        return view;
-    }
-
-    private void initView(View view) {
-        grid_view = view.findViewById(R.id.grid_view);
-
-    }
-
-
-    private void init() {
-        gEngineKit = activity.getEngineKit();
-    }
-
-    @Override
-    public void onClick(View v) {
-
-    }
-
-
-    @Override
-    public void didCallEndWithReason(EnumType.CallEndReason var1) {
-
-    }
-
-    @Override
-    public void didChangeState(EnumType.CallState var1) {
-
-    }
-
-    @Override
-    public void didChangeMode(boolean isAudioOnly) {
-
-    }
-
-    @Override
-    public void didCreateLocalVideoTrack() {
-        View surfaceView = gEngineKit.getCurrentSession().setupLocalVideo(true);
-        if (surfaceView != null) {
-            CallSession callSession = SkyEngineKit.Instance().getCurrentSession();
-            grid_view.addView(callSession.mMyId, surfaceView);
-
-
-        }
-
-    }
-
-    @Override
-    public void didReceiveRemoteVideoTrack(String userId) {
-        View surfaceView = gEngineKit.getCurrentSession().setupRemoteVideo(userId, true);
-        if (surfaceView != null) {
-            grid_view.addView(userId, surfaceView);
-        }
-    }
-
-    @Override
-    public void didUserLeave(String userId) {
-        grid_view.removeView(userId);
-    }
-
-    @Override
-    public void didError(String error) {
-
-    }
-
-    @Override
-    public void didDisconnected(String userId) {
-
-    }
-
-
-}

+ 0 - 73
WebRTC/src/main/java/com/wdkl/core/voip/NineGridView.java

@@ -1,73 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.GridLayout;
-
-import com.wdkl.webrtc.R;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Created by dds on 2020/7/5.
- * ddssingsong@163.com
- */
-public class NineGridView extends GridLayout {
-    private Map<String, View> map = new ConcurrentHashMap<>();
-
-    public NineGridView(Context context) {
-        this(context, null);
-    }
-
-    public NineGridView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    private void init() {
-        setColumnCount(3);
-        setRowCount(3);
-    }
-
-    public void addView(String userId, View view) {
-        map.put(userId, view);
-        resetView();
-    }
-
-
-    public void removeView(String userId) {
-        map.remove(userId);
-        resetView();
-    }
-
-    private void resetView() {
-        this.removeAllViews();
-        int i = 0;
-        Iterator<Map.Entry<String, View>> inter = map.entrySet().iterator();
-        while (inter.hasNext()) {
-            Map.Entry<String, View> entry = inter.next();
-            String key = entry.getKey();
-            View view = map.get(key);
-            GridLayout.Spec rowSpec = GridLayout.spec(i / 3, 1f);
-            GridLayout.Spec columnSpec = GridLayout.spec(i % 3, 1f);
-            GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(rowSpec, columnSpec);
-            layoutParams.height = 0;
-            layoutParams.width = 0;
-            if (i / 3 == 0)
-                layoutParams.bottomMargin = getResources().getDimensionPixelSize(R.dimen.dp_2);
-            if (i % 3 == 1) {
-                layoutParams.leftMargin = getResources().getDimensionPixelSize(R.dimen.dp_2);
-                layoutParams.rightMargin = getResources().getDimensionPixelSize(R.dimen.dp_2);
-            }
-            this.addView(view, layoutParams);
-            i++;
-        }
-
-
-    }
-
-
-}

+ 0 - 153
WebRTC/src/main/java/com/wdkl/core/voip/RomUtil.java

@@ -1,153 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.os.Build;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-/**
- * Created by dds on 2018/3/20.
- */
-
-public class RomUtil {
-    private static final String TAG = "RomUtil";
-
-    public static final String ROM_MIUI = "MIUI";
-    public static final String ROM_EMUI = "EMUI";
-    public static final String ROM_FLYME = "FLYME";
-    public static final String ROM_OPPO = "OPPO";
-    public static final String ROM_SMARTISAN = "SMARTISAN";
-
-    public static final String ROM_VIVO = "VIVO";
-    public static final String ROM_QIKU = "QIKU";
-
-    public static final String ROM_LENOVO = "LENOVO";
-    public static final String ROM_SAMSUNG = "SAMSUNG";
-
-    private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name";
-    private static final String KEY_VERSION_EMUI = "ro.build.version.emui";
-    private static final String KEY_VERSION_OPPO = "ro.build.version.opporom";
-    private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version";
-    private static final String KEY_VERSION_VIVO = "ro.vivo.os.version";
-    private static final String KEY_VERSION_GIONEE = "ro.gn.sv.version";
-    private static final String KEY_VERSION_LENOVO = "ro.lenovo.lvp.version";
-    private static final String KEY_VERSION_FLYME = "ro.build.display.id";
-
-
-    private static final String KEY_EMUI_VERSION_CODE = "ro.build.hw_emui_api_level";
-
-    private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
-    private static final String KEY_MIUI_HANDY_MODE_SF = "ro.miui.has_handy_mode_sf";
-    private static final String KEY_MIUI_REAL_BLUR = "ro.miui.has_real_blur";
-
-    private static final String KEY_FLYME_PUBLISHED = "ro.flyme.published";
-    private static final String KEY_FLYME_FLYME = "ro.meizu.setupwizard.flyme";
-
-    private static final String KEY_FLYME_ICON_FALG = "persist.sys.use.flyme.icon";
-    private static final String KEY_FLYME_SETUP_FALG = "ro.meizu.setupwizard.flyme";
-    private static final String KEY_FLYME_PUBLISH_FALG = "ro.flyme.published";
-
-    private static final String KEY_VIVO_OS_NAME = "ro.vivo.os.name";
-    private static final String KEY_VIVO_OS_VERSION = "ro.vivo.os.version";
-    private static final String KEY_VIVO_ROM_VERSION = "ro.vivo.rom.version";
-
-    public static boolean isEmui() {
-        return check(ROM_EMUI);
-    }
-
-    public static boolean isMiui() {
-        return check(ROM_MIUI);
-    }
-
-    public static boolean isVivo() {
-        return check(ROM_VIVO);
-    }
-
-    public static boolean isOppo() {
-        return check(ROM_OPPO);
-    }
-
-    public static boolean isFlyme() {
-        return check(ROM_FLYME);
-    }
-
-    public static boolean isQiku() {
-        return check(ROM_QIKU) || check("360");
-    }
-
-    public static boolean isSmartisan() {
-        return check(ROM_SMARTISAN);
-    }
-
-    private static String sName;
-
-    public static String getName() {
-        if (sName == null) {
-            check("");
-        }
-        return sName;
-    }
-
-    private static String sVersion;
-
-    public static String getVersion() {
-        if (sVersion == null) {
-            check("");
-        }
-        return sVersion;
-    }
-
-    public static boolean check(String rom) {
-        if (sName != null) {
-            return sName.equals(rom);
-        }
-
-        if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) {
-            sName = ROM_MIUI;
-        } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) {
-            sName = ROM_EMUI;
-        } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) {
-            sName = ROM_OPPO;
-        } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) {
-            sName = ROM_VIVO;
-        } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) {
-            sName = ROM_SMARTISAN;
-        } else {
-            sVersion = Build.DISPLAY;
-            if (sVersion.toUpperCase().contains(ROM_FLYME)) {
-                sName = ROM_FLYME;
-            } else {
-                sVersion = Build.UNKNOWN;
-                sName = Build.MANUFACTURER.toUpperCase();
-            }
-        }
-        return sName.equals(rom);
-    }
-
-    public static String getProp(String name) {
-        String line = null;
-        BufferedReader input = null;
-        try {
-            Process p = Runtime.getRuntime().exec("getprop " + name);
-            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
-            line = input.readLine();
-            input.close();
-        } catch (IOException ex) {
-            Log.e(TAG, "Unable to read prop " + name, ex);
-            return null;
-        } finally {
-            if (input != null) {
-                try {
-                    input.close();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-        return line;
-    }
-
-}

+ 0 - 265
WebRTC/src/main/java/com/wdkl/core/voip/SettingsCompat.java

@@ -1,265 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.app.Activity;
-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;
-
-/**
- * Created by dds on 2018/3/20.
- */
-
-public class SettingsCompat {
-    private static final String TAG = "ezy-settings-compat";
-    public static final int REQUEST_SYSTEM_ALERT_WINDOW = 11001;
-
-    private static final int OP_WRITE_SETTINGS = 23;
-    private static final int OP_SYSTEM_ALERT_WINDOW = 24;
-
-    public static boolean canDrawOverlays(Context context) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            return Settings.canDrawOverlays(context);
-        } else {
-            return checkOp(context, OP_SYSTEM_ALERT_WINDOW);
-        }
-    }
-
-    public static boolean canWriteSettings(Context context) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            return Settings.System.canWrite(context);
-        } else {
-            return checkOp(context, OP_WRITE_SETTINGS);
-        }
-    }
-
-    public static boolean setDrawOverlays(Context context, boolean allowed) {
-        return setMode(context, OP_SYSTEM_ALERT_WINDOW, allowed);
-    }
-
-    public static boolean setWriteSettings(Context context, boolean allowed) {
-        return setMode(context, OP_WRITE_SETTINGS, allowed);
-    }
-
-    public static void manageDrawOverlays(Activity context) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            try {
-                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
-                intent.setData(Uri.parse("package:" + context.getPackageName()));
-                context.startActivityForResult(intent, REQUEST_SYSTEM_ALERT_WINDOW);
-                return;
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-
-        if (manageDrawOverlaysForRom(context)) {
-            Log.d("SettingsCompat", "打开设置页面");
-        }
-
-    }
-
-    public static void manageWriteSettings(Context context) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
-            intent.setData(Uri.parse("package:" + context.getPackageName()));
-            context.startActivity(intent);
-        }
-    }
-
-    private static boolean manageDrawOverlaysForRom(Context context) {
-        if (RomUtil.isMiui()) {
-            return manageDrawOverlaysForMiui(context);
-        }
-        if (RomUtil.isEmui()) {
-            return manageDrawOverlaysForEmui(context);
-        }
-        if (RomUtil.isFlyme()) {
-            return manageDrawOverlaysForFlyme(context);
-        }
-        if (RomUtil.isOppo()) {
-            return manageDrawOverlaysForOppo(context);
-        }
-        if (RomUtil.isVivo()) {
-            return manageDrawOverlaysForVivo(context);
-        }
-        if (RomUtil.isQiku()) {
-            return manageDrawOverlaysForQihu(context);
-        }
-        if (RomUtil.isSmartisan()) {
-            return manageDrawOverlaysForSmartisan(context);
-        }
-        return false;
-    }
-
-
-    private static boolean checkOp(Context context, int op) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
-            try {
-                Method method = AppOpsManager.class.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));
-            }
-        }
-        return false;
-    }
-
-    // 可设置Android 4.3/4.4的授权状态
-    private static boolean setMode(Context context, int op, boolean allowed) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            return false;
-        }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
-            try {
-                @SuppressLint("PrivateApi") Method method = AppOpsManager.class.getDeclaredMethod("setMode", int.class, int.class, String.class, int.class);
-                method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName(), allowed ? AppOpsManager.MODE_ALLOWED : AppOpsManager
-                        .MODE_IGNORED);
-                return true;
-            } catch (Exception e) {
-                Log.e(TAG, Log.getStackTraceString(e));
-
-            }
-        }
-        return false;
-    }
-
-    private static boolean startSafely(Context context, Intent intent) {
-        if (context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0) {
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            context.startActivity(intent);
-            return true;
-        } else {
-            Log.e(TAG, "Intent is not available! " + intent);
-            return false;
-        }
-    }
-
-    // 小米
-    private static boolean manageDrawOverlaysForMiui(Context context) {
-        Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
-        intent.putExtra("extra_pkgname", context.getPackageName());
-        intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
-        if (startSafely(context, intent)) {
-            return true;
-        }
-        intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
-        if (startSafely(context, intent)) {
-            return true;
-        }
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-            Intent intent1 = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
-            intent1.setData(Uri.fromParts("package", context.getPackageName(), null));
-            return startSafely(context, intent1);
-        }
-        return false;
-    }
-
-    private final static String HUAWEI_PACKAGE = "com.huawei.systemmanager";
-
-    // 华为
-    private static boolean manageDrawOverlaysForEmui(Context context) {
-        Intent intent = new Intent();
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            intent.setClassName(HUAWEI_PACKAGE, "com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity");
-            if (startSafely(context, intent)) {
-                return true;
-            }
-        }
-        // Huawei Honor P6|4.4.4|3.0
-        intent.setClassName(HUAWEI_PACKAGE, "com.huawei.notificationmanager.ui.NotificationManagmentActivity");
-        intent.putExtra("showTabsNumber", 1);
-        if (startSafely(context, intent)) {
-            return true;
-        }
-        intent.setClassName(HUAWEI_PACKAGE, "com.huawei.permissionmanager.ui.MainActivity");
-        if (startSafely(context, intent)) {
-            return true;
-        }
-        return false;
-    }
-
-    // VIVO
-    private static boolean manageDrawOverlaysForVivo(Context context) {
-        // 不支持直接到达悬浮窗设置页,只能到 i管家 首页
-        Intent intent = new Intent("com.iqoo.secure");
-        intent.setClassName("com.iqoo.secure", "com.iqoo.secure.MainActivity");
-        // com.iqoo.secure.ui.phoneoptimize.SoftwareManagerActivity
-        // com.iqoo.secure.ui.phoneoptimize.FloatWindowManager
-        return startSafely(context, intent);
-    }
-
-    // OPPO
-    private static boolean manageDrawOverlaysForOppo(Context context) {
-        Intent intent = new Intent();
-        intent.putExtra("packageName", context.getPackageName());
-        // OPPO A53|5.1.1|2.1
-        intent.setAction("com.oppo.safe");
-        intent.setClassName("com.oppo.safe", "com.oppo.safe.permission.floatwindow.FloatWindowListActivity");
-        if (startSafely(context, intent)) {
-            return true;
-        }
-        // OPPO R7s|4.4.4|2.1
-        intent.setAction("com.color.safecenter");
-        intent.setClassName("com.color.safecenter", "com.color.safecenter.permission.floatwindow.FloatWindowListActivity");
-        if (startSafely(context, intent)) {
-            return true;
-        }
-        intent.setAction("com.coloros.safecenter");
-        intent.setClassName("com.coloros.safecenter", "com.coloros.safecenter.sysfloatwindow.FloatWindowListActivity");
-        return startSafely(context, intent);
-    }
-
-    // 魅族
-    private static boolean manageDrawOverlaysForFlyme(Context context) {
-        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());
-        return startSafely(context, intent);
-    }
-
-    // 360
-    private static boolean manageDrawOverlaysForQihu(Context context) {
-        Intent intent = new Intent();
-        intent.setClassName("com.android.settings", "com.android.settings.Settings$OverlaySettingsActivity");
-        if (startSafely(context, intent)) {
-            return true;
-        }
-        intent.setClassName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity");
-        return startSafely(context, intent);
-    }
-
-    // 锤子
-    private static boolean manageDrawOverlaysForSmartisan(Context context) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            return false;
-        }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            // 锤子 坚果|5.1.1|2.5.3
-            Intent intent = new Intent("com.smartisanos.security.action.SWITCHED_PERMISSIONS_NEW");
-            intent.setClassName("com.smartisanos.security", "com.smartisanos.security.SwitchedPermissions");
-            intent.putExtra("index", 17); // 不同版本会不一样
-            return startSafely(context, intent);
-        } else {
-            // 锤子 坚果|4.4.4|2.1.2
-            Intent intent = new Intent("com.smartisanos.security.action.SWITCHED_PERMISSIONS");
-            intent.setClassName("com.smartisanos.security", "com.smartisanos.security.SwitchedPermissions");
-            intent.putExtra("permission", new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW});
-
-            //        Intent intent = new Intent("com.smartisanos.security.action.MAIN");
-            //        intent.setClassName("com.smartisanos.security", "com.smartisanos.security.MainActivity");
-            return startSafely(context, intent);
-        }
-    }
-}

+ 0 - 7
WebRTC/src/main/java/com/wdkl/core/voip/Utils.java

@@ -1,7 +0,0 @@
-package com.wdkl.core.voip;
-
-public class Utils {
-
-    public static String ACTION_VOIP_RECEIVER = "com.wdkl.voip.Receiver";
-
-}

+ 0 - 111
WebRTC/src/main/java/com/wdkl/core/voip/VoipEvent.java

@@ -1,111 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.media.AudioManager;
-import android.net.Uri;
-import android.util.Log;
-
-import com.wdkl.core.socket.SocketManager;
-import com.wdkl.skywebrtc.inter.ISkyEvent;
-import com.wdkl.webrtc.R;
-
-import java.util.List;
-
-/**
- * Created by dds on 2019/8/25.
- * android_shuai@163.com
- */
-public class VoipEvent implements ISkyEvent {
-    private static final String TAG = "VoipEvent";
-    private AsyncPlayer ringPlayer;
-
-    public VoipEvent() {
-        //ringPlayer = new AsyncPlayer(null);
-    }
-
-    @Override
-    public void createRoom(String room, int roomSize) {
-        SocketManager.getInstance().createRoom(room, roomSize);
-    }
-
-    @Override
-    public void sendInvite(String room, List<String> userIds, boolean audioOnly) {
-        SocketManager.getInstance().sendInvite(room, userIds, audioOnly);
-    }
-
-    @Override
-    public void sendRefuse(String room, String inviteId, int refuseType) {
-        SocketManager.getInstance().sendRefuse(room, inviteId, refuseType);
-    }
-
-    @Override
-    public void sendTransAudio(String toId) {
-        SocketManager.getInstance().sendTransAudio(toId);
-    }
-
-    @Override
-    public void sendDisConnect(String room, String toId, boolean isCrashed) {
-        SocketManager.getInstance().sendDisconnect(room, toId);
-    }
-
-    @Override
-    public void sendCancel(String mRoomId, List<String> toIds) {
-        SocketManager.getInstance().sendCancel(mRoomId, toIds);
-    }
-
-
-    @Override
-    public void sendJoin(String room) {
-        SocketManager.getInstance().sendJoin(room);
-    }
-
-    @Override
-    public void sendRingBack(String targetId, String room) {
-        SocketManager.getInstance().sendRingBack(targetId, room);
-    }
-
-    @Override
-    public void sendLeave(String room, String userId) {
-        SocketManager.getInstance().sendLeave(room, userId);
-    }
-
-
-    @Override
-    public void sendOffer(String userId, String sdp) {
-        SocketManager.getInstance().sendOffer(userId, sdp);
-    }
-
-    @Override
-    public void sendAnswer(String userId, String sdp) {
-        SocketManager.getInstance().sendAnswer(userId, sdp);
-
-    }
-
-    @Override
-    public void sendIceCandidate(String userId, String id, int label, String candidate) {
-        SocketManager.getInstance().sendIceCandidate(userId, id, label, candidate);
-    }
-
-    @Override
-    public void onRemoteRing() {
-
-    }
-
-
-    //==============================================================================
-    @Override
-    public void shouldStartRing(boolean isComing) {
-        if (isComing) {
-            //Uri uri = Uri.parse("android.resource://" + SocketManager.getInstance().getContext().getPackageName() + "/" + R.raw.incoming_call_ring);
-            //ringPlayer.play(SocketManager.getInstance().getContext(), uri, true, AudioManager.STREAM_RING);
-        } else {
-            //Uri uri = Uri.parse("android.resource://" + SocketManager.getInstance().getContext().getPackageName() + "/" + R.raw.wr_ringback);
-            //ringPlayer.play(SocketManager.getInstance().getContext(), R.raw.wr_ringback, true, AudioManager.STREAM_MUSIC);
-        }
-    }
-
-    @Override
-    public void shouldStopRing() {
-        Log.d(TAG, "shouldStopRing begin");
-        //ringPlayer.stop();
-    }
-}

+ 0 - 237
WebRTC/src/main/java/com/wdkl/core/voip/VoipReceiver.java

@@ -1,237 +0,0 @@
-package com.wdkl.core.voip;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Build;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.blankj.utilcode.util.LogUtils;
-import com.wdkl.core.base.BaseActivity;
-import com.wdkl.core.socket.SocketManager;
-import com.wdkl.core.util.ActivityStackManager;
-import com.wdkl.ncs.android.component.nursehome.common.Constants;
-import com.wdkl.ncs.android.middleware.utils.MessageEvent;
-import com.wdkl.permission.Permissions;
-import com.wdkl.skywebrtc.SkyEngineKit;
-import com.wdkl.webrtc.R;
-import com.tapadoo.alerter.Alerter;
-
-import org.greenrobot.eventbus.EventBus;
-
-import java.util.ArrayList;
-
-/**
- * Created by dds on 2019/8/25.
- * android_shuai@163.com
- */
-public class VoipReceiver extends BroadcastReceiver {
-    private static final String TAG = "VoipReceiver";
-    private AsyncPlayer ringPlayer;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        String action = intent.getAction();
-        if (Utils.ACTION_VOIP_RECEIVER.equals(action)) {
-            String room = intent.getStringExtra("room");
-            boolean audioOnly = intent.getBooleanExtra("audioOnly", true);
-            String inviteId = intent.getStringExtra("inviteId");
-            String inviteUserName = intent.getStringExtra("inviteUserName");
-            String userList = intent.getStringExtra("userList");
-            String[] list = userList.split(",");
-            SkyEngineKit.init(new VoipEvent());
-            //todo 处理邀请人名称
-            if (inviteUserName == null) {
-                inviteUserName = "p2pChat";
-            }
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-                //if (com.wdkl.core.util.Utils.isAppRunningForeground(context)) {
-                    onForegroundOrBeforeVersionO(context, room, userList, inviteId, audioOnly, inviteUserName, true);
-                //} else {
-                //    onBackgroundAfterVersionO(context, room, userList, inviteId, audioOnly, inviteUserName);
-                //}
-            } else {
-                onForegroundOrBeforeVersionO(context,
-                        room,
-                        userList,
-                        inviteId,
-                        audioOnly,
-                        inviteUserName,
-                        com.wdkl.core.util.Utils.isAppRunningForeground(context)
-                );
-            }
-        }
-    }
-
-    private void onBackgroundAfterVersionO(Context context,
-            String room, String userList,
-            String inviteId, Boolean audioOnly, String inviteUserName
-    ) {
-        String[] strArr = userList.split(",");
-        ArrayList<String> list = new ArrayList<>();
-        for (String str : strArr)
-            list.add(str);
-        SkyEngineKit.init(new VoipEvent());
-        //BaseActivity activity = (BaseActivity) ActivityStackManager.getInstance().getTopActivity();
-        // 权限检测
-        String[] per;
-        if (audioOnly) {
-            per = new String[]{Manifest.permission.RECORD_AUDIO};
-        } else {
-            per = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};
-        }
-        boolean hasPermission = true;  //Permissions.has(activity, per);
-        if (hasPermission) {
-            onBackgroundHasPermission(context, room, list, inviteId, audioOnly, inviteUserName);
-        } /*else {
-            CallForegroundNotification notification = new CallForegroundNotification(SocketManager.getInstance().getContext());
-            notification.sendRequestIncomingPermissionsNotification(
-                    activity,
-                    room,
-                    userList,
-                    inviteId,
-                    inviteUserName,
-                    audioOnly
-            );
-        }*/
-    }
-
-    private void onBackgroundHasPermission(
-            Context context, String room, ArrayList<String> list,
-            String inviteId, Boolean audioOnly, String inviteUserName) {
-        boolean b = SkyEngineKit.Instance().startInCall(SocketManager.getInstance().getContext(), room, inviteId, audioOnly);
-        LogUtils.dTag(TAG, "onBackgroundHasPermission b = " + b );
-        if (b) {
-            //App.getInstance().setOtherUserId(inviteId);
-            if (list.size() == 1) {
-                CallForegroundNotification notification = new CallForegroundNotification(SocketManager.getInstance().getContext());
-                notification.sendIncomingCallNotification(
-                        SocketManager.getInstance().getContext(),
-                        inviteId,
-                        false,
-                        inviteUserName,
-                        audioOnly,
-                        true
-                );
-            }
-        }
-    }
-
-    private void onForegroundOrBeforeVersionO(Context context,
-            String room, String userList,
-            String inviteId, Boolean audioOnly, String inviteUserName, Boolean isForeGround
-    ) {
-        String[] strArr = userList.split(",");
-        ArrayList<String> list = new ArrayList<>();
-        for (String str : strArr)
-            list.add(str);
-        SkyEngineKit.init(new VoipEvent());
-        //BaseActivity activity = (BaseActivity) ActivityStackManager.getInstance().getTopActivity();
-        // 权限检测
-        String[] per;
-        if (audioOnly) {
-            per = new String[]{Manifest.permission.RECORD_AUDIO};
-        } else {
-            per = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};
-        }
-        boolean hasPermission = true;  //Permissions.has(activity, per);
-        LogUtils.dTag(TAG, "onForegroundOrBeforeVersionO hasPermission = " + hasPermission + ", isForeGround = " + isForeGround);
-        if (hasPermission) {
-            onHasPermission(context, room, list, inviteId, audioOnly, inviteUserName);
-        } /*else {
-
-            ringPlayer = new AsyncPlayer(null);
-            shouldStartRing(true); //来电先响铃
-            if (isForeGround) {
-                Alerter.create(activity).setTitle("来电通知")
-                        .setText(
-                                "您收到" + inviteUserName + "的来电邀请,请允许"
-                                        + (audioOnly ? "录音"
-                                        : "录音和相机") + "权限来通话"
-                        )
-                        .enableSwipeToDismiss()
-                        .setBackgroundColorRes(R.color.colorAccent) // or setBackgroundColorInt(Color.CYAN)
-                        .setDuration(60 * 1000)
-                        .addButton("确定", R.style.AlertButtonBgWhite, v -> {
-                            Permissions.request(activity, per, integer -> {
-                                shouldStopRing();
-                                Log.d(TAG, "Permissions.request integer = " + integer);
-                                if (integer == 0) { //权限同意
-                                    onHasPermission(activity, room, list, inviteId, audioOnly, inviteUserName);
-                                } else {
-                                    onPermissionDenied(room, inviteId);
-                                }
-                                Alerter.hide();
-                            });
-                        })
-                        .addButton("取消", R.style.AlertButtonBgWhite, v -> {
-                            shouldStopRing();
-                            onPermissionDenied(room, inviteId);
-                            Alerter.hide();
-                        }).show();
-            } else {
-                CallForegroundNotification notification = new CallForegroundNotification(SocketManager.getInstance().getContext());
-                notification.sendRequestIncomingPermissionsNotification(
-                        activity,
-                        room,
-                        userList,
-                        inviteId,
-                        inviteUserName,
-                        audioOnly
-                );
-            }
-
-        }*/
-    }
-
-    private void onHasPermission(
-            Context context, String room, ArrayList<String> list,
-            String inviteId, Boolean audioOnly, String inviteUserName
-    ) {
-        boolean b = SkyEngineKit.Instance().startInCall(SocketManager.getInstance().getContext(), room, inviteId, audioOnly);
-        LogUtils.dTag(TAG, "onHasPermission b = " + b);
-        if (b) {
-            //App.getInstance().setOtherUserId(inviteId);
-            LogUtils.dTag(TAG, "onHasPermission list.size() = " + list.size());
-            EventBus.getDefault().post(new MessageEvent(Constants.INCOME_CALL_READY,Constants.INCOME_CALL_READY));
-            if (list.size() == 1) {
-                //以视频电话拨打,切换到音频或重走这里,结束掉上一个,防止对方挂断后,下边还有一个通话界面
-//                if (context instanceof CallSingleActivity) {
-//                    ((CallSingleActivity) context).finish();
-//                }
-//                CallSingleActivity.openActivity(context, inviteId, false, inviteUserName, audioOnly, true);
-            } else {
-                // 群聊
-            }
-        } /*else {
-            Activity activity = ActivityStackManager.getInstance().getTopActivity();
-            activity.finish(); //销毁掉刚才拉起的
-        }*/
-    }
-
-    // 权限拒绝
-    private void onPermissionDenied(String room, String inviteId) {
-        SkyEngineKit.Instance().sendRefuseOnPermissionDenied(room, inviteId);//通知对方结束
-        Toast.makeText(SocketManager.getInstance().getContext(), "权限被拒绝,无法通话", Toast.LENGTH_SHORT).show();
-    }
-
-    private void shouldStartRing(boolean isComing) {
-        if (isComing) {
-            //Uri uri = Uri.parse("android.resource://" + SocketManager.getInstance().getContext().getPackageName() + "/" + R.raw.incoming_call_ring);
-            //ringPlayer.play(SocketManager.getInstance().getContext(), uri, true, AudioManager.STREAM_RING);
-        } else {
-            //Uri uri = Uri.parse("android.resource://" + SocketManager.getInstance().getContext().getPackageName() + "/" + R.raw.wr_ringback);
-            //ringPlayer.play(SocketManager.getInstance().getContext(), R.raw.wr_ringback, true, AudioManager.STREAM_MUSIC);
-        }
-    }
-
-    private void shouldStopRing() {
-        Log.d(TAG, "shouldStopRing begin");
-        //ringPlayer.stop();
-    }
-}

+ 0 - 37
WebRTC/src/main/java/com/wdkl/net/HttpRequest.java

@@ -1,37 +0,0 @@
-package com.wdkl.net;
-
-import java.io.InputStream;
-import java.util.Map;
-
-/**
- * Created by dds on 2018/4/23.
- */
-
-public interface HttpRequest {
-
-    /**
-     * get请求
-     *
-     * @param url      url
-     * @param params   params
-     * @param callback callback
-     */
-    void get(String url, Map<String, Object> params, ICallback callback);
-
-    /**
-     * post请求
-     *
-     * @param url      url
-     * @param params   params
-     * @param callback callback
-     */
-    void post(String url, Map<String, Object> params, ICallback callback);
-
-    /**
-     * 设置双向证书
-     *
-     * @param certificate certificate
-     * @param pwd         pwd
-     */
-    void setCertificate(InputStream certificate, String pwd);
-}

+ 0 - 47
WebRTC/src/main/java/com/wdkl/net/HttpRequestPresenter.java

@@ -1,47 +0,0 @@
-package com.wdkl.net;
-
-import java.io.InputStream;
-import java.util.Map;
-
-/**
- * Created by dds on 2019/7/3.
- * android_shuai@163.com
- */
-public class HttpRequestPresenter implements HttpRequest {
-    protected HttpRequest httpRequest;
-    private static volatile HttpRequestPresenter instance;
-
-    public HttpRequestPresenter(HttpRequest httpRequest) {
-        this.httpRequest = httpRequest;
-    }
-
-    public static void init(HttpRequest httpRequest) {
-        if (null == instance) {
-            synchronized (HttpRequestPresenter.class) {
-                if (null == instance) {
-                    instance = new HttpRequestPresenter(httpRequest);
-                }
-            }
-        }
-    }
-
-    public static HttpRequestPresenter getInstance() {
-        return instance;
-    }
-
-    @Override
-    public void get(String url, Map<String, Object> params, ICallback callback) {
-        httpRequest.get(url, params, callback);
-    }
-
-    @Override
-    public void post(String url, Map<String, Object> params, ICallback callback) {
-        httpRequest.post(url, params, callback);
-    }
-
-    // 设置双向证书
-    @Override
-    public void setCertificate(InputStream certificate, String pwd) {
-        httpRequest.setCertificate(certificate, pwd);
-    }
-}

+ 0 - 12
WebRTC/src/main/java/com/wdkl/net/ICallback.java

@@ -1,12 +0,0 @@
-package com.wdkl.net;
-
-/**
- * Created by dds on 2018/4/23.
- */
-
-public interface ICallback {
-
-    void onSuccess(String result);
-
-    void onFailure(int code, Throwable t);
-}

+ 0 - 54
WebRTC/src/main/java/com/wdkl/net/urlconn/UrlConnRequest.java

@@ -1,54 +0,0 @@
-package com.wdkl.net.urlconn;
-
-
-import com.wdkl.net.HttpRequest;
-import com.wdkl.net.ICallback;
-
-import java.io.InputStream;
-import java.util.Map;
-
-/**
- * Created by dds on 2019/12/20.
- */
-public class UrlConnRequest implements HttpRequest {
-
-
-    public UrlConnRequest() {
-    }
-
-    @Override
-    public void get(String url, Map<String, Object> params, ICallback callback) {
-        try {
-            String param = null;
-            if (params != null) {
-                param = UrlConnUtils.builderUrlParams(params);
-
-            }
-            String s = UrlConnUtils.sendGet(url, param);
-            callback.onSuccess(s);
-
-        } catch (Exception e) {
-            callback.onFailure(-1, e);
-        }
-
-    }
-
-    @Override
-    public void post(String url, Map<String, Object> params, ICallback callback) {
-        try {
-            String postStr = null;
-            if (params != null) {
-                postStr = UrlConnUtils.builderUrlParams(params);
-            }
-            String result = UrlConnUtils.sendPost(url, postStr);
-            callback.onSuccess(result);
-        } catch (Exception e) {
-            callback.onFailure(-1, e);
-        }
-    }
-
-    @Override
-    public void setCertificate(InputStream certificate, String pwd) {
-
-    }
-}

+ 0 - 263
WebRTC/src/main/java/com/wdkl/net/urlconn/UrlConnUtils.java

@@ -1,263 +0,0 @@
-package com.wdkl.net.urlconn;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * Created by dds on 2019/11/28.
- * android_shuai@163.com
- */
-public class UrlConnUtils {
-    private static final String TAG = "dds_UrlConnUtils";
-
-    public static String sendPost(String serverUrl, String formBody) throws Exception {
-        String result;
-        DataOutputStream out;
-        URL url = new URL(serverUrl);
-        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
-        if (serverUrl.startsWith("https")) {
-            trustAllHosts(connection);
-            connection.setHostnameVerifier(DO_NOT_VERIFY);
-        }
-        connection.setDoInput(true);
-        connection.setDoOutput(true);
-        connection.setRequestMethod("POST");
-        connection.setUseCaches(false);
-        connection.setInstanceFollowRedirects(true);
-        connection.addRequestProperty("Content-Type", "application/json");
-        connection.connect();
-        out = new DataOutputStream(connection.getOutputStream());
-        if (formBody != null && !"".equals(formBody)) {
-            out.writeBytes(formBody);
-        }
-        out.flush();
-        int responseCode = connection.getResponseCode();
-        if (responseCode >= 200 && responseCode < 300) {
-            InputStream inputStream = connection.getInputStream();
-            result = inputStream2String(inputStream);
-        } else {
-            throw new Exception(String.format("response code:%d, error msg:%s", responseCode, connection.getResponseMessage()));
-        }
-        connection.disconnect();
-        out.close();
-        return result;
-    }
-
-    public static String sendGet(String serverUrl, String param) throws Exception {
-        String result;
-        String reqUrl = serverUrl + (param == null ? "" : ("?" + param));
-        URL url = new URL(reqUrl);
-
-        // ---------------------------------https--------------------------
-//        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
-//        if (serverUrl.startsWith("https")) {
-//            trustAllHosts(connection);
-//            connection.setHostnameVerifier(DO_NOT_VERIFY);
-//        }
-        // http
-        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-        connection.setDoInput(true);
-        connection.setDoOutput(true);
-        connection.setRequestMethod("GET");
-        connection.setUseCaches(false);
-        connection.setInstanceFollowRedirects(true);
-        connection.addRequestProperty("Content-Type", "application/json");
-        connection.connect();
-        int responseCode = connection.getResponseCode();
-        if (responseCode >= 200 && responseCode < 300) {
-            InputStream inputStream = connection.getInputStream();
-            result = inputStream2String(inputStream);
-        } else {
-            throw new Exception(String.format("response code:%d, error msg:%s", responseCode, connection.getResponseMessage()));
-        }
-        connection.disconnect();
-        return result;
-    }
-
-    public static boolean download(String u, String path) {
-        try {
-            URL url = new URL(u);
-            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
-            trustAllHosts(connection);
-            connection.setHostnameVerifier(DO_NOT_VERIFY);
-            connection.setDoInput(true);
-            connection.setDoOutput(true);
-            connection.setRequestMethod("GET");
-            connection.setUseCaches(false);
-            connection.setInstanceFollowRedirects(true);
-            //可设置请求头
-            connection.setRequestProperty("Content-Type", "application/octet-stream");
-            connection.setRequestProperty("Connection", "Keep-Alive");// 维持长连接
-            connection.setRequestProperty("Charset", "UTF-8");
-            connection.connect();
-            byte[] file = input2byte(connection.getInputStream());
-            File file1 = writeBytesToFile(file, path);
-            if (file1.exists()) {
-                return true;
-            }
-        } catch (Exception e) {
-            return false;
-        }
-        return false;
-    }
-
-    /**
-     * 构建json参数
-     */
-    public static String builderJsonParams(Map<String, Object> params) {
-        JSONObject jsonObject;
-        try {
-            Set<String> keySet = params.keySet();
-            List<String> keyList = new ArrayList<>(keySet);
-            Collections.sort(keyList);
-            jsonObject = new JSONObject();
-            for (String key : keyList) {
-                Object value = params.get(key);
-                if (value == null || "".equals(value)) {
-                    continue;
-                }
-                jsonObject.put(key, String.valueOf(params.get(key)));
-            }
-        } catch (JSONException e) {
-            return null;
-        }
-        return jsonObject.toString();
-    }
-
-    /**
-     * 构建post参数
-     */
-    public static String builderUrlParams(Map<String, Object> params) {
-        StringBuilder sb = new StringBuilder();
-        Set<String> keySet = params.keySet();
-        List<String> keyList = new ArrayList<>(keySet);
-        Collections.sort(keyList);
-        for (String key : keyList) {
-            Object value = params.get(key);
-            if (value == null || "".equals(value)) {
-                continue;
-            }
-            sb.append(key).append("=").append(params.get(key)).append("&");
-        }
-        if (sb.length() > 0) {
-            return sb.substring(0, sb.length() - 1);
-        }
-        return null;
-    }
-
-    private static byte[] input2byte(InputStream inStream) throws IOException {
-        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
-        byte[] buff = new byte[100];
-        int rc = 0;
-        while ((rc = inStream.read(buff, 0, 100)) > 0) {
-            swapStream.write(buff, 0, rc);
-        }
-        return swapStream.toByteArray();
-    }
-
-    private static File writeBytesToFile(byte[] b, String outputFile) {
-        File file = null;
-        FileOutputStream os = null;
-        try {
-            file = new File(outputFile);
-            File parentFile = file.getParentFile();
-            if (!parentFile.exists()) {
-                parentFile.mkdirs();
-            }
-            os = new FileOutputStream(file);
-            os.write(b);
-        } catch (Exception var13) {
-            var13.printStackTrace();
-            if (file != null && file.exists()) {
-                file.delete();
-            }
-        } finally {
-            try {
-                if (os != null) {
-                    os.close();
-                }
-            } catch (IOException var12) {
-                var12.printStackTrace();
-            }
-        }
-        return file;
-    }
-
-    private static String inputStream2String(InputStream inputStream) {
-        ByteArrayOutputStream bos = null;
-        byte[] bytes = new byte[1024];
-        int len = 0;
-        try {
-            bos = new ByteArrayOutputStream();
-            while ((len = inputStream.read(bytes)) != -1) {
-                bos.write(bytes, 0, len);
-            }
-            return new String(bos.toByteArray());
-        } catch (IOException e) {
-            e.printStackTrace();
-        } finally {
-            if (inputStream != null) {
-                try {
-                    inputStream.close();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-            if (bos != null) {
-                try {
-                    bos.close();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-        return null;
-    }
-
-    private static void trustAllHosts(HttpsURLConnection connection) {
-        try {
-            SSLContext sc = SSLContext.getInstance("TLS");
-            sc.init(null, trustAllCerts, new java.security.SecureRandom());
-            SSLSocketFactory newFactory = sc.getSocketFactory();
-            connection.setSSLSocketFactory(newFactory);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    private static final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
-        public X509Certificate[] getAcceptedIssuers() {
-            return new X509Certificate[]{};
-        }
-
-        public void checkClientTrusted(X509Certificate[] chain, String authType) {
-        }
-
-        public void checkServerTrusted(X509Certificate[] chain, String authType) {
-        }
-    }};
-
-    private static final HostnameVerifier DO_NOT_VERIFY = (hostname, session) -> true;
-}

+ 0 - 18
WebRTC/src/main/java/com/wdkl/permission/Consumer.java

@@ -1,18 +0,0 @@
-package com.wdkl.permission;
-
-/**
- * Represents an operation that accepts a single input argument and returns no
- * result. Unlike most other functional interfaces, {@code Consumer} is expected
- * to operate via side-effects.
- *
- * @param <T> the type of the input to the operation
- */
-public interface Consumer<T> {
-
-	/**
-	 * Performs this operation on the given argument.
-	 *
-	 * @param t the input argument
-	 */
-	void accept(T t);
-}

+ 0 - 144
WebRTC/src/main/java/com/wdkl/permission/Permissions.java

@@ -1,144 +0,0 @@
-package com.wdkl.permission;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Process;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.core.content.ContextCompat;
-
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.Build.VERSION_CODES.M;
-
-/**
- * Permission-related helpers
- */
-public class Permissions {
-
-
-    /**
-     * @param callback will be called if request is not canceled, with either
-     *                 {@link PackageManager#PERMISSION_GRANTED} or {@link PackageManager#PERMISSION_DENIED}
-     */
-    public static void request(Activity activity, String permission, Consumer<Integer> callback) {
-        if (Build.VERSION.SDK_INT >= M) {
-            request2(activity, permission, callback);
-        } else {
-            if (has(activity, permission)) {
-                callback.accept(0);
-            } else {
-                callback.accept(-1);
-            }
-        }
-
-    }
-
-    /**
-     * @param callback will be called if request is not canceled, with either
-     *                 {@link PackageManager#PERMISSION_GRANTED} or {@link PackageManager#PERMISSION_DENIED}
-     */
-    public static void request(Activity activity, String[] permissions, Consumer<Integer> callback) {
-        if (Build.VERSION.SDK_INT >= M) {
-            request2(activity, permissions, callback);
-        } else {
-            if (has(activity, permissions)) {
-                callback.accept(0);
-            } else {
-                callback.accept(-1);
-            }
-
-        }
-
-    }
-
-    @RequiresApi(M)
-    public static void request2(Activity activity, String permission, Consumer<Integer> callback) {
-        final FragmentManager fm = activity.getFragmentManager();
-        if (!has(activity, permission)) {
-            fm.beginTransaction().add(new PermissionRequestFragment(new String[]{permission}, callback), null).commitAllowingStateLoss();
-        } else {
-            callback.accept(PERMISSION_GRANTED);
-        }
-    }
-
-    @RequiresApi(M)
-    public static void request2(Activity activity, String[] permissions, Consumer<Integer> callback) {
-        final FragmentManager fm = activity.getFragmentManager();
-        if (!has(activity, permissions)) {
-            fm.beginTransaction().add(new PermissionRequestFragment(permissions, callback), null).commitAllowingStateLoss();
-        } else {
-            callback.accept(PERMISSION_GRANTED);
-        }
-    }
-
-    public static boolean has(Context activity, String... permissions) {
-        List<String> mPermissionListDenied = new ArrayList<>();
-        for (String permission : permissions) {
-            int result = checkPermission(activity, permission);
-            if (result != PERMISSION_GRANTED) {
-                mPermissionListDenied.add(permission);
-            }
-        }
-        return mPermissionListDenied.size() == 0;
-    }
-
-    private static boolean has(Context context, String permission) {
-        return context.checkPermission(permission, Process.myPid(), Process.myUid()) == PERMISSION_GRANTED;
-    }
-
-    private static int checkPermission(Context activity, String permission) {
-        return ContextCompat.checkSelfPermission(activity, permission);
-    }
-
-    @RequiresApi(M)
-    public static class PermissionRequestFragment extends Fragment {
-
-        @SuppressLint("ValidFragment")
-        public PermissionRequestFragment(@NonNull final String[] permissions, @NonNull final Consumer<Integer> callback) {
-            mPermissions = permissions;
-            mCallback = callback;
-        }
-
-        @Override
-        public void onCreate(@Nullable final Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            if (mPermissions != null) requestPermissions(mPermissions, 0);
-        }
-
-        @Override
-        public void onRequestPermissionsResult(final int request, @NonNull final String[] permissions, @NonNull final int[] results) {
-            getFragmentManager().beginTransaction().remove(this).commit();
-            if (mCallback == null || results.length == 0/* canceled */) return;
-            boolean isGrant = true;
-            for (int result : results) {
-                if (result != PackageManager.PERMISSION_GRANTED) {
-                    isGrant = false;
-                    break;
-                }
-            }
-            mCallback.accept(isGrant ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
-        }
-
-        public PermissionRequestFragment() {
-            mPermissions = null;
-            mCallback = null;
-        }
-
-        private final @Nullable
-        String[] mPermissions;
-        private final @Nullable
-        Consumer<Integer> mCallback;
-    }
-}

+ 0 - 20
WebRTC/src/main/res/drawable-xhdpi/bg_btn_white.xml

@@ -1,20 +0,0 @@
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:insetLeft="4dp"
-    android:insetTop="6dp"
-    android:insetRight="4dp"
-    android:insetBottom="6dp">
-    <shape
-        android:shape="rectangle"
-        android:tint="@color/colorAccent">
-        <stroke
-            android:width="1dp"
-            android:color="#FFFFFF" />
-        <corners android:radius="25dp" />
-        <solid android:color="#FFFFFF" />
-        <padding
-            android:bottom="4dp"
-            android:left="8dp"
-            android:right="8dp"
-            android:top="4dp" />
-    </shape>
-</inset>

+ 0 - 52
WebRTC/src/main/res/layout/activity_launcher.xml

@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
-
-    tools:context="com.wdkl.LauncherActivity">
-
-    <com.google.android.material.appbar.AppBarLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:theme="@style/AppTheme.AppBarOverlay">
-
-        <androidx.appcompat.widget.Toolbar
-            android:id="@+id/toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="48dp"
-            app:popupTheme="@style/AppTheme.PopupOverlay" />
-
-    </com.google.android.material.appbar.AppBarLayout>
-
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:padding="16dp">
-
-        <EditText
-            android:id="@+id/et_user"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:digits="0123456789qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM"
-            android:hint="input your user name " />
-
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="The server side is written by Spring boot" />
-
-        <Button
-            android:id="@+id/button8"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:onClick="java"
-            android:text="ENTER"
-            android:textAllCaps="false" />
-    </LinearLayout>
-
-</LinearLayout>

+ 0 - 29
WebRTC/src/main/res/layout/activity_main.xml

@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <com.google.android.material.bottomnavigation.BottomNavigationView
-        android:id="@+id/nav_view"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="0dp"
-        android:layout_marginEnd="0dp"
-        android:background="?android:attr/windowBackground"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"
-        app:menu="@menu/bottom_nav_menu" />
-
-    <fragment
-        android:id="@+id/nav_host_fragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:layout_constraintBottom_toTopOf="@id/nav_view"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 0 - 112
WebRTC/src/main/res/layout/av_p2p_meeting_action.xml

@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:background="@android:color/background_dark"
-    android:gravity="center"
-    android:orientation="vertical">
-
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-
-
-        <LinearLayout
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="20dp"
-            android:layout_weight="1"
-            android:gravity="center"
-            android:orientation="vertical">
-
-            <ImageView
-                android:id="@+id/muteImageView"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:src="@drawable/av_mute_selector" />
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="10dp"
-                android:text="静音"
-                android:textColor="@android:color/white" />
-
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="20dp"
-            android:layout_marginBottom="20dp"
-            android:layout_weight="1"
-            android:gravity="center"
-            android:orientation="vertical">
-
-            <ImageView
-                android:id="@+id/switchCameraImageView"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:src="@drawable/av_switch_camera_selector" />
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="10dp"
-                android:text="切换摄像头"
-                android:textColor="@android:color/white" />
-
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="20dp"
-            android:layout_marginBottom="20dp"
-            android:layout_weight="1"
-            android:gravity="center"
-            android:orientation="vertical">
-
-            <ImageView
-                android:id="@+id/speakerImageView"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:src="@drawable/av_speaker_selector" />
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="10dp"
-                android:text="免提"
-                android:textColor="@android:color/white" />
-
-        </LinearLayout>
-
-    </LinearLayout>
-
-    <LinearLayout
-        android:id="@+id/hangupLinearLayout"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:layout_marginTop="10dp"
-        android:gravity="center"
-        android:orientation="vertical">
-
-        <ImageView
-            android:id="@+id/meetingHangupImageView"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:src="@drawable/av_hangup_selector" />
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="10dp"
-            android:text="挂断"
-            android:textColor="@android:color/white" />
-
-    </LinearLayout>
-</LinearLayout>

+ 0 - 39
WebRTC/src/main/res/layout/av_voip_float_view.xml

@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:background="@drawable/av_float_bg"
-    android:gravity="center"
-    android:orientation="vertical">
-
-    <LinearLayout
-        android:id="@+id/audioLinearLayout"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-
-        <ImageView
-            android:id="@+id/av_media_type"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:src="@drawable/av_float_audio" />
-
-        <TextView
-            android:id="@+id/durationTextView"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:gravity="center"
-            android:text="00:00"
-            android:textColor="#0195ff" />
-    </LinearLayout>
-
-    <FrameLayout
-        android:id="@+id/remoteVideoFrameLayout"
-        android:layout_width="100dp"
-        android:layout_height="140dp"
-        android:visibility="gone" />
-
-</LinearLayout>

+ 0 - 28
WebRTC/src/main/res/layout/fragment_home.xml

@@ -1,28 +0,0 @@
-<?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">
-
-
-    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
-        android:id="@+id/swipe"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-
-    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
-
-    <TextView
-        android:id="@+id/no_data"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_centerInParent="true"
-        android:gravity="center"
-        android:text="no data"
-        android:textSize="25sp" />
-
-</RelativeLayout>

+ 0 - 12
WebRTC/src/main/res/layout/fragment_meeting.xml

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/meeting_item_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <com.wdkl.core.voip.NineGridView
-        android:id="@+id/grid_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-</RelativeLayout>

+ 0 - 27
WebRTC/src/main/res/layout/fragment_room.xml

@@ -1,27 +0,0 @@
-<?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">
-
-    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
-        android:id="@+id/swipe"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-
-    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
-
-
-    <TextView
-        android:id="@+id/no_data"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_centerInParent="true"
-        android:gravity="center"
-        android:text="no data"
-        android:textSize="25sp" />
-</RelativeLayout>

+ 0 - 25
WebRTC/src/main/res/layout/fragment_setting.xml

@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:padding="16dp">
-
-    <TextView
-        android:id="@+id/text_notifications"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
-        android:textAlignment="center"
-        android:textSize="20sp" />
-
-    <Button
-        android:id="@+id/exit"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="退出登录" />
-
-
-</LinearLayout>

+ 0 - 40
WebRTC/src/main/res/layout/item_rooms.xml

@@ -1,40 +0,0 @@
-<?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="76dp"
-    android:background="#ddf2d2">
-
-    <ImageView
-        android:id="@+id/item_user_avatar"
-        android:layout_width="44dp"
-        android:layout_height="44dp"
-        android:layout_centerVertical="true"
-        android:layout_marginStart="16dp"
-        android:background="@color/colorPrimary" />
-
-    <TextView
-        android:id="@+id/item_user_name"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_marginStart="16dp"
-        android:layout_toEndOf="@id/item_user_avatar"
-        android:text="ddssingsong"
-        android:textColor="@android:color/black"
-        android:textSize="16sp" />
-
-    <Button
-        android:id="@+id/item_join_room"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:layout_centerVertical="true"
-        android:text="进入房间" />
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="1px"
-        android:layout_alignParentBottom="true"
-        android:background="@android:color/darker_gray" />
-
-</RelativeLayout>

+ 0 - 48
WebRTC/src/main/res/layout/item_users.xml

@@ -1,48 +0,0 @@
-<?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="70dp"
-    android:background="#dd82d2">
-
-    <ImageView
-        android:id="@+id/item_user_avatar"
-        android:layout_width="44dp"
-        android:layout_height="44dp"
-        android:layout_centerVertical="true"
-        android:layout_marginStart="16dp"
-        android:background="@android:color/holo_orange_dark" />
-
-    <TextView
-        android:id="@+id/item_user_name"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_marginStart="16dp"
-        android:layout_toEndOf="@id/item_user_avatar"
-        android:text="ddssingsong"
-        android:textColor="@android:color/black"
-        android:textSize="16sp" />
-
-    <Button
-        android:id="@+id/item_call_audio"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:layout_centerVertical="true"
-        android:text="语音" />
-
-    <Button
-        android:id="@+id/item_call_video"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/item_call_audio"
-        android:text="视频" />
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="1dp"
-        android:layout_alignParentBottom="true"
-        android:background="@android:color/holo_blue_dark" />
-
-</RelativeLayout>

+ 0 - 19
WebRTC/src/main/res/menu/bottom_nav_menu.xml

@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item
-        android:id="@+id/navigation_user"
-        android:icon="@drawable/ic_home_black_24dp"
-        android:title="@string/title_user" />
-
-    <item
-        android:id="@+id/navigation_room"
-        android:icon="@drawable/ic_dashboard_black_24dp"
-        android:title="@string/title_room" />
-
-    <item
-        android:id="@+id/navigation_setting"
-        android:icon="@drawable/ic_notifications_black_24dp"
-        android:title="@string/title_setting" />
-
-</menu>

+ 0 - 12
WebRTC/src/main/res/menu/menu_room.xml

@@ -1,12 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
-
-    <item
-        android:id="@+id/action_create"
-        android:icon="@android:drawable/ic_menu_add"
-        android:orderInCategory="100"
-        android:title="@string/action_create_room"
-        app:showAsAction="always" />
-
-
-</menu>

BIN
WebRTC/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
WebRTC/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
WebRTC/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
WebRTC/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
WebRTC/src/main/res/mipmap-xxxhdpi/ic_launcher.png


BIN
WebRTC/src/main/res/raw/incoming_call_ring.mp3


BIN
WebRTC/src/main/res/raw/outgoing_call_ring.mp3


BIN
WebRTC/src/main/res/raw/wr_ringback.wav


+ 0 - 9
WebRTC/src/main/res/values/colors.xml

@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <color name="colorPrimary">#1b82d2</color>       <!--toolbar-->
-    <color name="colorPrimaryDark">#1b82d2</color>   <!--status bar-->
-    <color name="colorAccent">#1b82d2</color>
-
-
-    <color name="av_bg_call_black">#281f1d</color>
-</resources>

+ 0 - 6
WebRTC/src/main/res/values/dimens.xml

@@ -1,6 +0,0 @@
-<resources>
-    <!-- Default screen margins, per the Android Design guidelines. -->
-    <dimen name="activity_horizontal_margin">16dp</dimen>
-    <dimen name="activity_vertical_margin">16dp</dimen>
-    <dimen name="dp_2">2dp</dimen>
-</resources>

+ 0 - 15
WebRTC/src/main/res/values/strings.xml

@@ -1,15 +0,0 @@
-<resources>
-    <string name="app_name">p2pChat</string>
-    <string name="action_settings">Settings</string>
-    <string name="action_create_room">Create Room</string>
-
-    <!--视频通话-->
-    <string name="av_waiting">正在等待对方接受邀请.</string>
-    <string name="av_audio_invite">邀请你进行语音通话</string>
-    <string name="av_video_invite">邀请你进行视频通话</string>
-
-    <string name="title_user">User</string>
-    <string name="title_room">Room</string>
-    <string name="title_setting">Setting</string>
-
-</resources>

+ 0 - 23
WebRTC/src/main/res/values/styles.xml

@@ -1,23 +0,0 @@
-<resources>
-
-    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
-        <item name="colorPrimary">@color/colorPrimary</item>
-        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
-        <item name="colorAccent">@color/colorAccent</item>
-    </style>
-
-    <style name="AppTheme.NoActionBar">
-        <item name="windowActionBar">false</item>
-        <item name="windowNoTitle">true</item>
-    </style>
-
-    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
-
-    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
-    <style name="AlertButtonBgWhite" parent="@style/Widget.AppCompat.Button.Colored">
-        <item name="android:background">@drawable/bg_btn_white</item>
-        <!--        <item name="minHeight">45dip</item>-->
-        <!--        <item name="minWidth">70dip</item>-->
-        <item name="android:layout_marginStart">15dip</item>
-    </style>
-</resources>

+ 2 - 2
build.gradle

@@ -32,7 +32,7 @@ buildscript {
     /**
      * SDK目标支持版本
      */
-    ext.target_sdk_version = 28
+    ext.target_sdk_version = 30
 
     /**
      * SDK编译版本
@@ -42,7 +42,7 @@ buildscript {
     /**
      * 支持库版本
      */
-    ext.support_library_version = "26.0.1"
+    ext.support_library_version = "26.1.0"
 
     /**
      * APP版本码

+ 1 - 1
common/build.gradle

@@ -221,7 +221,7 @@ dependencies {
     /**
      * 权限控制
      */
-    compile 'pub.devrel:easypermissions:0.2.0'
+    compile 'pub.devrel:easypermissions:3.0.0'
 
 
     compile 'com.github.pinguo-zhouwei:MZBannerView:v2.0.2'

+ 0 - 7
home/build.gradle

@@ -121,14 +121,7 @@ dependencies {
      */
     implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-
-//    compile project(':starRTC')
-//    compile project(':AmDemo_R')
-
     //web rtc
-    compile project(':webrtc')
-    //compile project(':libwebrtc')
-    compile project(':rtc-chat')
     compile project(':keepalive')
 }
 

+ 6 - 38
home/src/main/code/com/wdkl/ncs/android/component/home/activity/WatchHome2Activity.kt

@@ -19,10 +19,6 @@ import com.enation.javashop.net.engine.plugin.permission.RxPermissions
 import com.enation.javashop.utils.base.tool.CommonTool
 import com.enation.javashop.utils.base.widget.LoadingDialog
 import com.google.common.base.Strings
-import com.wdkl.core.consts.Urls
-import com.wdkl.core.socket.IUserState
-import com.wdkl.core.socket.SocketManager
-import com.wdkl.core.voip.VoipEvent
 import com.wdkl.ncs.android.component.home.BuildConfig
 import com.wdkl.ncs.android.component.home.R
 import com.wdkl.ncs.android.component.home.broadcast.BatteryBroadcastReceiver
@@ -49,7 +45,6 @@ import com.wdkl.ncs.android.middleware.tcp.NettyClient
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
 import com.wdkl.ncs.keepbackground.utils.SpManager
 import com.wdkl.ncs.keepbackground.work.DaemonEnv
-import com.wdkl.skywebrtc.SkyEngineKit
 import io.reactivex.Observable
 import kotlinx.android.synthetic.main.watch_activity_home2.*
 import kotlinx.android.synthetic.main.watch_activity_register.*
@@ -57,8 +52,7 @@ import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 
 //@Router(path = "/watch/home")
-class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivityHome2Binding>(), WatchHomeActivityContract.View, View.OnClickListener,
-       IUserState {
+class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivityHome2Binding>(), WatchHomeActivityContract.View, View.OnClickListener{
 
     var TAG = WatchHome2Activity::class.java.getSimpleName()
     //监听网络变化
@@ -81,10 +75,6 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
         loadingDialog = CommonTool.createLoadingDialog(this, R.layout.custom_loading,R.id.loadding_image)
         netOffLoadingDialog = CommonTool.createLoadingDialog(this, R.layout.netoff_loading,R.id.netoff_loading_image)
 
-        // 初始化信令
-        SkyEngineKit.init(VoipEvent())
-        SocketManager.getInstance().init(applicationContext)
-
         super.onCreate(savedInstanceState)
     }
 
@@ -152,7 +142,7 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
             }
         }
 
-        if (SocketManager.getInstance().connectFlag){
+        if (NettyClient.instance.isConnect()){
             watch_activity_register_layout.visibility = View.GONE
             watch_activity_home_linyout.visibility = View.VISIBLE
             sip_state_tv.setBackgroundColor(Color.parseColor("#00FFFF"))
@@ -171,7 +161,6 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
             }
 
             DaemonEnv.sendStopWorkBroadcast(this)
-            SocketManager.getInstance().unConnect()
 
             Constants.imei = Util.getIMEI(this)
             Log.i(TAG, "IMEI " + Util.getIMEI(this))
@@ -325,7 +314,6 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
             return
         }
         // 添加登录回调
-        SocketManager.getInstance().addUserStateCallback(this)
         presenter.getDeviceSettingData(""+Constants.partId)
 
         if (Strings.isNullOrEmpty(Constants.userName)){
@@ -377,8 +365,8 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
         }
     }
 
-    override fun userLogin() {
-        Log.i(TAG, "wdkl rtc 登录成功")
+    fun userLogin() {
+        Log.i(TAG, "连接成功")
 
         runOnUiThread(Runnable {
             tv_net_reconnect_text.visibility = View.GONE
@@ -388,30 +376,15 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
         })
     }
 
-    override fun userLogout() {
-        Log.w(TAG, "wdkl rtc 用户登出")
+    fun userLogout() {
+        Log.w(TAG, "网络断开")
 
         runOnUiThread(Runnable {
             tv_signal_strength.text = "网络断开"
             tv_net_reconnect_text.visibility = View.VISIBLE
             netOffLoadingDialog.show()
             sip_state_tv.setBackgroundColor(Color.parseColor("#FF0000"))
-            SocketManager.getInstance().unConnect()
         })
-//        if (SocketManager.getInstance().connectFlag) {
-//            reConnectRTC()
-//        }
-    }
-
-    fun reConnectRTC(){
-        if (SocketManager.getInstance().userState==0){
-            AppTool.Time.delay(5000){
-                SocketManager.getInstance().connect(Urls.WS, Constants.sipId, 0)
-                reConnectRTC()
-            }
-        } else {
-            return
-        }
     }
 
     override fun bindEvent() {
@@ -433,7 +406,6 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
         var count = 10
         Thread(Runnable {
             while (isUnRegister && count>0 && Strings.isNullOrEmpty(Constants.tcpServer)) {
-                SocketManager.getInstance().unConnect()
                 DaemonEnv.sendStopWorkBroadcast(this)
                 Log.i(TAG, "获取TCP服务器IP和端口")
                 runOnUiThread(Runnable {
@@ -480,10 +452,6 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
     }
 
     override fun destory() {
-        SpeechUtil.getInstance().release()
-        //注销webRTC
-        SocketManager.getInstance().unConnect()
-
         releaseReceiver()
         //停止服务
         DaemonEnv.sendStopWorkBroadcast(this)

+ 0 - 1
home/src/main/code/com/wdkl/ncs/android/component/home/adapter/TakeoverItemAdapter.kt

@@ -11,7 +11,6 @@ import com.enation.javashop.utils.base.tool.CommonTool
 import com.enation.javashop.utils.base.widget.LoadingDialog
 import com.google.common.base.Strings
 import com.google.gson.JsonObject
-import com.wdkl.core.socket.SocketManager
 import com.wdkl.ncs.android.component.home.R
 import com.wdkl.ncs.android.component.home.databinding.TakeoverItemBinding
 import com.wdkl.ncs.android.component.home.util.HandleTcpConnect

+ 2 - 9
home/src/main/code/com/wdkl/ncs/android/component/home/service/WdKeepAliveService.kt

@@ -10,8 +10,6 @@ import com.alibaba.fastjson.JSON
 import com.google.gson.FieldNamingPolicy
 import com.google.gson.Gson
 import com.google.gson.GsonBuilder
-import com.wdkl.core.consts.Urls
-import com.wdkl.core.socket.SocketManager
 import com.wdkl.ncs.android.component.home.activity.*
 import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
 import com.wdkl.ncs.android.component.home.util.*
@@ -99,6 +97,7 @@ class WdKeepAliveService : AbsWorkService() {
 
                     if (tcpModel.action == TcpAction.VoiceAction.SUCCESS) {  //拨出成功
                         Log.i(TAG, "拨出成功 ${interactionVO.fromMemberName} ${interactionVO.id}")
+
                         DeviceChannel.calling = true
                         intent.setClass(this, WebRTCVoipAudioActivity::class.java)
                         intent.putExtra("targetId", interactionVO?.toSipId)
@@ -106,6 +105,7 @@ class WdKeepAliveService : AbsWorkService() {
                         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                         intent.putExtra(WebRTCVoipAudioActivity().ACTION, WebRTCVoipAudioActivity().CALL)
                         startActivity(intent)
+
                     } else if (tcpModel.action == TcpAction.VoiceAction.CALL) {  //有来电
                         DeviceChannel.calling = true
                         DeviceChannel.callId = if (interactionVO.fromDeviceId.equals(Constants.deviceId)) interactionVO.toDeviceId else interactionVO.fromDeviceId
@@ -321,13 +321,6 @@ class WdKeepAliveService : AbsWorkService() {
             } else if (!NettyClient.instance.isConnect()){
                 Log.w(TAG,"TCP.进入重新连接")
                 HandleTcpConnect.instance.tcpReConnect()
-            } else {
-                if (SocketManager.getInstance().connectFlag) {
-                    EventBus.getDefault().post(MessageEvent(TcpModel(), Constants.EVENT_RTC_STATE))
-                } else {
-                    SocketManager.getInstance().unConnect()
-                    SocketManager.getInstance().connect(Urls.WS, Constants.sipId, 0)
-                }
             }
         } else {
             Thread(Runnable {

+ 1 - 16
home/src/main/code/com/wdkl/ncs/android/component/home/util/HandleTcpConnect.kt

@@ -2,12 +2,9 @@ package com.wdkl.ncs.android.component.home.util
 
 import android.annotation.SuppressLint
 import android.util.Log
-import com.wdkl.core.consts.Urls
-import com.wdkl.core.socket.SocketManager
 import com.wdkl.ncs.android.component.nursehome.common.Constants
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.middleware.tcp.NettyClient
-import io.reactivex.Observable
 
 class HandleTcpConnect {
     val TAG = HandleTcpConnect::class.simpleName
@@ -22,9 +19,7 @@ class HandleTcpConnect {
         Log.d(TAG, "TCP.开始初始连接")
         NettyClient.instance.connect(Constants.tcpServer,Constants.tcpPort,Constants.heartBeat.toLong()).subscribe {
             if (it){
-                Log.d(TAG, "TCP.连接成功,开始连接RTC")
-                SocketManager.getInstance().unConnect()
-                SocketManager.getInstance().connect(Urls.WS,Constants.sipId,0)
+                Log.d(TAG, "TCP.连接成功")
             } else {
                 Log.e(TAG, "TCP.连接失败")
             }
@@ -37,11 +32,6 @@ class HandleTcpConnect {
         NettyClient.instance.reConnect().subscribe {
             if (it){
                 Log.d(TAG, "TCP.重连成功")
-                if (SocketManager.getInstance().userState!=1) {
-                    Log.d(TAG, "TCP.RTC登出状态,重新连接")
-                    SocketManager.getInstance().unConnect()
-                    SocketManager.getInstance().connect(Urls.WS, Constants.sipId, 0)
-                }
             } else {
                 Log.e(TAG, "TCP.重连失败")
             }
@@ -55,11 +45,6 @@ class HandleTcpConnect {
         NettyClient.instance.reConnect().subscribe{
             if (it){
                 Log.d(TAG, "服务重连成功")
-                if (SocketManager.getInstance().userState!=1) {
-                    Log.d(TAG, "TCP.RTC登出状态,重新连接")
-                    SocketManager.getInstance().unConnect()
-                    SocketManager.getInstance().connect(Urls.WS, Constants.sipId, 0)
-                }
                 showMessage("重连成功,请重试")
             } else {
                 Log.d(TAG, "服务重连失败")

+ 0 - 1
home/src/main/code/com/wdkl/ncs/android/component/home/util/NetWorkChangeReceiver.kt

@@ -8,7 +8,6 @@ import android.net.Network
 import android.net.NetworkInfo
 import android.os.Build
 import android.util.Log
-import com.blankj.utilcode.util.NetworkUtils
 import com.wdkl.ncs.android.middleware.tcp.NettyClient
 
 class NetWorkChangeReceiver : BroadcastReceiver() {

+ 1 - 0
janus/.gitignore

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

+ 48 - 0
janus/build.gradle

@@ -0,0 +1,48 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 30
+
+    defaultConfig {
+        applicationId "com.wdkl.rtc"
+        minSdkVersion 23
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+    buildToolsVersion '26.0.2'
+}
+
+dependencies {
+    implementation fileTree(dir: "libs", include: ["*.jar"])
+    implementation 'com.google.android.material:material:1.2.1'
+    implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+    androidTestImplementation 'android.test.espresso:espresso-core:2.2.2'
+
+    api 'com.android.support:support-annotations:26.1.0'
+    //noinspection GradleCompatible
+    api 'com.android.support:appcompat-v7:26.1.0'
+
+    implementation 'org.webrtc:google-webrtc:1.0.32006'
+
+    implementation 'com.squareup.okhttp3:okhttp:3.8.0'
+
+    compile 'pub.devrel:easypermissions:3.0.0'
+    api 'org.greenrobot:eventbus:3.0.0'
+    api 'com.blankj:utilcodex:1.30.5'
+}

+ 1 - 1
libwebrtc/proguard-rules.pro

@@ -18,4 +18,4 @@
 
 # If you keep the line number information, uncomment this to
 # hide the original source file name.
-#-renamesourcefileattribute SourceFile
+#-renamesourcefileattribute SourceFile

+ 26 - 0
janus/src/androidTest/java/com/wdkl/rtc/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.wdkl.rtc;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.lesliefang.janusdemo2", appContext.getPackageName());
+    }
+}

+ 37 - 0
janus/src/main/AndroidManifest.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.wdkl.rtc">
+
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:networkSecurityConfig="@xml/network_security_config"
+        android:theme="@style/AppTheme">
+        <activity android:name="com.wdkl.rtc.MainActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".ui.CallSingleActivity"
+            android:showOnLockScreen="true"
+            android:showWhenLocked="true">
+            <intent-filter>
+                <action android:name="${applicationId}.kit.voip.single" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>

+ 92 - 0
janus/src/main/java/com/wdkl/rtc/MainActivity.java

@@ -0,0 +1,92 @@
+package com.wdkl.rtc;
+
+import android.Manifest;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.wdkl.rtc.rtc.WebRTCEngine;
+import com.wdkl.rtc.ui.CallSingleActivity;
+
+import java.math.BigInteger;
+
+import pub.devrel.easypermissions.EasyPermissions;
+
+public class MainActivity extends AppCompatActivity {
+    String[] perms = {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
+    EditText etUserName;
+    Button btnStart;
+    Button btnJoin;
+    CheckBox cbAudioOnly;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main2);
+        etUserName = findViewById(R.id.et_room_id);
+        btnStart = findViewById(R.id.btn_start);
+        btnJoin = findViewById(R.id.btn_join);
+        cbAudioOnly = findViewById(R.id.cb_audio_only);
+
+        etUserName.setText("12345678");
+
+        btnStart.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                int roomId = Integer.parseInt(etUserName.getText().toString().trim());
+                if (etUserName.getText().toString().trim().isEmpty()) {
+                    Toast.makeText(MainActivity.this, "房间号", Toast.LENGTH_SHORT).show();
+                    return;
+                }
+                if (!EasyPermissions.hasPermissions(MainActivity.this, perms)) {
+                    EasyPermissions.requestPermissions(MainActivity.this, "需要相机和录音权限",
+                            100, perms);
+                } else {
+//                    //启动 activity
+                    Intent intent = new Intent(MainActivity.this, CallSingleActivity.class);
+                    intent.putExtra(CallSingleActivity.EXTRA_ROOM_ID,roomId);
+                    intent.putExtra(CallSingleActivity.EXTRA_MO,true);
+                    intent.putExtra(CallSingleActivity.EXTRA_AUDIO_ONLY,cbAudioOnly.isChecked());
+                    //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    startActivity(intent);
+//                    CallSingleActivity.openActivity(MainActivity.this,roomId,true,false,false);
+                }
+            }
+        });
+
+        btnJoin.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                int roomId = Integer.parseInt(etUserName.getText().toString().trim());
+                if (etUserName.getText().toString().trim().isEmpty()) {
+                    Toast.makeText(MainActivity.this, "房间号", Toast.LENGTH_SHORT).show();
+                    return;
+                }
+
+                if (!EasyPermissions.hasPermissions(MainActivity.this, perms)) {
+                    EasyPermissions.requestPermissions(MainActivity.this, "需要相机和录音权限",
+                            100, perms);
+                } else {
+                    //启动 activity
+                    Intent intent = new Intent(MainActivity.this, CallSingleActivity.class);
+                    intent.putExtra(CallSingleActivity.EXTRA_ROOM_ID,roomId);
+                    intent.putExtra(CallSingleActivity.EXTRA_MO,false);
+                    intent.putExtra(CallSingleActivity.EXTRA_AUDIO_ONLY,cbAudioOnly.isChecked());
+                    startActivity(intent);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
+    }
+}

+ 1 - 1
WebRTC/src/main/java/com/wdkl/core/ui/event/MsgEvent.java

@@ -1,4 +1,4 @@
-package com.wdkl.core.ui.event;
+package com.wdkl.rtc.entity;
 
 public class MsgEvent<T> {
     private int code;

+ 54 - 0
janus/src/main/java/com/wdkl/rtc/entity/Publisher.java

@@ -0,0 +1,54 @@
+package com.wdkl.rtc.entity;
+
+import java.math.BigInteger;
+
+/**
+ */
+public class Publisher {
+    private BigInteger id;
+    private String display;
+
+    private BigInteger handleId;
+
+    public Publisher() {
+
+    }
+
+    public Publisher(BigInteger id, String display) {
+        this.id = id;
+        this.display = display;
+    }
+
+    public BigInteger getId() {
+        return id;
+    }
+
+    public void setId(BigInteger id) {
+        this.id = id;
+    }
+
+    public String getDisplay() {
+        return display;
+    }
+
+    public void setDisplay(String display) {
+        this.display = display;
+    }
+
+    public BigInteger getHandleId() {
+        return handleId;
+    }
+
+    public void setHandleId(BigInteger handleId) {
+        this.handleId = handleId;
+    }
+
+    @Override
+    public String toString() {
+        return "Publisher{" +
+                "id=" + id +
+                ", display='" + display + '\'' +
+                ", handleId=" + handleId +
+                '}';
+    }
+}

+ 68 - 0
janus/src/main/java/com/wdkl/rtc/entity/Room.java

@@ -0,0 +1,68 @@
+package com.wdkl.rtc.entity;
+
+import java.math.BigInteger;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ */
+public class Room {
+    private BigInteger id;
+
+    public Room() {
+
+    }
+
+    public Room(BigInteger id) {
+        this.id = id;
+    }
+
+    private Set<Publisher> publishers = new HashSet<>();
+
+    public BigInteger getId() {
+        return id;
+    }
+
+    public void setId(BigInteger id) {
+        this.id = id;
+    }
+
+    public Set<Publisher> getPublishers() {
+        return publishers;
+    }
+
+    public void addPublisher(Publisher publisher) {
+        Iterator<Publisher> it = publishers.iterator();
+        boolean found = false;
+        while (it.hasNext()) {
+            Publisher next = it.next();
+            if (next.getId().equals(publisher.getId())) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            publishers.add(publisher);
+        }
+    }
+
+    public Publisher findPublisherById(BigInteger id) {
+        for (Publisher next : publishers) {
+            if (next.getId().equals(id)) {
+                return next;
+            }
+        }
+        return null;
+    }
+
+    public void removePublisherById(BigInteger id) {
+        Iterator<Publisher> it = publishers.iterator();
+        while (it.hasNext()) {
+            Publisher next = it.next();
+            if (next.getId().equals(id)) {
+                it.remove();
+            }
+        }
+    }
+}

+ 820 - 0
janus/src/main/java/com/wdkl/rtc/janus/JanusClient.java

@@ -0,0 +1,820 @@
+package com.wdkl.rtc.janus;
+
+import android.util.Log;
+
+import com.wdkl.rtc.util.EnumType;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.webrtc.IceCandidate;
+import org.webrtc.SessionDescription;
+
+import java.math.BigInteger;
+import java.util.Random;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 参考1:https://blog.csdn.net/Java_lilin/article/details/104007291
+ * 参考2:https://github.com/benwtrent/janus-gateway-android
+ * 参考3:https://zhuanlan.zhihu.com/p/149324861?utm_source=wechat_session
+ */
+public class JanusClient implements WebSocketChannel.WebSocketCallback {
+    private static final String TAG = "JanusClient";
+    private ConcurrentHashMap<BigInteger, PluginHandle> attachedPlugins = new ConcurrentHashMap<>();
+    private ConcurrentHashMap<String, Transaction> transactions = new ConcurrentHashMap<>();
+    private BigInteger sessionId = null;
+    private BigInteger currentHandleId = null;
+    private JanusCallback janusCallback;
+
+    private volatile boolean isKeepAliveRunning;
+    private Thread keepAliveThread;
+
+    private String janusUrl;
+    private WebSocketChannel webSocketChannel;
+
+    private EnumType.CallState callState;
+    private EnumType.CallEndReason endReason;
+    private EnumType.RefuseType refuseType;
+
+    private BigInteger roomId;
+    private BigInteger userId;
+    public static String remoteUsername = "";
+
+    public static final int ERROR_CREATE_ROOM = 0x01;
+    public static final int ERROR_ON_MESSAGE = 0x02;
+
+    public JanusClient(String janusUrl, BigInteger userId) {
+        this.janusUrl = janusUrl;
+        this.userId = userId;
+        webSocketChannel = new WebSocketChannel();
+        webSocketChannel.setWebSocketCallback(this);
+    }
+
+    public void setJanusCallback(JanusCallback janusCallback) {
+        this.janusCallback = janusCallback;
+    }
+
+    public BigInteger getSessionId() {
+        return sessionId;
+    }
+
+    public BigInteger getCurrentHandleId() {
+        return currentHandleId;
+    }
+
+    public EnumType.CallState getCallState() {
+        return callState;
+    }
+
+    public void setCallState(EnumType.CallState callState) {
+        this.callState = callState;
+    }
+
+    public EnumType.CallEndReason getEndReason() {
+        return endReason;
+    }
+
+    public void setEndReason(EnumType.CallEndReason endReason) {
+        this.endReason = endReason;
+    }
+
+    public EnumType.RefuseType getRefuseType() {
+        return refuseType;
+    }
+
+    public void setRefuseType(EnumType.RefuseType refuseType) {
+        this.refuseType = refuseType;
+    }
+
+    public BigInteger getRoomId() {
+        return roomId;
+    }
+
+    public void setRoomId(BigInteger roomId) {
+        this.roomId = roomId;
+    }
+
+    public void connect() {
+        webSocketChannel.connect(janusUrl);
+    }
+
+    public void disConnect() {
+        stopKeepAliveTimer();
+        if (webSocketChannel != null) {
+            webSocketChannel.close();
+            webSocketChannel = null;
+        }
+    }
+
+    /**
+     * 创建session,并得到反馈
+     * 发出
+     * {
+     *         "janus" : "create",
+     *         "transaction" : "<random alphanumeric string>"
+     * }
+     * 成功后的反馈
+     * {
+     *         "janus" : "success",
+     *         "transaction" : "<same as the request>",
+     *         "data" : {
+     *                 "id" : <unique integer session ID>
+     *         }
+     * }
+     * 错误时的反馈
+     * error: a JSON object containing two fields:
+     *      code: a numeric error code, as defined in apierror.h;
+     *      reason: a verbose string describing the cause of the failure.
+     *
+     * {
+     *         "janus" : "error",
+     *         "transaction" : "<same as the request>",
+     *         "error" : {
+     *                 "code" : 458
+     *                 "reason" : "Could not find session 12345678"
+     *         }
+     * }
+     *
+     * Once you've created a session, a new endpoint you can use is created in the server. Specifically, the new endpoint is constructed by concatenating the server root and the session identifier you've been returned (e.g., /janus/12345678).
+     *
+     * This endpoint can be used in two different ways:
+     *
+     * using a parameter-less GET request to the endpoint, you'll issue a long-poll request to be notified about events and incoming messages from this session;
+     * using a POST request to send JSON messages, you'll interact with the session itself.
+     */
+    private void createSession() {
+        //先声明回调
+        String tid = randomString(12);
+        transactions.put(tid, new Transaction(tid) {
+            @Override
+            public void onSuccess(JSONObject msg) throws Exception {
+                JSONObject data = msg.getJSONObject("data");
+                sessionId = new BigInteger(data.getString("id"));
+                startKeepAliveTimer();
+                if (janusCallback != null) {
+                    janusCallback.onCreateSession(sessionId);
+                }
+            }
+        });
+        //再发送命令
+        try {
+            JSONObject obj = new JSONObject();
+            obj.put("janus", "create");
+            obj.put("transaction", tid);
+            webSocketChannel.sendMessage(obj.toString());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 释放session
+     */
+    public void destroySession() {
+        String tid = randomString(12);
+        transactions.put(tid, new Transaction(tid) {
+            @Override
+            public void onSuccess(JSONObject msg) throws Exception {
+                stopKeepAliveTimer();
+                if (janusCallback != null) {
+                    janusCallback.onDestroySession(sessionId);
+                }
+            }
+        });
+        try {
+            JSONObject obj = new JSONObject();
+            obj.put("janus", "destroy");
+            obj.put("transaction", tid);
+            obj.put("session_id", sessionId);
+            webSocketChannel.sendMessage(obj.toString());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Interacting with the session。建立session后,与session进行交互,得到handle id
+     * @param pluginName
+     */
+    public void attachPlugin(String pluginName) {
+        String tid = randomString(12);
+        transactions.put(tid, new Transaction(tid) {
+            @Override
+            public void onSuccess(JSONObject msg) throws Exception {
+                JSONObject data = msg.getJSONObject("data");
+                BigInteger handleId = new BigInteger(data.getString("id"));
+                currentHandleId = handleId;
+                if (janusCallback != null) {
+                    janusCallback.onAttached(handleId);
+                }
+                PluginHandle handle = new PluginHandle(handleId);
+                attachedPlugins.put(handleId, handle);
+            }
+        });
+
+        try {
+            JSONObject obj = new JSONObject();
+            obj.put("janus", "attach");
+            obj.put("transaction", tid);
+            obj.put("plugin", pluginName);
+            obj.put("session_id", sessionId);
+            webSocketChannel.sendMessage(obj.toString());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *
+     *
+     * attach 到发布者的 handler 上,准备接收视频流
+     * 每个发布者都要 attach 一遍,然后协商 sdp, SFU
+     *
+     * @param feedId
+     */
+    public void subscribeAttach(BigInteger feedId) {
+        String tid = randomString(12);
+        transactions.put(tid, new Transaction(tid, feedId) {
+            @Override
+            public void onSuccess(JSONObject msg, BigInteger feedId) throws Exception {
+                JSONObject data = msg.getJSONObject("data");
+                //其它发布者的 handleId
+                BigInteger handleId = new BigInteger(data.getString("id"));
+                if (janusCallback != null) {
+                    janusCallback.onSubscribeAttached(handleId, feedId);
+                }
+                PluginHandle handle = new PluginHandle(handleId);
+                attachedPlugins.put(handleId, handle);
+            }
+        });
+
+        try {
+            JSONObject obj = new JSONObject();
+            obj.put("janus", "attach");
+            obj.put("transaction", tid);
+            obj.put("plugin", "janus.plugin.videoroom");
+            obj.put("session_id", sessionId);
+            webSocketChannel.sendMessage(obj.toString());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *给 plugin 发送消息
+     *
+     * @param handleId
+     * @param sdp webrtc session description
+     */
+    public void createOffer(BigInteger handleId, SessionDescription sdp, Boolean videoOn) {
+        JSONObject message = new JSONObject();
+        try {
+            JSONObject publish = new JSONObject();
+            publish.putOpt("audio", true);
+            publish.putOpt("video", videoOn);
+
+            JSONObject jsep = new JSONObject();
+            jsep.putOpt("type", sdp.type);
+            jsep.putOpt("sdp", sdp.description);
+
+            message.putOpt("janus", "message");
+            message.putOpt("body", publish);
+            message.putOpt("jsep", jsep);
+            message.putOpt("transaction", randomString(12));
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", handleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    /**
+     * 开始订阅
+     *
+     * @param subscriptionHandleId
+     * @param sdp
+     */
+    public void subscriptionStart(BigInteger subscriptionHandleId, SessionDescription sdp) {
+        JSONObject message = new JSONObject();
+        try {
+            JSONObject body = new JSONObject();
+            body.putOpt("request", "start");
+            body.putOpt("room", roomId);
+
+            message.putOpt("janus", "message");
+            message.putOpt("body", body);
+            message.putOpt("transaction", randomString(12));
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", subscriptionHandleId);
+
+            if (sdp != null) {
+                JSONObject jsep = new JSONObject();
+                jsep.putOpt("type", sdp.type);
+                jsep.putOpt("sdp", sdp.description);
+                message.putOpt("jsep", jsep);
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    public void publish(BigInteger handleId, SessionDescription sdp, Boolean videoOn) {
+        JSONObject message = new JSONObject();
+        try {
+            JSONObject publish = new JSONObject();
+            //你也可以用configure请求代替publish。两者的功能在发布上是等效的,但从语义的角度来看,publish是发布时要发送的正确消息。configure请求也可以用于更新发布者会话的某些属性,在这种情况下,就不能用publish请求了
+            publish.putOpt("request", "publish");
+            publish.putOpt("audio", true);
+            publish.putOpt("video", videoOn);
+
+            JSONObject jsep = new JSONObject();
+            jsep.putOpt("type", sdp.type);
+            jsep.putOpt("sdp", sdp.description);
+
+            message.putOpt("janus", "message");
+            message.putOpt("body", publish);
+            message.putOpt("jsep", jsep);
+            message.putOpt("transaction", randomString(12));
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", handleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    /**
+     * 订阅
+     *
+     * @param feedId 要订阅的ID
+     */
+    public void subscribe(BigInteger subscriptionHandleId, BigInteger feedId) {
+        JSONObject message = new JSONObject();
+        JSONObject body = new JSONObject();
+        try {
+            body.putOpt("ptype", "subscriber");
+            body.putOpt("request", "join");
+            body.putOpt("room", roomId);
+            body.putOpt("feed", feedId);
+
+            message.put("body", body);
+            message.putOpt("janus", "message");
+            message.putOpt("transaction", randomString(12));
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", subscriptionHandleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    public void trickleCandidate(BigInteger handleId, IceCandidate iceCandidate) {
+        JSONObject candidate = new JSONObject();
+        JSONObject message = new JSONObject();
+        try {
+            candidate.putOpt("candidate", iceCandidate.sdp);
+            candidate.putOpt("sdpMid", iceCandidate.sdpMid);
+            candidate.putOpt("sdpMLineIndex", iceCandidate.sdpMLineIndex);
+
+            message.putOpt("janus", "trickle");
+            message.putOpt("candidate", candidate);
+            message.putOpt("transaction", randomString(12));
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", handleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    public void trickleCandidateComplete(BigInteger handleId) {
+        JSONObject candidate = new JSONObject();
+        JSONObject message = new JSONObject();
+        try {
+            candidate.putOpt("completed", true);
+
+            message.putOpt("janus", "trickle");
+            message.putOpt("candidate", candidate);
+            message.putOpt("transaction", randomString(12));
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", handleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    /**
+     * 创建房间
+     * @param handleId
+     * @param newRoomId
+     *
+     * {
+     *         "request" : "create",
+     *         "room" : <unique numeric ID, optional, chosen by plugin if missing>,
+     *         "permanent" : <true|false, whether the room should be saved in the config file, default=false>,
+     *         "description" : "<pretty name of the room, optional>",
+     *         "secret" : "<password required to edit/destroy the room, optional>",
+     *         "pin" : "<password required to join the room, optional>",
+     *         "is_private" : <true|false, whether the room should appear in a list request>,
+     *         "allowed" : [ array of string tokens users can use to join this room, optional],
+     *         ...
+     * }
+     *
+     * 反馈
+     *
+     * {
+     *     "janus": "success",
+     *     "session_id": 6421975129252707,
+     *     "transaction": "m2D5tESZ3fwb",
+     *     "sender": 537399609431468,
+     *     "plugindata": {
+     *         "plugin": "janus.plugin.videoroom",
+     *         "data": {
+     *             "videoroom": "created",
+     *             "room": 12345678,
+     *             "permanent": false
+     *         }
+     *     }
+     * }
+     *
+     * {
+     *        "janus": "success",
+     *        "session_id": 1359598870403518,
+     *        "transaction": "4mC6b30kX0sr",
+     *        "sender": 2692286927487266,
+     *        "plugindata": {
+     *           "plugin": "janus.plugin.videoroom",
+     *           "data": {
+     *              "videoroom": "event",
+     *              "error_code": 427,
+     *              "error": "Room 12345678 already exists"
+     *           }
+     *        }
+     *     }
+     */
+    public void createRoom(BigInteger handleId, BigInteger newRoomId){
+        roomId = newRoomId;
+
+        String tid = randomString(12);
+        transactions.put(tid, new Transaction(tid) {
+            @Override
+            public void onSuccess(JSONObject msg) throws Exception {
+                JSONObject data = msg.getJSONObject("plugindata").getJSONObject("data");
+                if (data.getString("videoroom").equals("event")){
+                    if (data.has("error")) {
+                        if (data.getInt("error_code") == 427) {
+                            //拨打
+                            if (EnumType.CallState.Outgoing == callState) {
+                                destroyRoom(handleId, new DestroyRoomCallback() {
+                                    @Override
+                                    public void onSuccess() {
+                                        createRoom(handleId, newRoomId);
+                                    }
+
+                                    @Override
+                                    public void onFailed() {
+                                        janusCallback.onError(ERROR_CREATE_ROOM,"创建房间失败");
+                                    }
+                                });
+                            }
+                            //接收
+                            else if (EnumType.CallState.Incoming == callState) {
+                                janusCallback.onCreateRoom(handleId);
+                            }
+                        } else {
+                            janusCallback.onError(ERROR_CREATE_ROOM,"创建房间失败");
+                        }
+                    }
+                } else if (data.getString("videoroom").equals("created")){
+                    janusCallback.onCreateRoom(handleId);
+                }
+            }
+
+            @Override
+            public void onError() {
+                janusCallback.onError(ERROR_CREATE_ROOM,"创建房间失败");
+            }
+        });
+
+        JSONObject message = new JSONObject();
+        JSONObject body = new JSONObject();
+        try {
+            body.putOpt("request", "create");
+            body.putOpt("room", newRoomId);
+            message.put("body", body);
+
+            message.putOpt("janus", "message");
+            message.putOpt("transaction", tid);
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", handleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    /**
+     *
+     * @param handleId
+     *
+     * "videoroom" : "destroyed",
+     */
+    public void destroyRoom(BigInteger handleId, DestroyRoomCallback destroyRoomCallback){
+        String tid = randomString(12);
+        transactions.put(tid, new Transaction(tid) {
+            @Override
+            public void onSuccess(JSONObject msg) throws Exception {
+                JSONObject data = msg.getJSONObject("plugindata").getJSONObject("data");
+                if (destroyRoomCallback!=null) {
+                    if (data.getString("videoroom").equals("destroyed")) {
+                        destroyRoomCallback.onSuccess();
+                    } else {
+                        destroyRoomCallback.onFailed();
+                    }
+                }
+            }
+
+            @Override
+            public void onError() {
+                if (destroyRoomCallback!=null) {
+                    destroyRoomCallback.onFailed();
+                }
+            }
+        });
+
+        JSONObject message = new JSONObject();
+        JSONObject body = new JSONObject();
+        try {
+            body.putOpt("request", "destroy");
+            body.putOpt("room", roomId);
+            message.put("body", body);
+
+            message.putOpt("janus", "message");
+            message.putOpt("transaction", tid);
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", handleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    //给插件,发送消息,得到ack和event两个消息
+    public void joinRoom(BigInteger handleId, String displayName) {
+        JSONObject message = new JSONObject();
+        JSONObject body = new JSONObject();
+        try {
+            body.putOpt("display", displayName);
+            body.putOpt("ptype", "publisher");
+            body.putOpt("request", "join");
+            body.putOpt("id",userId); //发布者id,我司系统 sip_id
+            body.putOpt("room", roomId);
+            message.put("body", body);
+
+            message.putOpt("janus", "message");
+            message.putOpt("transaction", randomString(12));
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", handleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    public void leaveRoom(){
+        JSONObject message = new JSONObject();
+        JSONObject body = new JSONObject();
+        try {
+            body.putOpt("request", "leave");
+            message.put("body", body);
+
+            message.putOpt("janus", "message");
+            message.putOpt("transaction", randomString(12));
+            message.putOpt("session_id", sessionId);
+            message.putOpt("handle_id", currentHandleId);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        webSocketChannel.sendMessage(message.toString());
+    }
+
+    @Override
+    public void onOpen() {
+        if (sessionId==null) {
+            createSession();
+        }
+    }
+
+    @Override
+    public void onMessage(String message) {
+        //Log.d(TAG, "收到消息》》》" + message);
+        try {
+            JSONObject obj = new JSONObject(message);
+            JanusMessageType type = JanusMessageType.fromString(obj.getString("janus"));
+            String transaction = null;
+            BigInteger sender = null;
+            if (obj.has("transaction")) {
+                transaction = obj.getString("transaction");
+            }
+            //是插件 handleId
+            if (obj.has("sender")) {
+                sender = new BigInteger(obj.getString("sender"));
+            }
+            PluginHandle handle = null;
+            if (sender != null) {
+                handle = attachedPlugins.get(sender);
+            }
+            switch (type) {
+                case keepalive:
+                    break;
+                case ack:
+                    break;
+                case success:
+                    if (transaction != null) {
+                        Transaction cb = transactions.get(transaction);
+                        if (cb != null) {
+                            try {
+                                if (cb.getFeedId() != null) {
+                                    cb.onSuccess(obj, cb.getFeedId());
+                                } else {
+                                    cb.onSuccess(obj);
+                                }
+                                transactions.remove(transaction);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    }
+                    break;
+                case error: {
+                    if (transaction != null) {
+                        Transaction cb = transactions.get(transaction);
+                        if (cb != null) {
+                            cb.onError();
+                            transactions.remove(transaction);
+                        }
+                    }
+                    break;
+                }
+                case hangup: {
+                    if (handle != null) {
+                        if (janusCallback != null) {
+                            janusCallback.onHangup(handle.getHandleId());
+                        }
+                    }
+                    break;
+                }
+                case detached: {
+                    if (handle != null) {
+                        if (janusCallback != null) {
+                            janusCallback.onDetached(handle.getHandleId());
+                        }
+                    }
+                    break;
+                }
+                case event: {   //不进行 transaction 处理
+                    if (handle != null) {
+                        JSONObject plugin_data = null;
+                        if (obj.has("plugindata")) {
+                            plugin_data = obj.getJSONObject("plugindata");
+                        }
+                        if (plugin_data != null) {
+                            JSONObject data = null;
+                            JSONObject jsep = null;
+                            if (plugin_data.has("data")) {
+                                data = plugin_data.getJSONObject("data");
+                            }
+                            if (obj.has("jsep")) {
+                                jsep = obj.getJSONObject("jsep");
+                            }
+                            if (janusCallback != null) {
+                                janusCallback.onMessage(sender, handle.getHandleId(), data, jsep);
+                            }
+                        }
+                    }
+                }
+                case trickle:
+                    if (handle != null) {
+                        if (obj.has("candidate")) {
+                            JSONObject candidate = obj.getJSONObject("candidate");
+                            if (janusCallback != null) {
+                                janusCallback.onIceCandidate(handle.getHandleId(), candidate);
+                            }
+                        }
+                    }
+                    break;
+                case destroy:
+                    if (janusCallback != null) {
+                        janusCallback.onDestroySession(sessionId);
+                    }
+                    break;
+                case slowlink:
+                    break;
+            }
+        } catch (JSONException ex) {
+            if (janusCallback != null) {
+                janusCallback.onError(ERROR_ON_MESSAGE,ex.getMessage());
+            }
+        }
+    }
+
+    /**
+     * The long-poll request has a 30 seconds timeout. If it has no event to report, a simple keep-alive message will be triggered:
+     */
+    private void startKeepAliveTimer() {
+        isKeepAliveRunning = true;
+        keepAliveThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                while (isKeepAliveRunning && !Thread.interrupted()) {
+                    try {
+                        Thread.sleep(25*1000);
+                    } catch (InterruptedException ex) {
+                        ex.printStackTrace();
+                    }
+                    if (webSocketChannel != null && webSocketChannel.isConnected()) {
+                        JSONObject obj = new JSONObject();
+                        try {
+                            obj.put("janus", "keepalive");
+                            obj.put("session_id", sessionId);
+                            obj.put("transaction", randomString(12));
+                            webSocketChannel.sendMessage(obj.toString());
+                        } catch (JSONException e) {
+                            e.printStackTrace();
+                        }
+                    } else {
+                        Log.e(TAG, "keepAlive failed websocket is null or not connected");
+                    }
+                }
+                Log.d(TAG, "keepAlive thread stopped");
+            }
+        }, "KeepAlive");
+        keepAliveThread.start();
+    }
+
+    private void stopKeepAliveTimer() {
+        isKeepAliveRunning = false;
+        if (keepAliveThread != null) {
+            keepAliveThread.interrupt();
+        }
+    }
+
+    @Override
+    public void onClosed() {
+        stopKeepAliveTimer();
+    }
+
+    public String randomString(int length) {
+        String str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+        Random random = new Random();
+        StringBuilder sb = new StringBuilder(length);
+        for (int i = 0; i < length; i++) {
+            sb.append(str.charAt(random.nextInt(str.length())));
+        }
+        return sb.toString();
+    }
+
+    public interface DestroyRoomCallback{
+        void onSuccess();
+        void onFailed();
+    }
+
+    public interface JanusCallback {
+        void onCreateSession(BigInteger sessionId);
+
+        void onCreateRoom(BigInteger handleId);
+
+        void onAttached(BigInteger handleId);
+
+        /**
+         * 订阅回调
+         *
+         * @param subscribeHandleId 订阅HandlerId
+         * @param feedId            订阅 feedId
+         */
+        void onSubscribeAttached(BigInteger subscribeHandleId, BigInteger feedId);
+
+        void onDetached(BigInteger handleId);
+
+        void onHangup(BigInteger handleId);
+
+        void onMessage(BigInteger sender, BigInteger handleId, JSONObject msg, JSONObject jsep);
+
+        void onIceCandidate(BigInteger handleId, JSONObject candidate);
+
+        void onDestroySession(BigInteger sessionId);
+
+        void onError(int errorCode, String error);
+    }
+}

+ 33 - 0
janus/src/main/java/com/wdkl/rtc/janus/JanusMessageType.java

@@ -0,0 +1,33 @@
+package com.wdkl.rtc.janus;
+
+public enum JanusMessageType {
+    message,
+    trickle,
+    detach,
+    destroy,
+    keepalive,
+    create,
+    attach,
+    event,
+    error,
+    ack,
+    success,
+    webrtcup,
+    hangup,
+    detached,
+    media,
+    slowlink;
+
+    @Override
+    public String toString() {
+        return name();
+    }
+
+    public boolean EqualsString(String type) {
+        return this.toString().equals(type);
+    }
+
+    public static JanusMessageType fromString(String string) {
+        return (JanusMessageType) valueOf(JanusMessageType.class, string.toLowerCase());
+    }
+}

+ 19 - 0
janus/src/main/java/com/wdkl/rtc/janus/PluginHandle.java

@@ -0,0 +1,19 @@
+package com.wdkl.rtc.janus;
+
+import java.math.BigInteger;
+
+public class PluginHandle {
+    private BigInteger handleId;
+
+    public PluginHandle(BigInteger handleId) {
+        this.handleId = handleId;
+    }
+
+    public BigInteger getHandleId() {
+        return handleId;
+    }
+
+    public void setHandleId(BigInteger handleId) {
+        this.handleId = handleId;
+    }
+}

+ 47 - 0
janus/src/main/java/com/wdkl/rtc/janus/Transaction.java

@@ -0,0 +1,47 @@
+package com.wdkl.rtc.janus;
+
+import org.json.JSONObject;
+
+import java.math.BigInteger;
+
+/**
+ * a random string that the client can use to match incoming messages from the server (since, as explained in the Plugins documentation, all messages are asynchronous).
+ */
+public class Transaction {
+    private String tid;
+
+    /**
+     * 如果有 feed 说明这是一个订阅的 Transaction
+     */
+    private BigInteger feedId;
+
+    public Transaction(String tid) {
+        this.tid = tid;
+    }
+
+    public Transaction(String tid, BigInteger feedId) {
+        this.tid = tid;
+        this.feedId = feedId;
+    }
+
+    public void onError() {
+    }
+
+    public void onSuccess(JSONObject data) throws Exception {
+    }
+
+    public void onSuccess(JSONObject data, BigInteger feed) throws Exception {
+    }
+
+    public String getTid() {
+        return tid;
+    }
+
+    public BigInteger getFeedId() {
+        return feedId;
+    }
+
+    public void setFeedId(BigInteger feedId) {
+        this.feedId = feedId;
+    }
+}

+ 358 - 0
janus/src/main/java/com/wdkl/rtc/janus/VideoRoomCallback.java

@@ -0,0 +1,358 @@
+package com.wdkl.rtc.janus;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import com.wdkl.rtc.entity.MsgEvent;
+import com.wdkl.rtc.entity.Publisher;
+import com.wdkl.rtc.entity.Room;
+import com.wdkl.rtc.rtc.observer.CreateAnswerCallback;
+import com.wdkl.rtc.rtc.observer.CreateOfferCallback;
+import com.wdkl.rtc.rtc.observer.CreatePeerConnectionCallback;
+import com.wdkl.rtc.rtc.Peer;
+import com.wdkl.rtc.rtc.WebRTCEngine;
+import com.wdkl.rtc.ui.SingleCallFragment;
+import com.wdkl.rtc.util.EnumType;
+
+import org.greenrobot.eventbus.EventBus;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.webrtc.IceCandidate;
+import org.webrtc.MediaStream;
+import org.webrtc.SdpObserver;
+import org.webrtc.SessionDescription;
+
+import java.math.BigInteger;
+
+public class VideoRoomCallback implements JanusClient.JanusCallback {
+    private final static String TAG = VideoRoomCallback.class.getSimpleName();
+
+    private JanusClient janusClient;
+    private Peer peer;
+    private BigInteger videoRoomHandlerId;
+    private Room room;
+    private BigInteger userId;
+    private SingleCallFragment currentFragment;
+
+    public VideoRoomCallback(JanusClient janusClient, Room room, BigInteger userId, SingleCallFragment currentFragment){
+        this.janusClient = janusClient;
+        this.room = room;
+        this.userId = userId;
+        this.currentFragment = currentFragment;
+    }
+
+    @Override
+    public void onCreateRoom(BigInteger handleId) {
+        videoRoomHandlerId = handleId;
+        janusClient.joinRoom(handleId, userId.toString());
+    }
+
+    @Override
+    public void onCreateSession(BigInteger sessionId) {
+        janusClient.attachPlugin("janus.plugin.videoroom");
+    }
+
+    @Override
+    public void onAttached(BigInteger handleId) {
+        Log.d(TAG, "onAttached");
+        janusClient.createRoom(handleId, room.getId());
+    }
+
+    @Override
+    public void onSubscribeAttached(BigInteger subscriptionHandleId, BigInteger feedId) {
+        Publisher publisher = room.findPublisherById(feedId);
+        if (publisher != null) {
+            publisher.setHandleId(subscriptionHandleId);
+            // 订阅发布者
+            janusClient.subscribe(subscriptionHandleId, feedId);
+        }
+    }
+
+    @Override
+    public void onDetached(BigInteger handleId) {
+        videoRoomHandlerId = null;
+    }
+
+    @Override
+    public void onHangup(BigInteger handleId) {
+        EventBus.getDefault().post(new MsgEvent<BigInteger>(3));
+    }
+
+    @Override
+    public void onMessage(BigInteger sender, BigInteger handleId, JSONObject data, JSONObject jsep) {
+        if (!data.has("videoroom")) {
+            return;
+        }
+        try {
+            String type = data.getString("videoroom");
+            if ("joined".equals(type)) {
+
+                //================= WebRTC
+                //创建本地PeerConnection,设置本地媒体流
+                WebRTCEngine.getInstance().createLocalPeer(userId, peerConnectionCallback);
+                this.peer = WebRTCEngine.getInstance().getPeer(userId);
+
+                // 加入房间成功
+                // 发送 offer 和网关建立连接
+                peer.createOffer(new CreateOfferCallback() {
+                    @Override
+                    public void onCreateOfferSuccess(SessionDescription sdp) {
+                        // 发布
+                        janusClient.publish(videoRoomHandlerId, sdp, !WebRTCEngine.getInstance().mIsAudioOnly);
+                    }
+
+                    @Override
+                    public void onCreateFailed(String error) {
+
+                    }
+                });
+
+                //userId = BigInteger.valueOf(data.getInt("id"));  //用户id
+
+                JSONArray publishers = data.getJSONArray("publishers");
+                handleNewPublishers(publishers);
+            } else if ("event".equals(type)) {
+                if (data.has("configured") && data.getString("configured").equals("ok")
+                        && jsep != null) {
+                    // sdp 协商成功,收到网关发来的 sdp answer,开始接收
+                    String sdp = jsep.getString("sdp");
+
+                    peer.getPeerConnection().setRemoteDescription(new SdpObserver() {
+                        @Override
+                        public void onCreateSuccess(SessionDescription sdp) {
+                            Log.d(TAG, "setRemoteDescription onCreateSuccess");
+                        }
+
+                        @Override
+                        public void onSetSuccess() {
+                            Log.d(TAG, "setRemoteDescription onSetSuccess");
+                            //加载本地视频
+                            EventBus.getDefault().post(new MsgEvent<BigInteger>(1));
+                        }
+
+                        @Override
+                        public void onCreateFailure(String error) {
+                            Log.d(TAG, "setRemoteDescription onCreateFailure " + error);
+                        }
+
+                        @Override
+                        public void onSetFailure(String error) {
+                            Log.d(TAG, "setRemoteDescription onSetFailure " + error);
+                        }
+                    }, new SessionDescription(SessionDescription.Type.ANSWER, sdp));
+                } else if (data.has("unpublished")) {
+                    Long unPublishdUserId = data.getLong("unpublished");
+                } else if (data.has("leaving")) {
+                    // 离开
+                    BigInteger leavingUserId = new BigInteger(data.getString("leaving"));
+                    room.removePublisherById(leavingUserId);
+                    //用户离开房间,此用户的peer应当从 engine 中清掉
+                    WebRTCEngine.getInstance().leaveRoom(leavingUserId);
+
+                    if (room.getPublishers().size()<=1){
+                        janusClient.setCallState(EnumType.CallState.Idle);
+                        EventBus.getDefault().post(new MsgEvent<BigInteger>(3,leavingUserId));
+                    }
+                } else if (data.has("publishers")) {
+                    // 新用户开始发布
+                    JSONArray publishers = data.getJSONArray("publishers");
+                    handleNewPublishers(publishers);
+                } else if (data.has("started") && data.getString("started").equals("ok")) {
+                    // 订阅 start 成功
+                    Log.d(TAG, "subscription started ok");
+                    currentFragment.didChangeState(EnumType.CallState.Connected);
+                }
+            } else if ("attached".equals(type) && jsep != null) {
+                // attach 到了一个Publisher 上,会收到网关转发来的sdp offer
+                String sdp = jsep.getString("sdp");
+                // plugindata.data.id 其它发布者的 userId
+                BigInteger feedId = new BigInteger(data.getString("id"));
+                String display = data.getString("display");
+                Publisher publisher = room.findPublisherById(feedId);
+
+                //创建新 peer connection
+                CreatePeerConnectionCallback remotePeerConnectionCallback = new CreatePeerConnectionCallback() {
+                    @Override
+                    public void onIceGatheringComplete() {
+                        janusClient.trickleCandidateComplete(sender);
+                    }
+
+                    @Override
+                    public void onIceCandidate(IceCandidate candidate) {
+                        janusClient.trickleCandidate(sender, candidate);
+                    }
+
+                    @Override
+                    public void onIceCandidatesRemoved(IceCandidate[] candidates) {
+
+                    }
+
+                    @Override
+                    public void onAddStream(MediaStream stream) {
+                        if (stream.videoTracks.size() > 0) {
+                            stream.audioTracks.get(0).setEnabled(true);
+                            WebRTCEngine.getInstance().getPeer(feedId)._remoteStream = stream;
+                            //todo:此处需其它回调
+                            janusClient.setCallState(EnumType.CallState.Connected);
+
+                            // todo: 添加用户到界面
+                            //handler.post(()->currentFragment.didReceiveRemoteVideoTrack(feedId));
+                            EventBus.getDefault().post(new MsgEvent<BigInteger>(2, feedId));
+                        }
+                    }
+
+                    @Override
+                    public void onRemoveStream(MediaStream stream) {
+                        peer._remoteStream = null;
+                        //todo:此处需其它回调
+                    }
+
+                    @Override
+                    public void onIceConnected() {
+
+                    }
+
+                    @Override
+                    public void onIceDisconnected() {
+
+                    }
+
+                    @Override
+                    public void onIceConnectFail() {
+
+                    }
+                };
+                WebRTCEngine.getInstance().createRemotePeer(feedId,remotePeerConnectionCallback);
+
+                WebRTCEngine.getInstance().getPeer(feedId).getPeerConnection().setRemoteDescription(new SdpObserver() {
+                    @Override
+                    public void onCreateSuccess(SessionDescription sdp) {
+                        Log.d(TAG, "setRemoteDescription onCreateSuccess");
+                    }
+
+                    @Override
+                    public void onSetSuccess() {
+                        Log.d(TAG, "setRemoteDescription onSetSuccess");
+                        // 回复网关一个 start ,附带自己的 sdp answer
+                        WebRTCEngine.getInstance().getPeer(feedId).createAnswer(new CreateAnswerCallback() {
+                            @Override
+                            public void onSetAnswerSuccess(SessionDescription sdp) {
+                                janusClient.subscriptionStart(publisher.getHandleId(), sdp);
+                            }
+
+                            @Override
+                            public void onSetAnswerFailed(String error) {
+
+                            }
+                        });
+                    }
+
+                    @Override
+                    public void onCreateFailure(String error) {
+                        Log.d(TAG, "setRemoteDescription onCreateFailure " + error);
+                    }
+
+                    @Override
+                    public void onSetFailure(String error) {
+                        Log.d(TAG, "setRemoteDescription onSetFailure " + error);
+                    }
+                }, new SessionDescription(SessionDescription.Type.OFFER, sdp));
+            } else if ("destroyed".equals(type)){
+//                EventBus.getDefault().post(new MsgEvent<BigInteger>(3));
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void onIceCandidate(BigInteger handleId, JSONObject candidate) {
+//        try {
+//            if (!candidate.has("completed")) {
+//                peer.getPeerConnection().addIceCandidate(new IceCandidate(candidate.getString("sdpMid"),
+//                        candidate.getInt("sdpMLineIndex"), candidate.getString("candidate")));
+//            }
+//        } catch (JSONException e) {
+//            e.printStackTrace();
+//        }
+    }
+
+    @Override
+    public void onDestroySession(BigInteger sessionId) {
+    }
+
+    @Override
+    public void onError(int errorCode, String error) {
+        if (errorCode==JanusClient.ERROR_CREATE_ROOM){
+            Log.e(TAG,error);
+            EventBus.getDefault().post(new MsgEvent<BigInteger>(4));
+        }
+    }
+
+    private void handleNewPublishers(JSONArray publishers) {
+        for (int i = 0; i < publishers.length(); i++) {
+            try {
+                JSONObject publishObj = publishers.getJSONObject(i);
+                BigInteger feedId = new BigInteger(publishObj.getString("id"));
+                String display = publishObj.getString("display");
+                // subscribeAttach 到发布者的 handle 上
+                janusClient.subscribeAttach(feedId);
+
+                room.addPublisher(new Publisher(feedId, display));
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+        }
+
+        StringBuilder sb = new StringBuilder(512);
+        for(Publisher publisher:room.getPublishers()){
+            sb.append("用户id: " + publisher.getId() + " " + publisher.getDisplay() + " "+ publisher.getHandleId());
+        }
+        Log.d(TAG, "当前房间有 :" + room.getPublishers().size() + " 人," + sb.toString());
+    }
+
+    //收集candidate并发送
+    private CreatePeerConnectionCallback peerConnectionCallback = new CreatePeerConnectionCallback() {
+        @Override
+        public void onIceGatheringComplete() {
+            janusClient.trickleCandidateComplete(videoRoomHandlerId);
+        }
+
+        @Override
+        public void onIceCandidate(IceCandidate candidate) {
+            janusClient.trickleCandidate(videoRoomHandlerId, candidate);
+        }
+
+        @Override
+        public void onIceCandidatesRemoved(IceCandidate[] candidates) {
+            peer.getPeerConnection().removeIceCandidates(candidates);
+        }
+
+        @Override
+        public void onAddStream(MediaStream stream) {
+
+        }
+
+        @Override
+        public void onRemoveStream(MediaStream stream) {
+
+        }
+
+        @Override
+        public void onIceConnected() {
+
+        }
+
+        @Override
+        public void onIceDisconnected() {
+
+        }
+
+        @Override
+        public void onIceConnectFail() {
+
+        }
+    };
+}

+ 110 - 0
janus/src/main/java/com/wdkl/rtc/janus/WebSocketChannel.java

@@ -0,0 +1,110 @@
+package com.wdkl.rtc.janus;
+
+import android.util.Log;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.WebSocket;
+import okhttp3.WebSocketListener;
+
+/**
+ */
+public class WebSocketChannel {
+    private static final String TAG = WebSocketChannel.class.getSimpleName();
+    private WebSocket webSocket;
+    private boolean connected;
+    private WebSocketCallback webSocketCallback;
+    private String url;
+    private String lastMsg = null;
+
+    public void connect(String url) {
+        Log.d(TAG,"连接 websocket");
+        this.url = url;
+        OkHttpClient client = new OkHttpClient();
+        /* WebSocket 子协议只是添加一个 Sec-WebSocket-Protocol 的 http 请求头,告诉服务器我们要使用 janus-protocol 这种协议来通信了。
+         * Response 中也会返回这个头。
+         * Sec-WebSocket-Protocol=janus-protocol"
+         */
+        Request request = new Request.Builder()
+                .header("Sec-WebSocket-Protocol", "janus-protocol")
+                .url(url)
+                .build();
+        webSocket = client.newWebSocket(request, new WebSocketHandler());
+    }
+
+    public boolean isConnected() {
+        return connected;
+    }
+
+    public void sendMessage(String message) {
+        if (webSocket != null && connected) {
+            Log.d(TAG, "send==>>" + message);
+            webSocket.send(message);
+        } else {
+            //lastMsg = message;
+            Log.e(TAG, "send failed socket not connected");
+            //connect(url);
+        }
+    }
+
+    public void close() {
+        if (webSocket != null) {
+            webSocket.close(1000, "manual close");
+            webSocket = null;
+        }
+    }
+
+    private class WebSocketHandler extends WebSocketListener {
+        @Override
+        public void onOpen(WebSocket webSocket, Response response) {
+            connected = true;
+            Log.d(TAG, "onOpen");
+//            if (lastMsg!=null){
+//                sendMessage(lastMsg);
+//                lastMsg = null;
+//            }
+            if (webSocketCallback != null) {
+                webSocketCallback.onOpen();
+            }
+        }
+
+        @Override
+        public void onMessage(WebSocket webSocket, String text) {
+            Log.d(TAG, "onMessage " + text);
+            if (webSocketCallback != null) {
+                webSocketCallback.onMessage(text);
+            }
+        }
+
+        @Override
+        public void onClosed(WebSocket webSocket, int code, String reason) {
+            Log.d(TAG, "onClosed " + reason);
+            connected = false;
+            if (webSocketCallback != null) {
+                webSocketCallback.onClosed();
+            }
+        }
+
+        @Override
+        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
+            Log.d(TAG, "onFailure " + t.getMessage());
+            connected = false;
+            if (webSocketCallback != null) {
+                webSocketCallback.onClosed();
+            }
+        }
+    }
+
+    public void setWebSocketCallback(WebSocketCallback webSocketCallback) {
+        this.webSocketCallback = webSocketCallback;
+    }
+
+    public interface WebSocketCallback {
+        void onOpen();
+
+        void onMessage(String text);
+
+        void onClosed();
+    }
+}

+ 1 - 5
rtc-chat/src/main/java/com/wdkl/skywebrtc/render/ProxyVideoSink.java

@@ -1,13 +1,9 @@
-package com.wdkl.skywebrtc.render;
+package com.wdkl.rtc.render;
 
 import org.webrtc.Logging;
 import org.webrtc.VideoFrame;
 import org.webrtc.VideoSink;
 
-/**
- * Created by dds on 2019/4/4.
- * android_shuai@163.com
- */
 public class ProxyVideoSink implements VideoSink {
     private static final String TAG = "dds_ProxyVideoSink";
     private VideoSink target;

+ 1 - 1
rtc-chat/src/main/java/com/wdkl/skywebrtc/render/VideoFileRenderer.java

@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-package com.wdkl.skywebrtc.render;
+package com.wdkl.rtc.render;
 
 import android.os.Handler;
 import android.os.HandlerThread;

+ 1 - 1
rtc-chat/src/main/java/com/wdkl/skywebrtc/engine/AudioFocusManager.java

@@ -1,4 +1,4 @@
-package com.wdkl.skywebrtc.engine;
+package com.wdkl.rtc.rtc;
 
 import android.content.Context;
 import android.media.AudioAttributes;

+ 188 - 0
janus/src/main/java/com/wdkl/rtc/rtc/Peer.java

@@ -0,0 +1,188 @@
+package com.wdkl.rtc.rtc;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.wdkl.rtc.render.ProxyVideoSink;
+import com.wdkl.rtc.rtc.observer.AnswerSdpObserver;
+import com.wdkl.rtc.rtc.observer.CreateAnswerCallback;
+import com.wdkl.rtc.rtc.observer.CreateOfferCallback;
+import com.wdkl.rtc.rtc.observer.CreatePeerConnectionCallback;
+import com.wdkl.rtc.rtc.observer.CustomPCObserver;
+import com.wdkl.rtc.rtc.observer.OfferSdpObserver;
+
+import org.webrtc.EglBase;
+import org.webrtc.IceCandidate;
+import org.webrtc.MediaConstraints;
+import org.webrtc.MediaStream;
+import org.webrtc.PeerConnection;
+import org.webrtc.PeerConnectionFactory;
+import org.webrtc.RendererCommon;
+import org.webrtc.SessionDescription;
+import org.webrtc.SurfaceViewRenderer;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ScheduledExecutorService;
+
+public class Peer {
+    private final static String TAG = "Peer";
+
+    private final PeerConnection peerConnection;
+    private final BigInteger mUserId;
+
+    private List<IceCandidate> queuedRemoteCandidates;
+    private SessionDescription localSdp;
+    private final PeerConnectionFactory mFactory;
+    private final List<PeerConnection.IceServer> mIceLis;
+    private ScheduledExecutorService executor;
+
+    public MediaStream _remoteStream;
+    public SurfaceViewRenderer renderer;
+    public ProxyVideoSink sink;
+
+    public Peer(PeerConnectionFactory factory, List<PeerConnection.IceServer> list, CreatePeerConnectionCallback peerConnectionCallback, ScheduledExecutorService executor, BigInteger userId) {
+        this.mFactory = factory;
+        this.mIceLis = list;
+        this.executor = executor;
+        this.mUserId = userId;
+        this.queuedRemoteCandidates = new ArrayList<>();
+        this.peerConnection = createPeerConnection(peerConnectionCallback);
+        Log.d(TAG, "create Peer:" + mUserId);
+    }
+
+    public PeerConnection createPeerConnection(CreatePeerConnectionCallback peerConnectionCallback) {
+        PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(mIceLis);
+        if (mFactory != null) {
+            return mFactory.createPeerConnection(rtcConfig, new CustomPCObserver(executor, peerConnectionCallback));
+        } else {
+            return null;
+        }
+    }
+
+    public PeerConnection getPeerConnection() {
+        return peerConnection;
+    }
+
+    public SessionDescription getLocalSdp() {
+        return localSdp;
+    }
+
+    public void setLocalSdp(SessionDescription localSdp) {
+        this.localSdp = localSdp;
+    }
+
+    // 创建offer
+    public void createOffer(CreateOfferCallback offerCallback){
+        if (peerConnection == null) return;
+        Log.d(TAG, "createOffer");
+        peerConnection.createOffer(new OfferSdpObserver(this, offerCallback), offerOrAnswerConstraint());
+    }
+
+    // 创建answer
+    public void createAnswer(CreateAnswerCallback answerCallback) {
+        if (peerConnection == null) return;
+        Log.d(TAG, "createAnswer");
+        peerConnection.createAnswer(new AnswerSdpObserver(this, answerCallback), offerOrAnswerConstraint());
+    }
+
+    //添加本地流
+    public void addLocalStream(MediaStream stream) {
+        if (peerConnection == null) return;
+        Log.d(TAG, "addLocalStream" + mUserId);
+        peerConnection.addStream(stream);
+    }
+
+    // 添加RemoteIceCandidate
+    public synchronized void addRemoteIceCandidate(final IceCandidate candidate) {
+        Log.d(TAG, "addRemoteIceCandidate");
+        if (peerConnection != null) {
+            if (queuedRemoteCandidates != null) {
+               Log.d(TAG, "addRemoteIceCandidate");
+                synchronized (Peer.class) {
+                    if (queuedRemoteCandidates != null) {
+                        queuedRemoteCandidates.add(candidate);
+                    }
+                }
+            } else {
+               Log.d(TAG, "addRemoteIceCandidate");
+                peerConnection.addIceCandidate(candidate);
+            }
+        }
+    }
+
+    // 移除RemoteIceCandidates
+    public void removeRemoteIceCandidates(final IceCandidate[] candidates) {
+        if (peerConnection == null) {
+            return;
+        }
+        drainCandidates();
+        peerConnection.removeIceCandidates(candidates);
+    }
+
+    public void createRender(EglBase mRootEglBase, Context context, boolean isOverlay) {
+        renderer = new SurfaceViewRenderer(context);
+        renderer.init(mRootEglBase.getEglBaseContext(), new RendererCommon.RendererEvents() {
+            @Override
+            public void onFirstFrameRendered() {
+                Log.d(TAG, "createRender onFirstFrameRendered");
+            }
+
+            @Override
+            public void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation) {
+                Log.d(TAG, "createRender onFrameResolutionChanged");
+            }
+        });
+        renderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL);
+        renderer.setMirror(true);
+        renderer.setZOrderMediaOverlay(isOverlay);
+        sink = new ProxyVideoSink();
+        sink.setTarget(renderer);
+        if (_remoteStream != null && _remoteStream.videoTracks.size() > 0) {
+            _remoteStream.videoTracks.get(0).addSink(sink);
+        }
+    }
+
+    // 关闭Peer
+    public void close() {
+        if (renderer != null) {
+            renderer.release();
+            renderer = null;
+        }
+        if (sink != null) {
+            sink.setTarget(null);
+        }
+        if (peerConnection != null) {
+            try {
+                peerConnection.close();
+                peerConnection.dispose();
+            } catch (Exception e) {
+
+            }
+        }
+    }
+
+    public void drainCandidates() {
+        Log.i(TAG, "drainCandidates");
+        synchronized (Peer.class) {
+            if (queuedRemoteCandidates != null) {
+                Log.d(TAG, "Add " + queuedRemoteCandidates.size() + " remote candidates");
+                for (IceCandidate candidate : queuedRemoteCandidates) {
+                    peerConnection.addIceCandidate(candidate);
+                }
+                queuedRemoteCandidates = null;
+            }
+        }
+    }
+
+    public MediaConstraints offerOrAnswerConstraint() {
+        MediaConstraints mediaConstraints = new MediaConstraints();
+        ArrayList<MediaConstraints.KeyValuePair> keyValuePairs = new ArrayList<>();
+        keyValuePairs.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
+        keyValuePairs.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
+        mediaConstraints.mandatory.addAll(keyValuePairs);
+        //mediaConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
+        return mediaConstraints;
+    }
+}

File diff suppressed because it is too large
+ 497 - 521
rtc-chat/src/main/java/com/wdkl/skywebrtc/engine/webrtc/WebRTCEngine.java


+ 71 - 0
janus/src/main/java/com/wdkl/rtc/rtc/observer/AnswerSdpObserver.java

@@ -0,0 +1,71 @@
+package com.wdkl.rtc.rtc.observer;
+
+import android.util.Log;
+
+import com.wdkl.rtc.rtc.Peer;
+
+import org.webrtc.SdpObserver;
+import org.webrtc.SessionDescription;
+
+public class AnswerSdpObserver implements SdpObserver {
+    private final static String TAG = AnswerSdpObserver.class.getSimpleName();
+
+    Peer peer;
+    CreateAnswerCallback callback;
+
+    public AnswerSdpObserver(Peer peer, CreateAnswerCallback callback){
+        this.peer = peer;
+        this.callback = callback;
+    }
+
+    @Override
+    public void onCreateSuccess(SessionDescription sdp) {
+        Log.d(TAG, "createOffer onCreateSuccess " + sdp.toString());
+        peer.getPeerConnection().setLocalDescription(new SdpObserver() {
+            @Override
+            public void onCreateSuccess(SessionDescription sdp) {
+                Log.d(TAG, "createAnswer setLocalDescription onCreateSuccess");
+            }
+
+            @Override
+            public void onSetSuccess() {
+                Log.d(TAG, "createAnswer setLocalDescription onSetSuccess");
+                // send answer sdp
+                if (callback != null) {
+                    callback.onSetAnswerSuccess(sdp);
+                }
+            }
+
+            @Override
+            public void onCreateFailure(String error) {
+                Log.d(TAG, "createAnswer setLocalDescription onCreateFailure " + error);
+                if (callback != null) {
+                    callback.onSetAnswerFailed(error);
+                }
+            }
+
+            @Override
+            public void onSetFailure(String error) {
+                Log.d(TAG, "createAnswer setLocalDescription onSetFailure " + error);
+                if (callback != null) {
+                    callback.onSetAnswerFailed(error);
+                }
+            }
+        }, sdp);
+    }
+
+    @Override
+    public void onSetSuccess() {
+        Log.d(TAG, "createAnswer onSetSuccess");
+    }
+
+    @Override
+    public void onCreateFailure(String s) {
+        Log.d(TAG, "createAnswer onCreateFailure " + s);
+    }
+
+    @Override
+    public void onSetFailure(String s) {
+        Log.d(TAG, "createAnswer onSetFailure " + s);
+    }
+}

+ 9 - 0
janus/src/main/java/com/wdkl/rtc/rtc/observer/CreateAnswerCallback.java

@@ -0,0 +1,9 @@
+package com.wdkl.rtc.rtc.observer;
+
+import org.webrtc.SessionDescription;
+
+public interface CreateAnswerCallback {
+    void onSetAnswerSuccess(SessionDescription sdp);
+
+    void onSetAnswerFailed(String error);
+}

+ 9 - 0
janus/src/main/java/com/wdkl/rtc/rtc/observer/CreateOfferCallback.java

@@ -0,0 +1,9 @@
+package com.wdkl.rtc.rtc.observer;
+
+import org.webrtc.SessionDescription;
+
+public interface CreateOfferCallback {
+    void onCreateOfferSuccess(SessionDescription sdp);
+
+    void onCreateFailed(String error);
+}

+ 20 - 0
janus/src/main/java/com/wdkl/rtc/rtc/observer/CreatePeerConnectionCallback.java

@@ -0,0 +1,20 @@
+package com.wdkl.rtc.rtc.observer;
+
+import org.webrtc.IceCandidate;
+import org.webrtc.MediaStream;
+
+public interface CreatePeerConnectionCallback {
+    void onIceGatheringComplete();
+
+    void onIceCandidate(IceCandidate candidate);
+
+    void onIceCandidatesRemoved(IceCandidate[] candidates);
+
+    void onAddStream(MediaStream stream);
+
+    void onRemoveStream(MediaStream stream);
+
+    void onIceConnected();
+    void onIceDisconnected();
+    void onIceConnectFail();
+}

+ 128 - 0
janus/src/main/java/com/wdkl/rtc/rtc/observer/CustomPCObserver.java

@@ -0,0 +1,128 @@
+package com.wdkl.rtc.rtc.observer;
+
+import android.util.Log;
+
+import org.webrtc.DataChannel;
+import org.webrtc.IceCandidate;
+import org.webrtc.MediaStream;
+import org.webrtc.PeerConnection;
+import org.webrtc.RtpReceiver;
+
+import java.util.concurrent.ScheduledExecutorService;
+
+public class CustomPCObserver implements PeerConnection.Observer {
+    private final static String TAG = CustomPCObserver.class.getSimpleName();
+
+    private ScheduledExecutorService executor;
+    private CreatePeerConnectionCallback callback;
+
+    public CustomPCObserver(ScheduledExecutorService executor, CreatePeerConnectionCallback callback) {
+        this.executor = executor;
+        this.callback = callback;
+    }
+    @Override
+    public void onIceCandidate(final IceCandidate candidate) {
+        Log.d(TAG,"onIceCandidate");
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                if (callback != null) {
+                    callback.onIceCandidate(candidate);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onIceCandidatesRemoved(final IceCandidate[] candidates) {
+        Log.d(TAG, "onIceCandidatesRemoved");
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                if (callback != null) {
+                    callback.onIceCandidatesRemoved(candidates);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onSignalingChange(PeerConnection.SignalingState newState) {
+        Log.d(TAG, "SignalingState: " + newState);
+    }
+
+    @Override
+    public void onIceConnectionChange(final PeerConnection.IceConnectionState newState) {
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                Log.d(TAG, "IceConnectionState: " + newState);
+                if (newState == PeerConnection.IceConnectionState.CONNECTED) {
+                    callback.onIceConnected();
+                } else if (newState == PeerConnection.IceConnectionState.DISCONNECTED) {
+                    callback.onIceDisconnected();
+                } else if (newState == PeerConnection.IceConnectionState.FAILED) {
+                    callback.onIceConnectFail();
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onIceGatheringChange(PeerConnection.IceGatheringState newState) {
+        Log.d(TAG, "onIceGatheringChange " + newState);
+        if (newState == PeerConnection.IceGatheringState.COMPLETE) {
+            if (callback != null) {
+                callback.onIceGatheringComplete();
+            }
+        }
+    }
+
+    @Override
+    public void onIceConnectionReceivingChange(boolean receiving) {
+        Log.d(TAG, "onIceConnectionReceivingChange changed to " + receiving);
+    }
+
+    @Override
+    public void onAddStream(final MediaStream stream) {
+        Log.d(TAG, "onAddStream");
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                if (callback != null) {
+                    callback.onAddStream(stream);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onRemoveStream(final MediaStream stream) {
+        Log.d(TAG, "onRemoveStream");
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                if (callback != null) {
+                    callback.onRemoveStream(stream);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onDataChannel(final DataChannel dc) {
+        Log.d(TAG, "New Data channel " + dc.label());
+
+    }
+
+    @Override
+    public void onRenegotiationNeeded() {
+        // No need to do anything; AppRTC follows a pre-agreed-upon
+        // signaling/negotiation protocol.
+    }
+
+    @Override
+    public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {
+
+    }
+}

+ 78 - 0
janus/src/main/java/com/wdkl/rtc/rtc/observer/OfferSdpObserver.java

@@ -0,0 +1,78 @@
+package com.wdkl.rtc.rtc.observer;
+
+import android.util.Log;
+
+import com.wdkl.rtc.rtc.Peer;
+
+import org.webrtc.SdpObserver;
+import org.webrtc.SessionDescription;
+
+public class OfferSdpObserver implements SdpObserver {
+    private final static String TAG = OfferSdpObserver.class.getSimpleName();
+
+    Peer peer;
+    CreateOfferCallback callback;
+
+    public OfferSdpObserver(Peer peer, CreateOfferCallback callback){
+        this.peer = peer;
+        this.callback = callback;
+    }
+
+    @Override
+    public void onCreateSuccess(SessionDescription originalSdp) {
+        Log.d(TAG, "createOffer sdp创建成功       " + originalSdp.type);
+        final SessionDescription sdp = new SessionDescription(originalSdp.type, originalSdp.description);
+        peer.setLocalSdp(sdp);
+        peer.getPeerConnection().setLocalDescription(new SdpObserver() {
+            @Override
+            public void onCreateSuccess(SessionDescription sessionDescription) {
+                Log.d(TAG, "setLocalDescription sdp创建成功       " + sessionDescription.type);
+            }
+
+            @Override
+            public void onSetSuccess() {
+                Log.d(TAG, "setLocalDescription onSetSuccess");
+                if (peer.getPeerConnection().getRemoteDescription()==null){
+                    //发出offer
+                    if (callback != null) {
+                        callback.onCreateOfferSuccess(sdp);
+                    }
+                } else {
+                    Log.d(TAG, "Remote SDP set succesfully");
+                    peer.drainCandidates();
+                }
+            }
+
+            @Override
+            public void onCreateFailure(String s) {
+                Log.d(TAG, "setLocalDescription onCreateFailure   " + s);
+            }
+
+            @Override
+            public void onSetFailure(String s) {
+                Log.d(TAG, "setLocalDescription onSetFailure   " + s);
+            }
+        },sdp);
+    }
+
+    @Override
+    public void onSetSuccess() {
+        Log.d(TAG, "createOffer onSetSuccess");
+    }
+
+    @Override
+    public void onCreateFailure(String s) {
+        Log.d(TAG, "createOffer onCreateFailure " + s);
+        if (callback != null) {
+            callback.onCreateFailed(s);
+        }
+    }
+
+    @Override
+    public void onSetFailure(String s) {
+        Log.d(TAG, "createOffer onSetFailure " + s);
+        if (callback != null) {
+            callback.onCreateFailed(s);
+        }
+    }
+}

+ 222 - 0
janus/src/main/java/com/wdkl/rtc/ui/CallSingleActivity.java

@@ -0,0 +1,222 @@
+package com.wdkl.rtc.ui;
+
+import android.Manifest;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+
+import com.wdkl.rtc.util.Constant;
+import com.wdkl.rtc.R;
+import com.wdkl.rtc.entity.Room;
+import com.wdkl.rtc.janus.JanusClient;
+import com.wdkl.rtc.janus.VideoRoomCallback;
+import com.wdkl.rtc.rtc.WebRTCEngine;
+import com.wdkl.rtc.util.EnumType;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+import pub.devrel.easypermissions.EasyPermissions;
+
+/**
+ * 单人通话界面
+ */
+public class CallSingleActivity extends AppCompatActivity {
+
+    public static final String EXTRA_ROOM_ID = "roomId";
+    public static final String EXTRA_MO = "isOutGoing";
+    public static final String EXTRA_AUDIO_ONLY = "audioOnly";
+    public static final String EXTRA_INVITE_USER = "inviteUser";
+    private static final String TAG = "CallSingleActivity";
+
+    private boolean isOutgoing;
+    private BigInteger roomId;
+    private Room room;
+    private BigInteger localUserId = BigInteger.valueOf(new Random().nextInt(1000));
+    boolean isAudioOnly = true;
+    JanusClient janusClient;
+    VideoRoomCallback videoRoomCallback;
+
+    private SingleCallFragment currentFragment;
+
+    public static Intent getCallIntent(Context context, int roomId, boolean isOutgoing,
+                                       boolean isAudioOnly, boolean isClearTop) {
+        Intent voip = new Intent(context, CallSingleActivity.class);
+        voip.putExtra(CallSingleActivity.EXTRA_MO, isOutgoing);
+        voip.putExtra(CallSingleActivity.EXTRA_ROOM_ID, roomId);
+        voip.putExtra(CallSingleActivity.EXTRA_AUDIO_ONLY, isAudioOnly);
+        if (isClearTop) {
+            voip.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        }
+        return voip;
+    }
+
+
+    public static void openActivity(Context context, int roomId, boolean isOutgoing,                                     boolean isAudioOnly, boolean isClearTop) {
+        Intent intent = getCallIntent(context, roomId, isOutgoing, isAudioOnly, isClearTop);
+        //if (context instanceof Activity) {
+        //    context.startActivity(intent);
+        //} else {
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            context.startActivity(intent);
+        //}
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setStatusBarOrScreenStatus(this);
+        setContentView(R.layout.activity_single_call);
+
+        final Intent intent = getIntent();
+        roomId = BigInteger.valueOf(intent.getIntExtra(EXTRA_ROOM_ID, 0));
+        isOutgoing = intent.getBooleanExtra(EXTRA_MO, false);
+        isAudioOnly = intent.getBooleanExtra(EXTRA_AUDIO_ONLY,true);
+
+        // 权限检测
+        String[] perms;
+        if (isAudioOnly) {
+            perms = new String[]{Manifest.permission.RECORD_AUDIO};
+        } else {
+            perms = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};
+        }
+        if (!EasyPermissions.hasPermissions(CallSingleActivity.this, perms)) {
+            EasyPermissions.requestPermissions(CallSingleActivity.this, "需要相机和录音权限",
+                    100, perms);
+        } else {
+            //初始化 engine
+            WebRTCEngine.getInstance().init(isAudioOnly, this);
+            init(roomId, isAudioOnly);
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+        //通话时不能按返回键,跟微信同现象,只能挂断结束或者接听
+        super.onBackPressed();
+        if (currentFragment != null) {
+            if (currentFragment instanceof FragmentAudio) {
+                ((FragmentAudio) currentFragment).onBackPressed();
+            } else if (currentFragment instanceof FragmentVideo) {
+                ((FragmentVideo) currentFragment).onBackPressed();
+            }
+        }
+    }
+
+    public SingleCallFragment getCurrentFragment() {
+        return currentFragment;
+    }
+
+    private void init(BigInteger roomId, boolean audioOnly) {
+        SingleCallFragment fragment;
+        if (audioOnly) {
+            fragment = new FragmentAudio();
+        } else {
+            fragment = new FragmentVideo();
+        }
+        FragmentManager fragmentManager = getSupportFragmentManager();
+        currentFragment = fragment;
+        fragmentManager.beginTransaction()
+                    .replace(R.id.fragment_content, fragment)
+                    .commit();
+
+        room = new Room(roomId);
+
+        //================ 信令
+        //初始化 janusClient
+        janusClient = new JanusClient(Constant.JANUS_URL, localUserId);
+
+        //================ 信令
+        videoRoomCallback = new VideoRoomCallback(janusClient,room, localUserId,currentFragment);
+        janusClient.setJanusCallback(videoRoomCallback);
+        // 1,连接,监听 onOpen, createSession,createSession 成功时设置janusClient sessionId,回调videoRoomCallback.onCreateSession
+        // 2,在 videoRoomCallback.onCreateSession 中使用 janusClient.attachPlugin("janus.plugin.videoroom") 获得插件 handleId,回调 videoRoomCallback.onAttached
+        // 3,在 videoRoomCallback.onAttached 中设置 videoRoomHandlerId变量为handleId,并调用 janusClient.joinRoom(handleId, room.getId(), inviteUserId.toString())
+        // 4,发送 joinRoom 后,经过janusClient onMeesage处理后,由 videoRoomCallback.onMessage 处理 plugindata.data
+        // 5,处理 janus:event,plugindata.data.videoroom:joined,在 peerConnection上createOffer,设置本地 sdp,回调 offerCallback.onCreateOfferSuccess,发布 publisher
+        if (isOutgoing) {
+            janusClient.setCallState(EnumType.CallState.Outgoing);
+        } else {
+            janusClient.setCallState(EnumType.CallState.Incoming);
+        }
+        janusClient.connect();
+
+        // 6,处理 publishers,每个publisher 包含 id (feedId) 和 display,attach 到发布者的 handler 上,准备接收视频流,每个发布者都要 attach 一遍,然后协商 sdp, SFU,subscribeAttach 到发布者的 handle 上 [janusClient.subscribeAttach(feedId)]。将publisher 放到Room对象中的publishers, 在 janusClient.subscribeAttach(feedId) 中回调 videoRoomCallback.onSubscribeAttached
+        // 7,在 videoRoomCallback.onSubscribeAttached 中订阅发布者,如果有 publisher 的话
+    }
+
+    // 切换到语音通话
+    public void switchAudio() {
+        //init(targetId, isOutgoing, true, true);
+    }
+
+    public Room getRoom() {
+        return room;
+    }
+
+    @TargetApi(19)
+    private static int getSystemUiVisibility() {
+        int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN |
+                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+        }
+        return flags;
+    }
+
+    /**
+     * 设置状态栏透明
+     */
+    @TargetApi(19)
+    public void setStatusBarOrScreenStatus(Activity activity) {
+        Window window = activity.getWindow();
+        //全屏+锁屏+常亮显示
+        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
+                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
+                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
+                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+        window.getDecorView().setSystemUiVisibility(getSystemUiVisibility());
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+            WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
+            layoutParams.layoutInDisplayCutoutMode =
+                    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+            window.setAttributes(layoutParams);
+        }
+        // 5.0以上系统状态栏透明
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            //清除透明状态栏
+            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+            //设置状态栏颜色必须添加
+            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+            window.setStatusBarColor(Color.TRANSPARENT);//设置透明
+        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //19
+            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+        }
+    }
+
+    @Override
+    public void finish(){
+//        janusClient.leaveRoom();
+//        janusClient.destroySession();
+        if (isOutgoing){
+            janusClient.setCallState(EnumType.CallState.Idle);
+            janusClient.destroyRoom(janusClient.getCurrentHandleId(),null);
+        }
+        janusClient.disConnect();
+        WebRTCEngine.getInstance().release();
+        super.finish();
+    }
+
+    public boolean isOutgoing() {
+        return isOutgoing;
+    }
+}

+ 39 - 50
WebRTC/src/main/java/com/wdkl/core/voip/FragmentAudio.java

@@ -1,4 +1,4 @@
-package com.wdkl.core.voip;
+package com.wdkl.rtc.ui;
 
 import android.os.Build;
 import android.util.Log;
@@ -7,15 +7,14 @@ import android.widget.ImageView;
 import android.widget.RelativeLayout;
 
 import com.blankj.utilcode.util.BarUtils;
-import com.wdkl.core.util.OSUtils;
-import com.wdkl.skywebrtc.CallSession;
-import com.wdkl.skywebrtc.EnumType.CallState;
-import com.wdkl.skywebrtc.SkyEngineKit;
-import com.wdkl.webrtc.R;
+import com.wdkl.rtc.R;
+import com.wdkl.rtc.entity.Publisher;
+import com.wdkl.rtc.entity.Room;
+import com.wdkl.rtc.rtc.WebRTCEngine;
+import com.wdkl.rtc.util.EnumType;
+import com.wdkl.rtc.util.OSUtils;
 
 /**
- * Created by dds on 2018/7/26.
- * android_shuai@163.com
  * 语音通话控制界面
  */
 public class FragmentAudio extends SingleCallFragment implements View.OnClickListener {
@@ -54,14 +53,12 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
     @Override
     public void init() {
         super.init();
-        CallSession currentSession = gEngineKit.getCurrentSession();
-        currentState = currentSession.getState();
+
         // 如果已经接通
-        if (currentSession != null && currentState == CallState.Connected) {
+        if (callSingleActivity.janusClient != null && callSingleActivity.janusClient.getCallState() == EnumType.CallState.Connected) {
             descTextView.setVisibility(View.GONE); // 提示语
             outgoingActionContainer.setVisibility(View.VISIBLE);
             durationTextView.setVisibility(View.VISIBLE);
-            //minimizeImageView.setVisibility(View.VISIBLE);
             startRefreshTime();
         } else {
             // 如果未接通
@@ -78,17 +75,34 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
     }
 
     @Override
-    public void didChangeState(CallState state) {
+    public void onBackPressed() {
+        super.onDestroy();
+    }
 
+    @Override
+    public void didChangeState(EnumType.CallState state) {
+        Log.d(TAG, "didChangeState, state = " + state);
+        callSingleActivity.janusClient.setCallState(state);
         currentState = state;
         runOnUiThread(() -> {
-            if (state == CallState.Connected) {
-                handler.removeMessages(WHAT_DELAY_END_CALL);
+            if (state == EnumType.CallState.Connected) {
                 incomingActionContainer.setVisibility(View.GONE);
                 outgoingActionContainer.setVisibility(View.VISIBLE);
                 //minimizeImageView.setVisibility(View.VISIBLE);
                 descTextView.setVisibility(View.GONE);
 
+                isSpeakerOn=!isSpeakerOn;
+                Log.d(TAG,"didChangeState 外放切换" + isSpeakerOn);
+                WebRTCEngine.getInstance().toggleSpeaker(isSpeakerOn);
+                speakerImageView.setSelected(isSpeakerOn);
+
+                Room room = callSingleActivity.getRoom();
+                StringBuilder sb = new StringBuilder(512);
+                for(Publisher publisher:room.getPublishers()){
+                    sb.append("id:" + publisher.getId() + ",name:" + publisher.getDisplay());
+                }
+                nameTextView.setText(sb.toString());
+
                 startRefreshTime();
             } else {
                 // do nothing now
@@ -101,50 +115,25 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
         int id = v.getId();
         // 接听
         if (id == R.id.acceptImageView) {
-            CallSession session = gEngineKit.getCurrentSession();
-            if (session != null)
-                Log.d(TAG, "session = " + session + "; session.getState() = " + session.getState());
-            if (session != null && session.getState() == CallState.Incoming) {
-                session.joinHome(session.getRoomId());
-            } else if (session != null) {
-                session.sendRefuse();
-            }
+
         }
         // 挂断电话
         if (id == R.id.incomingHangupImageView || id == R.id.outgoingHangupImageView) {
-            //App.getInstance().setOtherUserId("0");
-            CallSession session = gEngineKit.getCurrentSession();
-            if (session != null) {
-                SkyEngineKit.Instance().endCall();
-            }
-            //            activity.finish();
-            //再onEvent中结束,防止ChatActivity结束了,消息发送不了
+            if (callSingleActivity != null) callSingleActivity.finish();
         }
         // 静音
         if (id == R.id.muteImageView) {
-            CallSession session = gEngineKit.getCurrentSession();
-            if (session != null && session.getState() != CallState.Idle) {
-                if (session.toggleMuteAudio(!micEnabled)) {
-                    micEnabled = !micEnabled;
-                }
-                muteImageView.setSelected(micEnabled);
-            }
+            micEnabled = !micEnabled;
+            Log.d(TAG,"静音切换" + micEnabled);
+            WebRTCEngine.getInstance().muteAudio(micEnabled);
+            muteImageView.setSelected(micEnabled);
         }
         // 扬声器
         if (id == R.id.speakerImageView) {
-            CallSession session = gEngineKit.getCurrentSession();
-            if (session != null && session.getState() != CallState.Idle) {
-                if (session.toggleSpeaker(!isSpeakerOn)) {
-                    isSpeakerOn = !isSpeakerOn;
-                }
-                speakerImageView.setSelected(isSpeakerOn);
-            }
+            isSpeakerOn=!isSpeakerOn;
+            Log.d(TAG,"外放切换" + isSpeakerOn);
+            WebRTCEngine.getInstance().toggleSpeaker(isSpeakerOn);
+            speakerImageView.setSelected(isSpeakerOn);
         }
-        // 小窗
-        /*if (id == R.id.minimizeImageView) {
-            if (callSingleActivity != null) {
-                callSingleActivity.showFloatingView();
-            }
-        }*/
     }
 }

+ 46 - 95
WebRTC/src/main/java/com/wdkl/core/voip/FragmentVideo.java

@@ -1,4 +1,4 @@
-package com.wdkl.core.voip;
+package com.wdkl.rtc.ui;
 
 import android.content.Context;
 import android.os.Build;
@@ -12,17 +12,16 @@ import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 
 import com.blankj.utilcode.util.BarUtils;
-import com.wdkl.core.util.OSUtils;
-import com.wdkl.skywebrtc.CallSession;
-import com.wdkl.skywebrtc.EnumType.CallState;
-import com.wdkl.skywebrtc.SkyEngineKit;
-import com.wdkl.webrtc.R;
+import com.wdkl.rtc.R;
+import com.wdkl.rtc.rtc.WebRTCEngine;
+import com.wdkl.rtc.util.EnumType;
+import com.wdkl.rtc.util.OSUtils;
 
 import org.webrtc.SurfaceViewRenderer;
 
+import java.math.BigInteger;
+
 /**
- * Created by dds on 2018/7/26.
- * android_shuai@163.com
  * 视频通话控制界面
  */
 public class FragmentVideo extends SingleCallFragment implements View.OnClickListener {
@@ -38,16 +37,12 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
     private FrameLayout fullscreenRenderer;
     private FrameLayout pipRenderer;
     private LinearLayout inviteeInfoContainer;
-    private boolean isFromFloatingView = false;
     private SurfaceViewRenderer localSurfaceView;
     private SurfaceViewRenderer remoteSurfaceView;
 
     @Override
     public void onAttach(@NonNull Context context) {
         super.onAttach(context);
-        if (callSingleActivity != null) {
-            isFromFloatingView = callSingleActivity.isFromFloatingView();
-        }
     }
 
     @Override
@@ -103,24 +98,14 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
 
     }
 
-
     @Override
     public void init() {
         super.init();
-        CallSession session = gEngineKit.getCurrentSession();
-        if (session != null) {
-            currentState = session.getState();
-        }
-        if (session == null || CallState.Idle == session.getState()) {
-            if (callSingleActivity != null) {
-                callSingleActivity.finish();
-            }
-        } else if (CallState.Connected == session.getState()) {
+        if (EnumType.CallState.Connected == callSingleActivity.janusClient.getCallState()) {
             incomingActionContainer.setVisibility(View.GONE);
             outgoingActionContainer.setVisibility(View.GONE);
             connectedActionContainer.setVisibility(View.VISIBLE);
             inviteeInfoContainer.setVisibility(View.GONE);
-            //minimizeImageView.setVisibility(View.VISIBLE);
             startRefreshTime();
         } else {
             if (isOutgoing) {
@@ -133,9 +118,8 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
                 outgoingActionContainer.setVisibility(View.GONE);
                 connectedActionContainer.setVisibility(View.GONE);
                 descTextView.setText(R.string.av_video_invite);
-                if (currentState == CallState.Incoming) {
-                    View surfaceView = gEngineKit.getCurrentSession().setupLocalVideo(false);
-                    Log.d(TAG, "init surfaceView != null is " + (surfaceView != null) + "; isOutgoing = " + isOutgoing + "; currentState = " + currentState);
+                if (callSingleActivity.janusClient.getCallState() == EnumType.CallState.Incoming) {
+                    View surfaceView = WebRTCEngine.getInstance().startPreview(false);
                     if (surfaceView != null) {
                         localSurfaceView = (SurfaceViewRenderer) surfaceView;
                         localSurfaceView.setZOrderMediaOverlay(false);
@@ -144,27 +128,20 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
                 }
             }
         }
-        if (isFromFloatingView) {
-            didCreateLocalVideoTrack();
-            if (session != null) {
-                didReceiveRemoteVideoTrack(session.mTargetId);
-            }
-        }
     }
 
-    @Override
-    public void didChangeState(CallState state) {
-        currentState = state;
+    public void didChangeState(EnumType.CallState state) {
         Log.d(TAG, "didChangeState, state = " + state);
+        callSingleActivity.janusClient.setCallState(state);
+        currentState = state;
         runOnUiThread(() -> {
-            if (state == CallState.Connected) {
-                handler.removeMessages(WHAT_DELAY_END_CALL);
+            if (state == EnumType.CallState.Connected) {
                 incomingActionContainer.setVisibility(View.GONE);
                 outgoingActionContainer.setVisibility(View.GONE);
                 connectedActionContainer.setVisibility(View.VISIBLE);
                 inviteeInfoContainer.setVisibility(View.GONE);
                 descTextView.setVisibility(View.GONE);
-                //minimizeImageView.setVisibility(View.VISIBLE);
+
                 // 开启计时器
                 startRefreshTime();
             } else {
@@ -173,16 +150,14 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
         });
     }
 
-    @Override
     public void didChangeMode(Boolean isAudio) {
         runOnUiThread(() -> callSingleActivity.switchAudio());
     }
 
-
     @Override
     public void didCreateLocalVideoTrack() {
         if (localSurfaceView == null) {
-            View surfaceView = gEngineKit.getCurrentSession().setupLocalVideo(true);
+            View surfaceView = WebRTCEngine.getInstance().startPreview(true);
             if (surfaceView != null) {
                 localSurfaceView = (SurfaceViewRenderer) surfaceView;
             } else {
@@ -192,40 +167,36 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
         } else {
             localSurfaceView.setZOrderMediaOverlay(true);
         }
-        Log.d(TAG,
-                "didCreateLocalVideoTrack localSurfaceView != null is " + (localSurfaceView != null) + "; remoteSurfaceView == null = " + (remoteSurfaceView == null)
-        );
 
-        if (localSurfaceView.getParent() != null) {
-            ((ViewGroup) localSurfaceView.getParent()).removeView(localSurfaceView);
-        }
-        if (isOutgoing && remoteSurfaceView == null) {
+        if (remoteSurfaceView!=null){
+            pipRenderer.setVisibility(View.VISIBLE);
+            if (pipRenderer.getChildCount() != 0) pipRenderer.removeAllViews();
+
+            localSurfaceView.setZOrderMediaOverlay(true);
+            pipRenderer.addView(localSurfaceView);
+        } else {
+            pipRenderer.setVisibility(View.GONE);
             if (fullscreenRenderer != null && fullscreenRenderer.getChildCount() != 0)
                 fullscreenRenderer.removeAllViews();
             fullscreenRenderer.addView(localSurfaceView);
-        } else {
-            if (pipRenderer.getChildCount() != 0) pipRenderer.removeAllViews();
-            pipRenderer.addView(localSurfaceView);
         }
-    }
 
+        Log.d(TAG,
+                "didCreateLocalVideoTrack localSurfaceView == null is " + (localSurfaceView == null) + "; remoteSurfaceView == null = " + (remoteSurfaceView == null)
+        );
+    }
 
-    @Override
-    public void didReceiveRemoteVideoTrack(String userId) {
-        pipRenderer.setVisibility(View.VISIBLE);
+    public void didReceiveRemoteVideoTrack(BigInteger userId) {
         if (localSurfaceView != null) {
             localSurfaceView.setZOrderMediaOverlay(true);
-            if (isOutgoing) {
-                if (localSurfaceView.getParent() != null) {
-                    ((ViewGroup) localSurfaceView.getParent()).removeView(localSurfaceView);
-                }
-                pipRenderer.addView(localSurfaceView);
+            if (localSurfaceView.getParent() != null) {
+                ((ViewGroup) localSurfaceView.getParent()).removeView(localSurfaceView);
             }
+            pipRenderer.setVisibility(View.VISIBLE);
+            pipRenderer.addView(localSurfaceView);
         }
 
-
-        View surfaceView = gEngineKit.getCurrentSession().setupRemoteVideo(userId, false);
-        Log.d(TAG, "didReceiveRemoteVideoTrack,surfaceView = " + surfaceView);
+        View surfaceView = WebRTCEngine.getInstance().setupRemoteVideo(userId, false);
         if (surfaceView != null) {
             fullscreenRenderer.setVisibility(View.VISIBLE);
             remoteSurfaceView = (SurfaceViewRenderer) surfaceView;
@@ -235,16 +206,9 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
             }
             fullscreenRenderer.addView(remoteSurfaceView);
         }
-    }
-
-    @Override
-    public void didUserLeave(String userId) {
-
-    }
-
-    @Override
-    public void didError(String error) {
 
+        // 开启计时器
+        startRefreshTime();
     }
 
 
@@ -252,29 +216,18 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
     public void onClick(View v) {
         int id = v.getId();
         // 接听
-        CallSession session = gEngineKit.getCurrentSession();
         if (id == R.id.acceptImageView) {
-            if (session != null && session.getState() == CallState.Incoming) {
-                session.joinHome(session.getRoomId());
-            } else if (session != null) {
-                if (callSingleActivity != null) {
-                    session.sendRefuse();
-                    callSingleActivity.finish();
-                }
-            }
+            //todo: 接听
         }
         // 挂断电话
         if (id == R.id.incomingHangupImageView || id == R.id.outgoingHangupImageView || id == R.id.connectedHangupImageView) {
-            if (session != null) {
-                Log.d(TAG, "endCall");
-                SkyEngineKit.Instance().endCall();
-            }
+            //todo: 挂断
             if (callSingleActivity != null) callSingleActivity.finish();
         }
 
         // 切换摄像头
         if (id == R.id.switchCameraImageView) {
-            session.switchCamera();
+            WebRTCEngine.getInstance().switchCamera();
         }
         if (id == R.id.pip_video_view) {
             boolean isFullScreenRemote = fullscreenRenderer.getChildAt(0) == remoteSurfaceView;
@@ -295,16 +248,9 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
 
         // 切换到语音拨打
         if (id == R.id.outgoingAudioOnlyImageView || id == R.id.incomingAudioOnlyImageView || id == R.id.connectedAudioOnlyImageView) {
-            if (session != null) {
-                if (callSingleActivity != null) callSingleActivity.isAudioOnly = true;
-                session.switchToAudio();
-            }
+            if (callSingleActivity != null) callSingleActivity.isAudioOnly = true;
+            // todo: 切换纯语音
         }
-
-        // 小窗
-        /*if (id == R.id.minimizeImageView) {
-            if (callSingleActivity != null) callSingleActivity.showFloatingView();
-        }*/
     }
 
 
@@ -314,4 +260,9 @@ public class FragmentVideo extends SingleCallFragment implements View.OnClickLis
         fullscreenRenderer.removeAllViews();
         pipRenderer.removeAllViews();
     }
+
+    @Override
+    public void onBackPressed() {
+        onDestroy();
+    }
 }

+ 55 - 77
WebRTC/src/main/java/com/wdkl/core/voip/SingleCallFragment.java

@@ -1,4 +1,4 @@
-package com.wdkl.core.voip;
+package com.wdkl.rtc.ui;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -9,8 +9,6 @@ import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.v4.app.Fragment;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -19,25 +17,22 @@ import android.view.ViewGroup;
 import android.widget.Chronometer;
 import android.widget.ImageView;
 import android.widget.TextView;
+import android.widget.Toast;
 
-import com.wdkl.core.ui.event.MsgEvent;
-import com.wdkl.skywebrtc.CallSession;
-import com.wdkl.skywebrtc.EnumType;
-import com.wdkl.skywebrtc.SkyEngineKit;
-import com.wdkl.webrtc.R;
+import com.wdkl.rtc.util.EnumType;
+import com.wdkl.rtc.R;
+import com.wdkl.rtc.entity.MsgEvent;
+import com.wdkl.rtc.rtc.WebRTCEngine;
 
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.Subscribe;
 import org.greenrobot.eventbus.ThreadMode;
 
-/**
- * <pre>
- *     author : Jasper
- *     e-mail : 229605030@qq.com
- *     time   : 2021/02/01
- *     desc   :
- * </pre>
- */
+import java.math.BigInteger;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 public abstract class SingleCallFragment extends Fragment {
     private static final String TAG = "SingleCallFragment";
     ImageView minimizeImageView;
@@ -56,21 +51,13 @@ public abstract class SingleCallFragment extends Fragment {
 
     View lytParent;
 
-    boolean isOutgoing = false;
-
-    SkyEngineKit gEngineKit;
-
+    boolean isOutgoing = true;
 
     CallSingleActivity callSingleActivity;
-
     CallHandler handler;
     boolean endWithNoAnswerFlag = false;
-    boolean isConnectionClosed = false;
-
     public static final int WHAT_DELAY_END_CALL = 0x01;
 
-    public static final int WHAT_NO_NET_WORK_END_CALL = 0x02;
-
     EnumType.CallState currentState;
     HeadsetPlugReceiver headsetPlugReceiver;
 
@@ -103,33 +90,53 @@ public abstract class SingleCallFragment extends Fragment {
 
     @Override
     public void onDestroy() {
-        handler.removeCallbacksAndMessages(null);
         if (EventBus.getDefault().isRegistered(this)) {
             EventBus.getDefault().unregister(this);
         }
         super.onDestroy();
     }
 
-
     abstract int getLayout();
 
-
     @Subscribe(threadMode = ThreadMode.MAIN)
-    public void onEvent(MsgEvent<Object> messageEvent) {
+    public void onEvent(MsgEvent<BigInteger> messageEvent) {
         int code = messageEvent.getCode();
-        Log.d(TAG, "onEvent code = $code; endWithNoAnswerFlag = $endWithNoAnswerFlag");
-        if (code == MsgEvent.CODE_ON_CALL_ENDED) {
-            if (endWithNoAnswerFlag) {
-                didCallEndWithReason(EnumType.CallEndReason.Timeout);
-            } else if (isConnectionClosed) {
-                didCallEndWithReason(EnumType.CallEndReason.SignalError);
-            } else {
-                if (callSingleActivity != null) {
-                    callSingleActivity.finish();
+        if (code==1){
+            runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    callSingleActivity.getCurrentFragment().didCreateLocalVideoTrack();
                 }
-            }
-        } else if (code == MsgEvent.CODE_ON_REMOTE_RING) {
-            descTextView.setText("对方已响铃");
+            });
+        } else if (code ==2){
+            BigInteger remoteUserId = messageEvent.getData();
+            runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    callSingleActivity.getCurrentFragment().didReceiveRemoteVideoTrack(remoteUserId);
+                }
+            });
+        } else if (code==3){
+            BigInteger remoteUserId = messageEvent.getData();
+            runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    Toast.makeText(SingleCallFragment.this.getContext(),"对方挂断",Toast.LENGTH_SHORT);
+                    if (callSingleActivity != null) {
+                        callSingleActivity.finish();
+                    }
+                }
+            });
+        } else if (code==4){
+            runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    Toast.makeText(SingleCallFragment.this.getContext(),"错误",Toast.LENGTH_SHORT);
+                    if (callSingleActivity != null) {
+                        callSingleActivity.finish();
+                    }
+                }
+            });
         }
     }
 
@@ -139,7 +146,6 @@ public abstract class SingleCallFragment extends Fragment {
         callSingleActivity = (CallSingleActivity) getActivity();
         if (callSingleActivity != null) {
             isOutgoing = callSingleActivity.isOutgoing();
-            gEngineKit = callSingleActivity.getEngineKit();
             headsetPlugReceiver = new HeadsetPlugReceiver();
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_HEADSET_PLUG);
@@ -171,8 +177,6 @@ public abstract class SingleCallFragment extends Fragment {
         connectedActionContainer = view.findViewById(R.id.connectedActionContainer);
 
         durationTextView.setVisibility(View.GONE);
-//        nameTextView.setText();
-//        portraitImageView.setImageResource(R.mipmap.icon_default_header);
         if (isOutgoing) {
             handler.sendEmptyMessageDelayed(WHAT_DELAY_END_CALL, 30 * 1000);//30s之后未接通,则挂断电话
         }
@@ -234,27 +238,12 @@ public abstract class SingleCallFragment extends Fragment {
         }, 1500);
     }
 
-    public void didChangeState(EnumType.CallState state) {
-
-    }
+    public void didChangeState(EnumType.CallState state){
 
-    public void didChangeMode(Boolean isAudio) {
     }
-
     public void didCreateLocalVideoTrack() {
     }
-
-    public void didReceiveRemoteVideoTrack(String userId) {
-    }
-
-    public void didUserLeave(String userId) {
-    }
-
-    public void didError(String error) {
-    }
-
-    public void didDisconnected(String error) {
-        handler.sendEmptyMessage(WHAT_NO_NET_WORK_END_CALL);
+    public void didReceiveRemoteVideoTrack(BigInteger userId) {
     }
 
     private void refreshMessage(Boolean isForCallTime) {
@@ -265,11 +254,9 @@ public abstract class SingleCallFragment extends Fragment {
     }
 
     public void startRefreshTime() {
-        CallSession session = SkyEngineKit.Instance().getCurrentSession();
-        if (session == null) return;
         if (durationTextView != null) {
             durationTextView.setVisibility(View.VISIBLE);
-            durationTextView.setBase(SystemClock.elapsedRealtime() - (System.currentTimeMillis() - session.getStartTime()));
+            durationTextView.setBase(SystemClock.elapsedRealtime());
             durationTextView.start();
         }
     }
@@ -287,33 +274,24 @@ public abstract class SingleCallFragment extends Fragment {
                 if (currentState != EnumType.CallState.Connected) {
                     endWithNoAnswerFlag = true;
                     if (callSingleActivity != null) {
-                        SkyEngineKit.Instance().endCall();
+                        callSingleActivity.finish();
                     }
                 }
-            } else if (msg.what == WHAT_NO_NET_WORK_END_CALL) {
-                isConnectionClosed = true;
-                if (callSingleActivity != null) {
-                    SkyEngineKit.Instance().endCall();
-                }
             }
         }
 
     }
 
+    public abstract void onBackPressed();
 
     class HeadsetPlugReceiver extends BroadcastReceiver {
-
         @Override
         public void onReceive(Context context, Intent intent) {
             if (intent.hasExtra("state")) {
-                CallSession session = SkyEngineKit.Instance().getCurrentSession();
-                if (session == null) {
-                    return;
-                }
                 if (intent.getIntExtra("state", 0) == 0) { //拔出耳机
-                    session.toggleHeadset(false);
+                    WebRTCEngine.getInstance().toggleHeadset(false);
                 } else if (intent.getIntExtra("state", 0) == 1) { //插入耳机
-                    session.toggleHeadset(true);
+                    WebRTCEngine.getInstance().toggleHeadset(true);
                 }
             }
         }

+ 15 - 0
janus/src/main/java/com/wdkl/rtc/util/Constant.java

@@ -0,0 +1,15 @@
+package com.wdkl.rtc.util;
+
+import com.wdkl.rtc.janus.JanusClient;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+public class Constant {
+    public final static String GATEWAY_URL="8.129.220.143";
+    public final static String GATEWAY_WS_PORT="8188";
+    public final static String JANUS_URL = "ws://"+Constant.GATEWAY_URL+":" + Constant.GATEWAY_WS_PORT;
+
+    public final static String[] STUN_SERVER = new String[]{"stun:8.129.220.143:3478"};
+    public final static String[] TURN_SERVER = null; //new String[]{"turn:stun.l.google.com:19302|username|password"};
+}

+ 1 - 5
rtc-chat/src/main/java/com/wdkl/skywebrtc/EnumType.java

@@ -1,9 +1,5 @@
-package com.wdkl.skywebrtc;
+package com.wdkl.rtc.util;
 
-/**
- * Created by dds on 2019/8/22.
- * android_shuai@163.com
- */
 public class EnumType {
 
     public enum CallState {

+ 0 - 0
WebRTC/src/main/java/com/wdkl/core/util/OSUtils.java


Some files were not shown because too many files changed in this diff