## 投票组件



### 版本历史

| 版本号 | 更新时间  | 更新描述             |
| ------ | --------- | -------------------- |
| 1.0.1  | 2022.5.7  | 投票组件上线         |
| 1.2.4  | 2023.8.7  | 修复已知问题         |
| 1.2.6  | 2023.12.1 | 升级依赖Glide4.x版本 |
| 1.2.7  | 2024.2.2  | 修复已知问题         |



### 组件引入

注意：所有使用互动组件必须要引入basemodule库，最新版本见 [互动组件对接文档](互动组件/互动组件对接文档)

项目根目录build.gradle引入：

```groovy
 repositories {
     maven { url 'http://nexus-app.bokecc.com/repository/sdk-group/' }
 }
```


module的build.gradle引入：

```java
 dependencies {
     api ('com.bokecc:basemodule:x.x.x')
     api ('com.bokecc.module:votemodule:x.x.x')
 }
```

Application的onCreate方法中，调用`DWLiveEngine.init`初始化dwlivesdk后，添加代码：

```java
VoteInteractSDK.getInstance().init(app);
```



### 1. 组件描述

投票组件是基于基础组件库扩展的投票组件服务，通过IM组件实现投票活动事件的实时推送，包括获取投票列表，获取投票详情、发送投票等功能，为业务方提供投票能力。投票组件包含管理器和基于管理器实现的UI界面，接入方可基于管理器对外API实现完全自定义UI的投票，也可直接集成组件SDK提供的UI。



### 2. 组件架构

#### 2.1 组件架构图

![image-20220506100931572](组件架构图.png)

#### 2.2 核心对外API

IVoteManager内部唯一实现类为VoteManagerImpl

| 作用         | API                                                          |
| ------------ | ------------------------------------------------------------ |
| 初始化       | init(BaseVoteListener listener, String userId, String roomId, String interactToken) |
| 发送投票     | sendVote(String activityId, List<Integer> optionIdList, IBaseCallBack<Object> callBack) |
| 获取投票列表 | getVoteList(IBaseCallBack<List<VoteResult>> callBack)        |
| 获取投票详情 | getVoteDetail(String activityId, IBaseCallBack<VoteBean> callBack) |
| 重连         | reConnect()                                                  |
| 释放         | release()                                                    |

API接口代码

```java
public interface IVoteManager {

    /**
     * @param listener      监听
     * @param userId        viewerId
     * @param roomId        房间id
     * @param interactToken token
     */
    void init(BaseVoteListener listener, String userId, String roomId, String interactToken);

    /**
     * 投票
     *
     * @param activityId   id
     * @param optionIdList 选择的id
     * @param callBack     回调
     */
    void sendVote(String activityId, List<Integer> optionIdList, IBaseCallBack<Object> callBack);

    /**
     * 投票结果列表
     *
     * @param callBack 回调
     */
    void getVoteList(IBaseCallBack<List<VoteResult>> callBack);

    /**
     * 获取正在进行的投票
     *
     * @param callBack 回调
     */
    void getVoting(IBaseCallBack<VoteBean> callBack);

    /**
     * 获取投票详情
     *
     * @param activityId 投票活动id
     * @param callBack 回调
     */
    void getVoteDetail(String activityId, IBaseCallBack<VoteBean> callBack);

    /**
     * 重连
     */
    void reConnect();

    /**
     * 释放
     */
    void release();

}
```





#### 2.3 数据参数定义

数据类参数说明

```java
public class VoteBean {

    /**
     * 投票id
     */
    private String activityId;
    /**
     * 业务线
     */
    private String businessLine;
    /**
     * 客户id
     */
    private String accountId;
    /**
     * 房间id
     */
    private String roomId;

    /**
     * 标题
     */
    private String title;
    /**
     * 截止时间
     */
    private String endTime;
    /**
     * 主题色:1.白色 2.绿色 3红色 4橙色 5蓝色
     */
    private int themeColor;
    /**
     * 显示banner
     */
    private int showBanner;
    /**
     * 投票形式 1.图文 2.文字
     */
    private int voteForm;
    /**
     * 选项类型 1.单选 2.多选
     */
    private int voteType;
    /**
     * 多选限制 0为不限制
     */
    private int voteLimit;
    /**
     * 显示结果 0 不显示 1显示
     */
    private int showResult;
    /**
     * 参加人数
     */
    private int voteCount;
    /**
     * 状态:  0未开始 1.投票中 2.已结束
     */
    private int status;
    /**
     * 选项
     */
    private List<VoteOptionsDTO> voteOptions;
    /**
     * banner图片地址
     */
    private String bannerUrl;
}

```



### 3. 组件接入

#### 3.1 使用组件提供UI

投票ViewGroup为VoteMainLayout

1. 登录业务SDK（云直播等）

2. xml中添加VoteMainLayout

   ```xml
   <?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:background="#eeeeee"
       android:orientation="vertical">
   
   
       <com.bokecc.vote.ui.VoteMainLayout
           android:id="@+id/vote_layout"
           android:layout_width="match_parent"
           android:layout_height="match_parent"/>
   
   </LinearLayout>
   ```

3. 设置VoteMainLayout的Listener

   ```java
   voteLayout.setVoteMainListener(new IVoteMainListener() {
                       @Override
                       public void onVoteStart() {
                           Toast.makeText(VoteTestActivity.this,"投票开始",Toast.LENGTH_SHORT).show();
                       }
   
                       @Override
                       public void onVoteEnd() {
                           Toast.makeText(VoteTestActivity.this,"投票结束",Toast.LENGTH_SHORT).show();
   
                       }
   
                       @Override
                       public void onCloseClick() {
                         //投票面板关闭回调
                           Toast.makeText(VoteTestActivity.this,"close",Toast.LENGTH_SHORT).show();
   
                       }
                   });
   ```

4. 初始化组件

   1. 获取token-初始化投票需要传递参数token，可以通过业务SDK（云直播等）提供的对外API获取token

   2. 获取正在进行活动-如果需要进入时就展示互动组件，需要调用业务SDK提供的正在进行中组件活动API获取正在进行的活动

   3. 初始化组件-使用前两步获取的信息初始化组件SDK

      代码示例（以云直播为例）：

   ```java
   DWLive..getInstance().getInteractiveToken(new BaseCallback<String>() {
                       @Override
                       public void onError(String error) {
   
                       }
   
                       @Override
                       public void onSuccess(String token) {
                           //获取正在进行的互动
                           DWLive.getInstance().getInteractiveOngoing(new BaseCallback<List<InteractionOngoing>>() {
                               @Override
                               public void onError(String error) {
                                   initVote(token,
                                           loginInfo.getUserId(),
                                           loginInfo.getRoomId(),
                                           false,
                                           ""
                                   );
   
                               }
   
                               @Override
                               public void onSuccess(List<InteractionOngoing> interactionOngoings) {
                                   //是否正在进行
                                   boolean isOngoing = false;
                                   String ongoingId = "";
                                   if (interactionOngoings != null) {
                                       for (int i = 0; i < interactionOngoings.size(); i++) {
                                         //  互动组件红包雨 TYPE_INTERACT_RED_PACKET = 6;
                                         // 互动组件投票 TYPE_INTERACT_VOTE = 7;
                                           if (interactionOngoings.get(i).getType() == InteractionOngoing.TYPE_INTERACT_VOTE) {
                                               isOngoing = true;
                                               ongoingId = interactionOngoings.get(i).getId();
                                               break;
                                           }
                                       }
                                   }
   
                                   initVote(
                                           token,
                                           loginInfo.getUserId(),
                                           loginInfo.getRoomId(),
                                           isOngoing,
                                           ongoingId
                                   );
                               }
                           });
                       }
                   });
   
   
   
   
   private void initVote(String token, String userId, String roomId, boolean isOngoing, String ongoingId) {
     //获取组件开关，用于判断房间组件是否开启，以云直播为例
           if (DWLive.getInstance().getInteractionConfigure().getVoteSwitch() == 1) {
               voteLayout.initialize(new VoteBaseLayout.VoteConfig()
                       .setInteractToken(token)
                       .setUserId(userId)
                       .setRoomId(roomId)
                       .setOngoing(isOngoing)
                       .setOngoingId(ongoingId));
           }
       }
   ```

5. 销毁组件

   ```java
   @Override
       protected void onDestroy() {
           super.onDestroy();
           voteLayout.release();
       }
   ```



#### 3.2 使用组件管理器+自定义UI

投票管理器实现类为VoteManagerImpl，对外方法参照IVoteManager，UI可以参考VoteBaseLayout以及其子类VoteMainLayout实现



### 4. 混淆配置

混淆配置

```
-keep class com.bokecc.**{*;}
-keep interface com.bokecc.**{*;}
```



### 5. 组件库依赖

```groovy
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.github.bumptech.glide:glide:4.9.0'
```