本文介绍Android端集成AUI Kits的操作方式、注意事项及相关代码示例等内容。

源码说明

源码下载

下载地址请参见源码下载

源码结构

├── AliInteractionLiveDemo-Android  // Demo根目录
│   ├── app                         // Demo代码
│   ├── AUIInteractionBusiness      // AUI无UI接口封装Module
│   ├── AUIInteractionCore          // AUI核心依赖库
│   ├── AUIInteractionUikit         // AUI组件Module
│   ├── AUIInteractionLiveRoom      // AUI直播间

架构图

架构图

环境要求

  • Android 5.0(SDK API Level 21)及以上版本。
  • 建议使用Android Studio 4.0以及以上版本。
  • Android 5.0或以上版本的真机,暂不支持模拟器调试。

前提条件

  • 您已经搭建AppServer并获取了访问域名。搭建步骤,请参见服务端集成
    说明 如果您仅需要跑通Demo体验功能,则无需搭建AppServer,我们在Demo中为您提供已搭建的AppServer域名。
  • 您已获取音视频终端SDK的直播推流和播放器的License授权和License Key。获取方法,请参见获取License

跑通Demo

  1. 下载并解压Demo文件,目录说明如下。下载地址请参见源码下载
    ├── AliInteractionLiveDemo-Android  // Demo根目录
    │   ├── app                         // Demo代码
    │   ├── AUIInteractionBusiness      // AUI无UI接口封装Module
    │   ├── AUIInteractionCore          // AUI核心依赖库
    │   ├── AUIInteractionUikit         // AUI组件Module
    │   ├── AUIInteractionLiveRoom      // AUI直播间                 
  2. 配置工程文件。
    使用Android Studio,选择File > Open,选择上一步下载的Demo工程文件。Android Studio
  3. 链接Android真机,连接成功后显示如下图。
    连接成功
  4. 单击下图绿色运行按钮,构建工程文件。
    运行
  5. 安装到Android真机上,运行互动直播应用。

快速集成

导入源码

下载并导入AUI Lits相关组件。

  1. 克隆AUI互动直播工程代码AliInteractionLiveDemo-Android
  2. 拷贝工程下的AUIInteractionCoreAUIInteractionBusinessAUIInteractionLiveRoomAUIInteractionUikit文件夹到您的工程中。
  3. setting.gradle中完成导入。
    include ':AUIInteractionLiveRoom'
    include ':AUIInteractionCore'
    include ':AUIInteractionBusiness:AUIPlayer'
    include ':AUIInteractionBusiness:AUIMessage'
    include ':AUIInteractionBusiness:AUIAppServer'
    include ':AUIInteractionBusiness:AUIPusher'
    include ':AUIInteractionBusiness:AUIBeauty'
    include ':AUIInteractionUikit:AUIPusherKit'
    include ':AUIInteractionUikit:AUIBarrageKit'
    include ':AUIInteractionUikit:AUINoticeKit'
    include ':AUIInteractionUikit:AUILinkMicKit'
    include ':AUIInteractionUikit:AUIPlayerKit'
    include ':AUIInteractionUikit:AUILikeKit'
    include ':AUIInteractionUikit:AUIBeautyKit'
    include ':AUIInteractionUikit:AUIBaseKit'
  4. 在App的build.gradle文件中添加对应的moudle依赖。
    implementation project(':AUIInteractionLiveRoom')
    implementation project(':AUIInteractionUikit:AUIBaseKit')

工程配置

配置权限、混淆及License文件。

  1. AndroidManifest.xml中配置App的权限,SDK需要以下权限(6.0以上的 Android 系统需要动态申请相机、麦克风权限等):
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  2. proguard-rules.pro文件中,将SDK相关类加入不混淆名单。
    -keep class com.alivc.** { *; }
    -keep class com.aliyun.** { *; }
    -keep class com.aliyun.rts.network.* { *; }
    -keep class org.webrtc.** { *; }
    -keep class com.alibaba.dingpaas.** { *; }
    -keep class com.dingtalk.mars.** { *; }
    -keep class com.dingtalk.bifrost.** { *; }
    -keep class com.dingtalk.mobile.** { *; }
    -keep class org.android.spdy.** { *; }
    -keep class com.alibaba.dingpaas.interaction.** { *; }
    -keep class com.cicada.**{*;}
  3. 配置License文件。
    1. 申请试用License、开通直播推流、播放、美颜、IM等能力,获取License文件和License Key。详细操作,请参见Demo体验
    2. 把License文件放到assets目录下,并修改文件名为license.crt
    3. 注册License Key到AndroidManifest.xml文件中。
      <meta-data
          tools:node="replace"
          android:name="com.aliyun.alivc_license.licensekey"
          android:value="foIVziMaUHaRqgDyhf6b6eb8fcf014af39535d0720a32****"/>
  4. build.gradle文件中增加Maven配置。
    allprojects {
        repositories {
            mavenCentral()
            jcenter()
            google()
            maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases' }
        }
    }
  5. 配置直播互动依赖。
    api 'com.aliyun.sdk.android:aliinteraction-cxx:1.0.0'
    api 'com.aliyun.sdk.android:aliinteraction-android:1.0.0'
    api 'com.aliyun.aio:AliVCSDK_Premium:1.8.0'
  6. 在AUIInteractionLiveRoom工程下找到RetrofitManager文件,修改自己的server访问地址。
    com.aliyun.aliinteraction.liveroom.network.RetrofitManager#SERVER_URL
  7. 配置local.properties文件,设置自己的SDK访问路径。
    sdk.dir=/Users/xx/Library/Android/sdk
    ndk.dir=/Users/xx/Library/Android/ndk
  8. 参照Demo中的CreateRoomActivity(创建房间)、RoomListActivity(房间列表)进行调用。

直播调用流程图

普通直播

普通直播

连麦直播

  • 无人连麦无人连麦
  • 有人连麦有人连麦

API参考

与直播互动SDK封装的消息服务API

public interface AUIMessageService {

    /**
     * 发送弹幕
     *
     * @param content  消息体内容
     * @param callback 回调函数
     */
    void sendComment(String content, Callback<String> callback);

    /**
     * 开始直播
     *
     * @param callback 回调函数
     */
    void startLive(Callback<String> callback);

    /**
     * 结束直播
     *
     * @param callback 回调函数
     */
    void stopLive(Callback<String> callback);

    /**
     * 更新公告
     *
     * @param notice   公告内容
     * @param callback 回调函数
     */
    void updateNotice(String notice, Callback<String> callback);

    /**
     * 申请连麦 (观众端调用)
     *
     * @param receiveId 指定接收消息的人 (该场景为主播id)
     * @param callback  回调函数
     */
    void applyJoinLinkMic(String receiveId, Callback<String> callback);

    /**
     * 处理连麦申请 (主播端调用)
     *
     * @param agree       true: 同意, false: 拒绝
     * @param applyUserId 申请人的ID
     * @param rtcPullUrl  主播端的rtc拉流地址
     * @param callback    回调函数
     */
    void handleApplyJoinLinkMic(boolean agree, String applyUserId, String rtcPullUrl, Callback<String> callback);

    /**
     * 上麦通知
     *
     * @param rtcPullUrl 上麦观众的rtc拉流地址
     */
    void joinLinkMic(String rtcPullUrl, Callback<String> callback);

    /**
     * 下麦通知
     *
     * @param reason 下麦原因
     */
    void leaveLinkMic(String reason, Callback<String> callback);

    /**
     * 踢下麦 (主播端调用)
     *
     * @param userId   踢下麦的用户ID
     * @param callback 回调函数
     */
    void kickUserFromLinkMic(String userId, Callback<String> callback);

    /**
     * 更新麦克风状态
     *
     * @param opened true:打开; false:关闭;
     */
    void updateMicStatus(boolean opened, Callback<String> callback);

    /**
     * 更新摄像头状态
     *
     * @param opened true:打开; false:关闭;
     */
    void updateCameraStatus(boolean opened, Callback<String> callback);

    /**
     * 取消申请连麦 (观众端调用)
     *
     * @param receiveId 指定接收消息的人 (该场景为主播ID)
     */
    void cancelApplyJoinLinkMic(String receiveId, Callback<String> callback);

    /**
     * 命令某人更改麦克风状态
     *
     * @param receiveId 被命令人的ID
     * @param open      true:打开; false:关闭;
     * @param callback  回调函数
     */
    void commandUpdateMic(String receiveId, boolean open, Callback<String> callback);

    /**
     * 命令某人更改摄像头状态
     *
     * @param receiveId 被命令人的ID
     * @param open      true:打开; false:关闭;
     * @param callback  回调函数
     */
    void commandUpdateCamera(String receiveId, boolean open, Callback<String> callback);

    /**
     * 添加消息监听器
     *
     * @param messageListener 消息监听器
     */
    void addMessageListener(AUIMessageListener messageListener);

    /**
     * 移除消息监听器
     *
     * @param messageListener 消息监听器
     */
    void removeMessageListener(AUIMessageListener messageListener);

    /**
     * 移除所有消息监听器
     */
    void removeAllMessageListeners();
}

与直播间AppServer相关的API

public interface ApiService {

    @POST("live/login")
    //登录
    ApiInvoker<AppServerToken> login(@Body LoginRequest request);
    //获取token校验合法性
    @POST("live/token")
    ApiInvoker<Token> getToken(@Body TokenRequest request);
    //创建直播间
    @POST("live/create")
    ApiInvoker<LiveModel> createLive(@Body CreateLiveRequest request);
     //更新直播间信息,比如更新公告等
    @POST("live/update")
    ApiInvoker<LiveModel> updateLive(@Body UpdateLiveRequest request);
    //获取直播间信息,方便进入直播间信息展示
    @POST("live/get")
    ApiInvoker<LiveModel> getLive(@Body GetLiveRequest request);
    //推流成功后, 调用此服务通知服务端更新状态(开播状态)
    @POST("live/start")
    ApiInvoker<Void> startLive(@Body StartLiveRequest request);
    //停止推流后, 调用此服务通知服务端更新状态(停播状态)
    @POST("live/stop")
    ApiInvoker<Void> stopLive(@Body StopLiveRequest request);
    //获取直播间列表
    @POST("live/list")
    ApiInvoker<List<LiveModel>> getLiveList(@Body ListLiveRequest request);
    //主播将最新的麦上成员列表更新到AppServer端,直播间连麦管理模块用
    @POST("live/updateMeetingInfo")
    ApiInvoker<MeetingInfo> updateMeetingInfo(@Body UpdateMeetingInfoRequest request);
    //获取连麦观众信息,直播间连麦管理模块用
    @POST("live/getMeetingInfo")
    ApiInvoker<MeetingInfo> getMeetingInfo(@Body GetMeetingInfoRequest request);
}

组件定制

直播间中涉及到的视图逻辑非常复杂,视图与视图之间还会存在一定的联动逻辑。例如:底部的点赞和顶部的点赞述分别对应点赞逻辑的写和读,底部的输入框和弹幕面板分别对应弹幕逻辑的写和读。

代码设计秉承高内聚低耦合原则,抽象出组件的概念,旨在将视图逻辑在一个独立的范围内自闭环。在房间页面,能看到的每个视图,大到整个信息面板,小到分享、点赞、美颜等图标,都属于组件。

考虑到组件和组件之间有着极为复杂的相对位置关系,SDK内部设计通过setContentView传递的XML资源文件来进行组件的灵活配置。

    <!-- 美颜 -->
    <com.aliyun.auibeauty.LiveBeautyComponent
        android:layout_width="@dimen/margin_normal"
        android:layout_height="@dimen/margin_normal"
        android:layout_marginStart="@dimen/ilr_feature_icon_left_margin"
        android:visibility="visible" />

    <!-- 点赞 -->
    <com.aliyun.auilikekit.LiveLikeComponent
        android:layout_width="@dimen/margin_normal"
        android:layout_height="@dimen/margin_normal"
        android:layout_marginStart="@dimen/ilr_feature_icon_left_margin" />

    <!-- 连麦管理 -->
    <com.aliyun.auilinkmickit.LiveLinkMicNumComponent
        android:layout_width="@dimen/margin_normal"
        android:layout_height="@dimen/margin_normal"
        android:layout_marginStart="@dimen/ilr_feature_icon_left_margin"
        android:visibility="gone" />

    <!-- 查看更多 -->
    <com.aliyun.aliinteraction.uikit.component.LiveMoreComponent
        android:layout_width="@dimen/margin_normal"
        android:layout_height="@dimen/margin_normal"
        android:layout_marginStart="@dimen/ilr_feature_icon_left_margin"
        tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck" />
</com.aliyun.aliinteraction.uikit.component.LiveBottomComponent>

<!-- 信息面板 -->
<com.aliyun.auibarrage.LiveBarrageComponent
    android:id="@+id/room_message_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@id/room_bottom_layout"
    android:layout_marginStart="@dimen/ilr_feature_icon_left_margin" />