Skip to content

安卓 SDK

微议Pro Android SDK 以 WySdk 为主入口类,提供会议创建、加入、音视频流发布与订阅等能力。本文档说明入会完整流程与相关 API。

使用前

  1. 将 SDK 包集成到 Android 工程(具体 AAR / Gradle 坐标请联系微议Pro 技术支持获取)。
  2. AndroidManifest.xml 中声明摄像头、麦克风、网络等必要权限。
  3. apiUrl 需指向已部署的微议Pro Web 服务器 API 地址(HTTPS 推荐)。
  4. 调用任何 SDK 方法前,必须先完成 init()

一、初始化 SDK

1.1 基础初始化

java
/**
 * 初始化 SDK
 * @param appContent 应用上下文
 * @param apiUrl API 服务地址
 */
public void init(Context appContent, String apiUrl)

示例:

java
WySdk.getInstance().init(getApplicationContext(), "https://api.example.com");

1.2 初始化(带音频增强)

java
/**
 * 初始化 SDK(带音频回声消除和噪声抑制)
 * @param appContent 应用上下文
 * @param apiUrl API 服务地址
 * @param useAEC_NS 是否启用 AEC/NS 音频增强
 */
public void init(Context appContent, String apiUrl, boolean useAEC_NS)

示例:

java
WySdk.getInstance().init(getApplicationContext(), "https://api.example.com", true);

二、检查会议信息

在加入会议前,可检查会议是否存在以及是否需要密码。

2.1 检查会议(无密码)

java
/**
 * 检查会议信息
 * @param context 上下文
 * @param serial 会议号
 * @param callback 回调接口
 */
public void checkMeeting(Context context, String serial, WyCallback<WyMeetingResponse> callback)

示例:

java
WySdk.getInstance().checkMeeting(this, "123456", new WyCallback<WyMeetingResponse>() {
    @Override
    public void onSuccess(WyMeetingResponse response) {
        // 会议存在,可以加入
        WyMeetingBean meeting = response.getMeeting();
        String roomId = meeting.getRoomid();
    }

    @Override
    public void onFailed(WyError error) {
        // 会议不存在或其他错误
        Toast.makeText(this, "加入失败: " + error.getMessage(), Toast.LENGTH_SHORT).show();
    }
});

2.2 检查会议(带密码)

java
/**
 * 检查会议信息(带密码验证)
 * @param context 上下文
 * @param serial 会议号
 * @param sig 会议密码
 * @param callback 回调接口
 */
public void checkMeeting(Context context, String serial, String sig, WyCallback<WyMeetingResponse> callback)

示例:

java
WySdk.getInstance().checkMeeting(this, "123456", "password123", new WyCallback<WyMeetingResponse>() {
    @Override
    public void onSuccess(WyMeetingResponse response) {
        // 验证成功
    }

    @Override
    public void onFailed(WyError error) {
        // 密码错误或会议不存在
        String errorMsg = error.getMessage();
        if (errorMsg.contains("1002")) {
            Toast.makeText(this, "密码错误", Toast.LENGTH_SHORT).show();
        } else if (errorMsg.contains("1001")) {
            Toast.makeText(this, "会议不存在", Toast.LENGTH_SHORT).show();
        }
    }
});

三、设置监听器

在加入会议前,需要设置各类事件监听器。

3.1 设置主观察者

java
/**
 * 设置 SDK 主观察者
 * @param wyObserver 观察者接口
 */
public void setWyObserver(WyObserver wyObserver)

3.2 设置流观察者

java
/**
 * 设置流观察者(监听音视频流变化)
 * @param wyObserver 流观察者接口
 */
public void setStreamObserver(StreamObserver wyObserver)

3.3 设置消息观察者

java
/**
 * 设置消息观察者(监听文本消息)
 * @param wyObserver 消息观察者接口
 */
public void setMessageObserver(MessageObserver wyObserver)

3.4 设置主席控制观察者

java
/**
 * 设置主席控制观察者
 * @param wyObserver 主席控制观察者接口
 */
public void setControlChairmanObserver(ControlChairmanObserver wyObserver)

3.5 添加入会成功监听器

java
/**
 * 添加入会成功监听器
 * @param listener 入会成功监听器
 */
public void addjoinSuccessListener(JoinSuccessListener listener)

完整示例:

java
// 设置主观察者
WySdk.getInstance().setWyObserver(new WyObserver() {
    @Override
    public void onMeetingLeft() {
        // 离开会议回调
    }

    @Override
    public void onError(WyError error) {
        // 错误回调
    }
});

// 设置流观察者
WySdk.getInstance().setStreamObserver(new StreamObserver() {
    @Override
    public void onRemoteUserAdded(RemoteUser remoteUser) {
        // 远程用户加入
    }

    @Override
    public void onRemoteUserRemoved(RemoteUser remoteUser) {
        // 远程用户离开
    }

    @Override
    public void onStreamAdded(Stream stream) {
        // 新增流
    }

    @Override
    public void onStreamRemoved(Stream stream) {
        // 移除流
    }
});

// 设置消息观察者
WySdk.getInstance().setMessageObserver(new MessageObserver() {
    @Override
    public void onTextMessage(MessageBean message) {
        // 收到文本消息
    }
});

// 添加入会成功监听
WySdk.getInstance().addjoinSuccessListener(new JoinSuccessListener() {
    @Override
    public void onJoinSuccess() {
        // 入会成功后的操作
        Log.d(TAG, "入会成功");
        // 创建本地用户
        // 发布音视频流等
    }
});

四、加入会议

4.1 普通入会

java
/**
 * 加入会议(标准版)
 * @param activity 当前 Activity
 * @param userId 用户 ID
 * @param nickName 昵称
 * @param serial 会议号
 * @param sig 会议密码,无密码填 null
 * @param role 用户角色(RoleType.Type)
 */
public void joinMeeting(AppCompatActivity activity, String userId,
                        String nickName, String serial, String sig,
                        @RoleType.Type String role)

角色类型:

常量说明
RoleType.USER普通用户
RoleType.SPEAKER演讲者
RoleType.CHAIRMAN主席

示例:

java
// 无密码入会
WySdk.getInstance().joinMeeting(
    this,
    "user_001",
    "张三",
    "123456",
    null,
    RoleType.USER
);

// 有密码入会
WySdk.getInstance().joinMeeting(
    this,
    "user_001",
    "张三",
    "123456",
    "password123",
    RoleType.USER
);

4.2 HD 版入会

java
/**
 * 加入会议(HD 版)
 * @param activity 当前 Activity
 * @param userId 用户 ID
 * @param nickName 昵称
 * @param serial 会议号
 * @param role 用户角色
 */
public void joinHDMeeting(Activity activity, String userId,
                          String nickName, String serial,
                          @RoleType.Type String role)

示例:

java
WySdk.getInstance().joinHDMeeting(
    this,
    "user_001",
    "张三",
    "123456",
    RoleType.USER
);

五、创建本地用户

入会成功后,需要创建本地用户实例。

java
/**
 * 创建本地用户
 * @param openCamera 是否开启摄像头
 * @param nickName 昵称
 * @param mdeviceId 设备 ID
 * @param userId 用户 ID
 * @param role 用户角色
 * @param userDeviceType 用户设备类型
 */
public void creatLocalUser(boolean openCamera, String nickName, String mdeviceId,
                          String userId, String role, String userDeviceType)

示例:

java
String deviceId = WySdk.getInstance().getDeviceId(this);

WySdk.getInstance().creatLocalUser(
    true,                    // 开启摄像头
    "张三",                  // 昵称
    deviceId,                // 设备 ID
    "user_001",             // 用户 ID
    RoleType.USER,          // 角色
    "android"               // 设备类型
);

六、发布和订阅音视频流

6.1 创建本地视频流

java
/**
 * 创建本地视频流(默认参数)
 * @param deviceId 设备 ID
 */
public void creatLocalVideoStream(String deviceId)

/**
 * 创建本地视频流(自定义参数)
 * @param deviceId 设备 ID
 * @param width 视频宽度
 * @param height 视频高度
 * @param fps 帧率
 */
public void creatLocalVideoStream(String deviceId, int width, int height, int fps)

示例:

java
// 使用默认参数(1280x720 @ 30fps)
String deviceId = WySdk.getInstance().getLocalUser().getMDeviceId();
WySdk.getInstance().creatLocalVideoStream(deviceId);

// 使用自定义参数
WySdk.getInstance().creatLocalVideoStream(deviceId, 1920, 1080, 30);

6.2 发布视频流

java
/**
 * 发布视频流
 * @param videoDeviceId 视频设备 ID
 */
public void publishVideo(String videoDeviceId)

/**
 * 发布视频流(强制模式)
 * @param videoDeviceId 视频设备 ID
 * @param force 是否强制发布
 */
public void publishVideo(String videoDeviceId, boolean force)

示例:

java
String deviceId = WySdk.getInstance().getLocalUser().getMDeviceId();
WySdk.getInstance().publishVideo(deviceId);

6.3 发布音频流

java
/**
 * 发布音频流
 */
public void publishAudio()

示例:

java
WySdk.getInstance().setPublishAudioCallBack(new WyCallback<Boolean>() {
    @Override
    public void onSuccess(Boolean result) {
        Log.d(TAG, "音频发布成功");
    }

    @Override
    public void onFailed(WyError error) {
        Log.e(TAG, "音频发布失败: " + error.getMessage());
    }
});

WySdk.getInstance().publishAudio();

6.4 订阅远程视频

java
/**
 * 订阅远程视频流
 * @param wySurface 显示视图
 * @param wyStreamBean 流信息
 */
public void subscribeVideo(WySurface wySurface, WyStreamBean wyStreamBean)

示例:

java
@Override
public void onStreamAdded(Stream stream) {
    WySurface surface = new WySurface(context);
    WyStreamBean streamBean = new WyStreamBean(stream);
    WySdk.getInstance().subscribeVideo(surface, streamBean);
}

6.5 订阅远程音频

java
/**
 * 订阅远程音频流
 * @param remoteUser 远程用户
 */
public void subscribeAudio(RemoteUser remoteUser)

示例:

java
WySdk.getInstance().subscribeAudio(remoteUser);

七、完整入会流程示例

java
public class MeetingActivity extends AppCompatActivity {

    private static final String TAG = "MeetingActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 1. 初始化 SDK
        WySdk.getInstance().init(this, "https://api.example.com");

        // 2. 设置监听器
        setupObservers();

        // 3. 检查并加入会议
        joinMeeting();
    }

    private void setupObservers() {
        WySdk.getInstance().setWyObserver(new WyObserver() {
            @Override
            public void onMeetingLeft() {
                Log.d(TAG, "已离开会议");
                finish();
            }

            @Override
            public void onError(WyError error) {
                Log.e(TAG, "SDK 错误: " + error.getMessage());
            }
        });

        WySdk.getInstance().setStreamObserver(new StreamObserver() {
            @Override
            public void onRemoteUserAdded(RemoteUser remoteUser) {
                Log.d(TAG, "用户加入: " + remoteUser.getUserId());
                subscribeRemoteStreams(remoteUser);
            }

            @Override
            public void onRemoteUserRemoved(RemoteUser remoteUser) {
                Log.d(TAG, "用户离开: " + remoteUser.getUserId());
            }

            @Override
            public void onStreamAdded(Stream stream) {
                Log.d(TAG, "流添加: " + stream.getDeviceId());
            }

            @Override
            public void onStreamRemoved(Stream stream) {
                Log.d(TAG, "流移除: " + stream.getDeviceId());
            }
        });

        WySdk.getInstance().addjoinSuccessListener(new JoinSuccessListener() {
            @Override
            public void onJoinSuccess() {
                Log.d(TAG, "入会成功");
                createAndPublishLocalStream();
            }
        });
    }

    private void joinMeeting() {
        WySdk.getInstance().checkMeeting(this, "123456", new WyCallback<WyMeetingResponse>() {
            @Override
            public void onSuccess(WyMeetingResponse response) {
                WySdk.getInstance().joinMeeting(
                    MeetingActivity.this,
                    "user_001",
                    "张三",
                    "123456",
                    null,
                    RoleType.USER
                );
            }

            @Override
            public void onFailed(WyError error) {
                Toast.makeText(MeetingActivity.this,
                    "加入失败: " + error.getMessage(),
                    Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void createAndPublishLocalStream() {
        String deviceId = WySdk.getInstance().getDeviceId(this);
        WySdk.getInstance().creatLocalUser(
            true,
            "张三",
            deviceId,
            "user_001",
            RoleType.USER,
            "android"
        );

        WySdk.getInstance().creatLocalVideoStream(deviceId);
        WySdk.getInstance().publishVideo(deviceId);
        WySdk.getInstance().publishAudio();
    }

    private void subscribeRemoteStreams(RemoteUser remoteUser) {
        WySdk.getInstance().subscribeAudio(remoteUser);

        List<Stream> streams = remoteUser.getStreams();
        for (Stream stream : streams) {
            if (stream.getMedia() == Stream.MediaType.VIDEO ||
                stream.getMedia() == Stream.MediaType.AUDIO_VIDEO) {
                WySurface surface = new WySurface(this);
                WyStreamBean streamBean = new WyStreamBean(stream);
                WySdk.getInstance().subscribeVideo(surface, streamBean);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        WySdk.getInstance().exitMeeting();
    }
}

八、入会流程图

┌─────────────────────────────────────────────────────────┐
│                      开始入会流程                         │
└─────────────────────────┬───────────────────────────────┘


┌─────────────────────────────────────────────────────────┐
│  1. 初始化 SDK                                            │
│  WySdk.getInstance().init(context, apiUrl)             │
└─────────────────────────┬───────────────────────────────┘


┌─────────────────────────────────────────────────────────┐
│  2. 设置监听器                                            │
│  - setWyObserver()                                      │
│  - setStreamObserver()                                  │
│  - setMessageObserver()                                 │
│  - addjoinSuccessListener()                             │
└─────────────────────────┬───────────────────────────────┘


┌─────────────────────────────────────────────────────────┐
│  3. 检查会议信息                                          │
│  checkMeeting(serial, callback)                         │
└─────────────────────────┬───────────────────────────────┘

                ┌─────────┴─────────┐
                │                   │
                ▼                   ▼
          ┌─────────┐        ┌─────────┐
          │ 成功    │        │ 失败    │
          └────┬────┘        └────┬────┘
               │                  │
               ▼                  ▼
    ┌──────────────────┐   ┌─────────────────┐
    │ 4. 加入会议        │   │ 提示错误信息     │
    │ joinMeeting()    │   │ 结束流程         │
    └────────┬─────────┘   └─────────────────┘


    ┌──────────────────┐
    │ 5. 等待入会成功   │
    │ (异步回调)       │
    └────────┬─────────┘


    ┌──────────────────┐
    │ 6. 创建本地用户   │
    │ creatLocalUser() │
    └────────┬─────────┘


    ┌──────────────────┐
    │ 7. 创建视频流     │
    │ creatLocalVideo  │
    │ Stream()         │
    └────────┬─────────┘


    ┌──────────────────┐
    │ 8. 发布音视频流   │
    │ - publishVideo() │
    │ - publishAudio() │
    └────────┬─────────┘


    ┌──────────────────┐
    │ 9. 订阅远程流     │
    │ (当用户加入时)    │
    └────────┬─────────┘


┌─────────────────────────────────────────────────────────┐
│                    入会完成                              │
│              正常进行音视频通话                            │
└─────────────────────────────────────────────────────────┘

九、其他重要 API

9.1 获取屏幕尺寸

java
public int getScreenWidth()   // 获取屏幕宽度
public int getScreenHeight()  // 获取屏幕高度

9.2 获取本地用户

java
public LocalUser getLocalUser()

9.3 离开会议

java
public void exitMeeting()

9.4 清理资源

java
public void clear()  // 清理所有资源并离开会议

9.5 摄像头控制

java
public void openCamera()        // 开启摄像头
public void closeCamera()       // 关闭摄像头
public void switchCamera()      // 切换摄像头

9.6 音频控制

java
public void publishAudio()      // 发布音频
public void unPublishAudio()    // 停止发布音频
public boolean isAudioOpen()    // 检查音频是否开启

十、常见问题

Q1: 入会失败怎么办?

请检查:

  1. 网络连接是否正常
  2. 会议号与密码是否正确
  3. apiUrl 是否指向正确的微议Pro API 地址
  4. onFailed 回调中的错误信息

Q2: 如何判断入会是否成功?

  1. 实现 JoinSuccessListener 接口
  2. 调用 addjoinSuccessListener() 注册监听
  3. onJoinSuccess() 中处理入会成功逻辑

Q3: 为什么视频无法发布?

请检查:

  1. 是否已创建本地用户
  2. 是否已创建视频流
  3. 摄像头权限是否已授予
  4. 使用 watchSelfAdd()watchSelfRemove() 管理观看者

Q4: 如何处理多设备场景?

SDK 支持多设备,每个设备使用唯一的 deviceId

java
String deviceId = WySdk.getInstance().getDeviceId(context);

十一、注意事项

  1. 初始化顺序:必须先调用 init() 再调用其他方法
  2. 权限要求:需授予摄像头与麦克风权限
  3. 线程安全:SDK 内部已做线程处理,可在任意线程调用
  4. 生命周期:在 Activity / Fragment 的 onDestroy 中调用 exitMeeting()clear()
  5. 网络依赖:入会需要稳定的网络连接
  6. 错误处理:务必实现回调接口,及时处理错误信息

版本信息

项目版本
SDK3.0.1
文档1.0
更新日期2025-06-05

相关服务端接口见 Web 服务器 API。SDK 包与 Gradle 集成细节请联系微议Pro 技术支持。

微议Pro SDK 开发者文档