安卓 SDK
微议Pro Android SDK 以 WySdk 为主入口类,提供会议创建、加入、音视频流发布与订阅等能力。本文档说明入会完整流程与相关 API。
使用前
- 将 SDK 包集成到 Android 工程(具体 AAR / Gradle 坐标请联系微议Pro 技术支持获取)。
- 在
AndroidManifest.xml中声明摄像头、麦克风、网络等必要权限。 apiUrl需指向已部署的微议Pro Web 服务器 API 地址(HTTPS 推荐)。- 调用任何 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: 入会失败怎么办?
请检查:
- 网络连接是否正常
- 会议号与密码是否正确
apiUrl是否指向正确的微议Pro API 地址onFailed回调中的错误信息
Q2: 如何判断入会是否成功?
- 实现
JoinSuccessListener接口 - 调用
addjoinSuccessListener()注册监听 - 在
onJoinSuccess()中处理入会成功逻辑
Q3: 为什么视频无法发布?
请检查:
- 是否已创建本地用户
- 是否已创建视频流
- 摄像头权限是否已授予
- 使用
watchSelfAdd()和watchSelfRemove()管理观看者
Q4: 如何处理多设备场景?
SDK 支持多设备,每个设备使用唯一的 deviceId:
java
String deviceId = WySdk.getInstance().getDeviceId(context);十一、注意事项
- 初始化顺序:必须先调用
init()再调用其他方法 - 权限要求:需授予摄像头与麦克风权限
- 线程安全:SDK 内部已做线程处理,可在任意线程调用
- 生命周期:在 Activity / Fragment 的
onDestroy中调用exitMeeting()或clear() - 网络依赖:入会需要稳定的网络连接
- 错误处理:务必实现回调接口,及时处理错误信息
版本信息
| 项目 | 版本 |
|---|---|
| SDK | 3.0.1 |
| 文档 | 1.0 |
| 更新日期 | 2025-06-05 |
相关服务端接口见 Web 服务器 API。SDK 包与 Gradle 集成细节请联系微议Pro 技术支持。
