Android integration

更新时间:
复制 MD 格式

Interaction Message enhances communication and engagement in live streaming rooms. Its SDK lets you add comments, bullet comments, and likes to your Android app with minimal effort.

Prerequisites

Complete the server-side integration and provide a client-accessible API endpoint for obtaining authentication tokens before you proceed. For more information, see Server-side integration.

Environment requirements

  • Android 5.0 (API level 21) or later.

  • Android Studio 4.0 or later.

Integrate the SDK

  1. Add the Maven repository.

    repositories {
        maven { url 'https://maven.aliyun.com/repository/releases' }
    }
  2. Add the SDK dependency.

    // Interaction library
    // Replace x.y.z with the specific SDK version number, for example, 1.9.0.
    // You can find the latest version number in the release notes.
    implementation "com.aliyun.sdk.android:AliVCInteractionMessage:x.y.z"
  3. Configure permissions in AndroidManifest.xml.

       <uses-permission android:name="android.permission.INTERNET" />
       <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  4. In your project's proguard-rules.pro file, add the following code to prevent SDK code obfuscation.

    Note

    You must add these obfuscation rules for SDK versions v1.4.0 and v1.4.1. For other versions, this is optional as the rules can be automatically imported from the AAR package.

    ###################### Obfuscation Rules #########################
    -keep class com.aliyun.im.common.** { *; }
    -keepclassmembers class com.aliyun.im.common.** { *; }
    -keep class com.aliyun.im.interaction.** { *; }
    -keepclassmembers class com.aliyun.im.interaction.** { *; }
    -keep interface com.aliyun.im.AliVCIMInterface { *; }
    -keep interface com.aliyun.im.AliVCIMGroupInterface { *; }
    -keep interface com.aliyun.im.AliVCIMMessageInterface { *; }

Use the SDK

Follow this sequence when using the SDK:

  1. Initialize

  2. Log in

  3. Perform operations

  4. Log out

  5. Uninitialize

  6. Other

Core operations cover group management and messaging:

Core operations

  • Group operations

    • Create a group (requires administrator privileges)

    • Close a group (group owner or group administrator only)

    • Join a group

    • Leave a group

    • Query group information

    • Modify group information (group owner or group administrator only)

    • List recent group members

    • List all group members (group owner or group administrator only)

    • Mute a group (group owner or group administrator only)

    • Unmute a group (group owner or group administrator only)

    • Mute specific users in a group (group owner or group administrator only)

    • Unmute specific users in a group (group owner or group administrator only)

    • List muted users in a group (group owner or group administrator only)

  • Message operations

    • Send a C2C message

    • Send a group message

    • List recent group messages

    • List all group messages (group owner or group administrator only)

    • Delete or retract a group message

    • Query historical messages

Usage notes

All IDs must follow these rules:

appid: Can be up to 64 characters long and can only contain uppercase letters (A-Z), lowercase letters (a-z), numbers (0-9), and hyphens (-).

userid: Can be up to 64 characters long and can only contain uppercase letters (A-Z), lowercase letters (a-z), numbers (0-9), and hyphens (-).

groupid: Can be up to 64 characters long and can only contain uppercase letters (A-Z), lowercase letters (a-z), numbers (0-9), and hyphens (-).

Initialize

Initialize the SDK at your app's entry point, for example, in the onCreate method of your Application or Activity class.

ImSdkConfig config = new ImSdkConfig();
config.deviceId = "deviceId"; // [Optional]
config.appId = "appId"; // [Required] Your AppId. Initialization fails with error code -2 if this parameter is empty. Replace the placeholder with the AppId obtained after creating your application.
config.appSign = "appSign"; // [Required] Your AppSign. Initialization fails with error code -2 if this parameter is empty. Replace the placeholder with the AppSign obtained after creating your application.
config.logLevel = ImLogLevel.DEBUG; // [Optional] Sets the minimum log level. Defaults to ImLogLevel.DEBUG. To disable logging, set to ImLogLevel.NONE.
// A non-zero return value indicates that initialization failed. Error codes: 1001 (already initialized), 1002 (failed to create the underlying engine), -1 (underlying component already initialized), -2 (invalid configuration).
int ret = AliVCIMEngine.instance().init(context, config);

Listen for connection status

AliVCIMEngine.instance().addSdkListener(new ImSdkListener() {
    @Override
    public void onConnecting() {

    }
    @Override
    public void onConnectSuccess() {
    }
    @Override
    public void onConnectFailed(com.aliyun.im.common.Error error) {
    }
    @Override
    public void onDisconnect(int code) {
    }
    // This callback is invoked when the authentication token expires. You must implement it to provide a new token.
    @Override
    public void onTokenExpired(ImTokenCallback callback) {
        // Step 1: Generate a new token. If this involves a time-consuming operation like a network request, perform it on a background thread.
        // Step 2: If token generation fails, call callback.onError() with the error information.
        // If token generation succeeds, call callback.onSuccess() with the new token.
    }
    @Override
    public void onReconnectSuccess(ArrayList<ImGroupInfo> groupStatus) {
    }

    /**
     * Starting from v1.4.1, a new callback for connection status is available. There are four states:
     * ImLinkState.IDLE: The initial state before you log in.
     * ImLinkState.CONNECTING: The state while connecting or reconnecting.
     * ImLinkState.CONNECTED: The state after a successful connection or reconnection.
     * ImLinkState.DISCONNECTED: The state when disconnected due to network issues or other exceptions.
     * 
     * You can use these state transitions to provide user feedback, such as displaying a "Check your network connection" message when the state changes from CONNECTED to DISCONNECTED.
     */
    @Override
    public void onLinkStateEvent(ImLinkStateEvent event) {
        // Get the previous connection state.
        ImLinkState previousState = event.getPreviousState();
        // Get the current connection state. Note: The variable name 'currentStateState' in the sample code contains a typo and should be interpreted as 'currentState'.
        ImLinkState currentStateState = event.getCurrentState();
    }
});

Log in

ImLoginReq req = new ImLoginReq();

req.user.userId = userId;
// Pass custom business data.
Map<String, Object> data = new HashMap<>();
data.put("level", "high");
req.user.userExtension = App.getGson().toJson(data).toString();

req.userAuth = new ImAuth(nonce,  timestamp, role, app_token);
AliVCIMEngine.instance().login(req, new ImSdkCallback());

The role parameter specifies the user's role:

  • Administrator (value: admin)

    Grants administrator privileges, including creating and closing groups, in addition to all non-administrator operations.

  • Non-administrator (value: any string other than admin)

Log out

AliVCIMEngine.instance().logout();

Uninitialize

Call this method after you log out to release SDK resources.

 AliVCIMEngine.instance().unInit();

Message service

// Get the message service instance.
AliVCIMMessageInterface messageInterface = AliVCIMEngine.instance().getMessageManager();

Non-administrator operations

Add message listener

// Add a listener for incoming messages.
messageInterface.addMessageListener(new ImMessageListener() {
    @Override
    public void onRecvC2cMessage(ImMessage msg) {
        
    }
    @Override
    public void onRecvGroupMessage(ImMessage msg, String groupId) {
    }

    @Override
    public void onDeleteGroupMessage(String msgId, String groupId) {
    }
});

Send a C2C message

ImSendMessageToUserReq req = new ImSendMessageToUserReq();
req.type = 88888;
req.data = "This is a test message";
req.receiverId = userInput.getText().toString();
// The receiver must be online. Otherwise, the operation fails with error code 424. We recommend retrying after the receiver comes online.
messageInterface.sendC2cMessage(req, new ImSdkValueCallback<ImSendMessageToUserRsp>() {
    @Override
    public void onSuccess(ImSendMessageToUserRsp data) {
        Log.v(ImTag.TAG, "Successfully sent C2C message:" + data.messageId);
    }
    @Override
    public void onFailure(Error error) {
        Log.v(ImTag.TAG, "Failed to send C2C message. Error code:" + error.code);
    }
});

Send group message

You can set the message level by using req.level = ImMessageLevel.NORMAL. The default level is NORMAL. For more details, see More information.

ImSendMessageToGroupReq req = new ImSendMessageToGroupReq();
/**
 * Set the message level. Default: NORMAL. For details, see the "Message tiering and throttling" documentation.
 */
req.level = ImMessageLevel.NORMAL;
req.type = 88888; // Custom message type
req.data = "a test"; // Custom message content
req.groupId = groupId; // Target group ID
req.repeatCount = 1; // Sets the increment value for message counting. Defaults to 1. This is useful for aggregating similar messages, such as likes. For example, you can aggregate N likes into a single message by setting repeatCount to N.
/**
 * 1. As of v1.9.0, `ImSendMessageToGroupReq#noStorage` is deprecated. Use `ImSendMessageToGroupReq#messageOption` instead.
 * 2. Starting from v1.9.0, you can separately configure message storage and caching via `ImSendMessageToGroupReq#messageOption`.
 */
req.messageOption = new ImSendMessageOption();
req.messageOption.enableStorage(false); // Sets whether to store the message. Default is false. If enabled, the message is saved to the database and can be retrieved by querying historical messages or the message list.
req.messageOption.enableCache(false); // Sets whether to cache the message. Default is false. If enabled, the message is cached in memory (up to 50 recent messages) and can be retrieved by querying the recent message list.
// You must successfully join the group (after the onSuccess callback of AliVCIMGroupInterface.joinGroup is triggered) before sending a group message. Otherwise, the operation fails with error code 425.
messageInterface.sendGroupMessage(req, new ImSdkValueCallback<ImSendMessageToGroupRsp>() {
    @Override
    public void onSuccess(ImSendMessageToGroupRsp data) {
        Log.v(ImTag.TAG, "Successfully sent group message:" + data.messageId);
    }
    @Override
    public void onFailure(Error error) {
        Log.v(ImTag.TAG, "Failed to send group message. Error code:" + error.code);
    }
});

List recent messages

ImListRecentMessageReq req;
req.groupId = groupId;
messageInterface.listRecentMessage(req, new ImSdkValueCallback<ImListRecentMessageRsp>() {
    @Override
    public void onSuccess(ImListRecentMessageRsp data) {
    }
    @Override
    public void onFailure(com.aliyun.im.common.Error error) {
    }
});

Query historical messages

// This API is primarily for replaying historical messages after a live stream has ended. It allows users to query messages without joining the group. This operation can be time-consuming and is not recommended for use during a live stream. This API may be subject to charges in the future.
ImListHistoryMessageReq req = new ImListHistoryMessageReq();
req.groupId = "your-group-id";
req.nextPageToken = 231231;  // Leave empty for the first page. The server returns a token for the next page, which you should use in your next request.
req.type = 99999;            // Custom message type. Must be greater than 10000.
req.sortType = ImSortType.ASC;
req.pageSize = 20;
req.beginTime = 0; // Start of the time range for the query, in seconds. A value of 0 means the earliest time.
req.endTime = 0;   // End of the time range for the query, in seconds. A value of 0 means the latest time.
messageInterface.listHistoryMessage(req, new ImSdkValueCallback<ImListHistoryMessageRsp>() {
    @Override
    public void onSuccess(ImListHistoryMessageRsp rsp) {
    }
    @Override
    public void onFailure(Error error) {
    }
});

Delete a message

ImDeleteMessageReq req = new ImDeleteMessageReq();
req.groupId = "your-group-id";
req.messageId = "your-message-id";
messageInterface.deleteMessage(req, new ImSdkCallback() {
    @Override
    public void onSuccess() {
                
    }

    @Override
    public void onFailure(Error error) {

    }
});

Administrator operations

List messages

// This API is available to the group owner and group administrators only.
ImListMessageReq req = new ImListMessageReq();
req.groupId = "your-group-id";
req.nextPageToken = 231231;  // Leave empty for the first page. The server returns a token for the next page, which you should use in your next request.
req.type = 99999;            // Custom message type. Must be greater than 10000.
req.sortType = ImSortType.ASC;
req.pageSize = 20;
req.beginTime = 0; // Start of the time range for the query, in seconds. A value of 0 means the earliest time.
req.endTime = 0;   // End of the time range for the query, in seconds. A value of 0 means the latest time.
messageInterface.listMessage(req, new ImSdkValueCallback<ImListMessageRsp>() {
    @Override
    public void onSuccess(ImListMessageRsp rsp) {
    }
    @Override
    public void onFailure(Error error) {
    }
});

Group service

// Get the group service instance.
AliVCIMGroupInterface groupInterface = AliVCIMEngine.instance().getGroupManager();

Non-administrator operations

Add group listener

groupManager.addGroupListener(new ImGroupListener() {
    /**
     * Notification for changes in group membership.
     * @param groupMemberChangeInfo Information about the group membership change.
     * @apiNote Added in v1.4.1. Overriding this method disables the old callback. Be sure to migrate your existing logic.
     */
    @Override
    public void onMemberChange(ImGroupMemberChangeInfo groupMemberChangeInfo) {
        // You can listen to this callback to update the room's member count and total viewership after a membership change.
        // If the group is a super large group (groupMemberChangeInfo.isBigGroup() returns true), notifications for membership changes are throttled and may not be real-time. For real-time notifications, use the corresponding OpenAPI.
    }

    /**
     * Notification for leaving a group.
     * @param groupId The group ID.
     * @param reason The reason for leaving. 1: The group was closed. 2: The user was removed from the group.
     */
    @Override
    public void onExit(String groupId, int reason) {
    }

    /**
     * Notification for a change in the group's mute status.
     * @param groupId The group ID.
     * @param status The group's mute status.
     */
    @Override
    public void onMuteChange(String groupId, ImGroupMuteStatus status) {
    }

    /**
     * Notification for a change in the group's information.
     * @param groupId The group ID.
     * @param info The group information.
     */
    @Override
    public void onInfoChange(String groupId, ImGroupInfoStatus info) {
    }
});

Join group

ImJoinGroupReq req = new ImJoinGroupReq();
req.groupId = groupId;
groupInterface.joinGroup(req, new ImSdkValueCallback<ImJoinGroupRsp>() {
    @Override
    public void onSuccess(ImJoinGroupRsp data) {
        
    }

    @Override
    public void onFailure(Error error) {
	}
});

Leave group

ImLeaveGroupReq req = new ImLeaveGroupReq();
req.groupId = groupId;
groupInterface.leaveGroup(req, new ImSdkCallback() {
    @Override
    public void onSuccess() {
        
    }

    @Override
    public void onFailure(Error error) {
	}
});

List recent group members

Important

Querying the user list is not supported for super large groups, so this API is unavailable.

/**
 * You need to check if the current group is a super large group, as this API is not available for super large groups.
 * 1. If ImGroupInfo.isBigGroup() returns true in the response to joining a group, the group is a super large group.
 * 2. A regular group can become a super large group as more members join.
 * 3. If ImGroupMemberChangeInfo.isBigGroup() returns true in the ImGroupListener#onMemberChange() callback, the group has become a super large group.
 */
ImListRecentGroupUserReq req = new ImListRecentGroupUserReq();
req.groupId = groupId;
groupManager.listRecentGroupUser(req, new ImSdkValueCallback<ImListRecentGroupUserRsp>() {
    @Override
    public void onSuccess(ImListRecentGroupUserRsp data) {
    }
    @Override
    public void onFailure(Error error) {
    }
});

Administrator operations

Create group

Note

You can create up to 5,000 groups. Closed groups do not count towards this limit. To ensure efficient resource use, close groups that are no longer needed.

ImCreateGroupReq req = new ImCreateGroupReq();
req.groupName = "Badminton Group";
Map<String, Object> data = new HashMap<>();
data.put("desc", "8-10 PM on Mon, Wed, Fri");
req.groupMeta = App.getGson().toJson(data).toString();
groupInterface.createGroup(req, new ImSdkValueCallback<ImCreateGroupRsp>() {
    @Override
    public void onSuccess(ImCreateGroupRsp data) {
        Log.v(ImTag.TAG, "Create Group Success:" + data.groupId);
        
    }
    @Override
    public void onFailure(com.aliyun.im.common.Error error) {
        Log.v(ImTag.TAG, "Create Group Failure:" + error.getCode());
    }
});

Close group

ImCloseGroupReq req = new ImCloseGroupReq();
req.groupId = groupId;
groupInterface.closeGroup(req, new ImSdkCallback() {
    @Override
    public void onSuccess() {
        
    }

    @Override
    public void onFailure(Error error) {
	}
});

Modify group

ImModifyGroupReq req = new ImModifyGroupReq();
req.groupId = groupId;
req.admins.add(adminUserId);// Specifies the list of group administrator IDs. You can set up to 3 administrators. To clear the list, provide an empty list or do not set this property, and set req.forceUpdateAdmins=true.
req.groupMeta = "extended-group-info";// Adds extended information for the group. To clear this field, provide an empty string or do not set this property, and set req.forceUpdateGroupMeta=true.
groupInterface.modifyGroup(req, new ImSdkCallback() {
    @Override
    public void onSuccess() {
        
    }

    @Override
    public void onFailure(Error error) {
	}
});

List group members

Important

Querying the user list is not supported for super large groups, so this API is unavailable.

/**
 * You need to check if the current group is a super large group, as this API is not available for super large groups.
 * 1. If ImGroupInfo.isBigGroup() returns true in the response to joining a group, the group is a super large group.
 * 2. A regular group can become a super large group as more members join.
 * 3. If ImGroupMemberChangeInfo.isBigGroup() returns true in the ImGroupListener#onMemberChange() callback, the group has become a super large group.
 */
ImListGroupUserReq req = new ImListGroupUserReq();
req.groupId = groupId;
req.sortType = ImSortType.ASC;
req.pageSize = 30;
groupManager.listGroupUser(req, new ImSdkValueCallback<ImListGroupUserRsp>() {
    @Override
    public void onSuccess(ImListGroupUserRsp data) {
    }
    @Override
    public void onFailure(Error error) {
    }
});

Mute all members

ImMuteAllReq req = new ImMuteAllReq();
req.groupId = groupId;
groupInterface.muteAll(req, new ImSdkCallback() {
    @Override
    public void onSuccess() {
        
    }

    @Override
    public void onFailure(Error error) {
	}
});

Unmute all members

ImCancelMuteAllReq req = new ImCancelMuteAllReq();
req.groupId = groupId;
groupInterface.cancelMuteAll(req, new ImSdkCallback() {
    @Override
    public void onSuccess() {
        
    }

    @Override
    public void onFailure(Error error) {
	}
});

Mute specific users

ImMuteUserReq req = new ImMuteUserReq();
req.groupId = groupId;
req.userList.add(muteUserId);
groupInterface.muteUser(req, new ImSdkCallback() {
    @Override
    public void onSuccess() {
        
    }

    @Override
    public void onFailure(Error error) {
	}
});

Unmute specific users

ImCancelMuteUserReq req = new ImCancelMuteUserReq();
req.groupId = groupId;
req.userList.add(muteUserId);
groupInterface.cancelMuteUser(req, new ImSdkCallback() {
    @Override
    public void onSuccess() {
        
    }

    @Override
    public void onFailure(Error error) {
	}
});

List muted users

ImListMuteUsersReq req = new ImListMuteUsersReq();
req.groupId = groupId;
groupManager.listMuteUsers(req, new ImSdkValueCallback<ImListMuteUsersRsp>() {
    @Override
    public void onSuccess(ImListMuteUsersRsp data) {
        
    }
    @Override
    public void onFailure(Error error) {
    }
});

Utility APIs

Use these APIs to check SDK and login status for specific business scenarios.

// Checks if the SDK has been initialized. Use this to determine if the SDK instance is ready.
AliVCIMEngine.instance().isInited();

// Checks if the user is currently logged in. Returns false if the login process is ongoing. Perform operations like joining a group or logging out only after a successful login.
AliVCIMEngine.instance().isLogin();

// Checks if the user is currently logged out. Returns false if the login process is ongoing. Perform the log in operation only when the user is logged out.
AliVCIMEngine.instance().isLogout();