组件介绍
TUIKaraoke 是一个开源的音视频 UI 组件,集成了 腾讯云实时音视频、即时通信、正版曲库直通车等产品,通过在项目中集成 TUIKaraoke 组件,只需要编写几行代码就可以为您的应用添加在线 K 歌场景,体验 K 歌、麦位管理、收发礼物、文字聊天等 TRTC 在 KTV 场景下的相关能力。
基本功能如下图所示:
- 房主创建新的 Karaoke 房间开播,听众进入 Karaoke 房间收听/互动。
- 房主可以管理点歌、将座位上的麦上主播踢下麦。
- 房主还能对座位进行封禁,其他听众就不能再进行申请上麦了。
- 听众可以申请上麦,变成麦上主播,上麦后可以点歌和唱歌,也可以随时下麦成为普通的听众。
- 支持发送礼物和各种文本、自定义消息,自定义消息可用于实现弹幕、点赞等。
房间内的角色及描述
角色 | 描述 |
---|---|
房主 | 歌房创建者 |
连麦主播 | 进入歌房后,通过上麦成为连麦主播 |
主唱 | 连麦主播点歌后进行排麦演唱,正在演唱者成为主唱 |
听众 | 进入歌房的倾听者 |
核心功能
- 实时音频互动:超低延时观看,听众实时接收房主和连麦主播的音频流,保证互动的流畅性。
- 互动连麦:听众可上麦成为连麦主播,房间内所有用户都可以实时收听麦上主播互动。
- 正版曲库:正版曲库直通车提供超20w热门曲目,全套高精度伴奏歌词,多码率音质灵活应用,搜索/榜单/歌手分类多维选曲。
- 排麦模块:连麦主播点歌后,歌曲进入已点列表;当同时上麦人数大于 1 时,根据每首点播歌曲的排麦顺序上麦演唱。
- 歌词模块:歌曲播放时,根据播放进度显示对应的歌词;听众收听的歌曲进度与歌词进度实时同步。
今天我们来体验一下,如何使用TUIKaraoke组件来快速搭建在线K歌。
当然在实验之前需要做一些准备,诸如环境配置,获取AppID和密钥等。
获取应用的SDKAppID和密钥
如果您未开通腾讯云 TRTC 服务,可进入 腾讯云实时音视频控制台,创建一个新的 TRTC 应用后,在应用管理列表里面找到当前的应用:
点击配置管理,进入到应用信息页面,在应用信息里面就可以找到SDKAppID:
点击快速上手,第二步 获取签发UserSig的密钥Secretkey:
环境准备
- 最低兼容 Android 4.2(SDK API Level 17),建议使用 Android 5.0 (SDK API Level 21)及以上版本
- Android Studio 3.5及以上版本
我们用最新版的Android Studio创建新项目,或者在你的项目里面Android Studio 需要3.5及以上版本,API Level 至少是17,官方建议 21以上。另外如果是体验官方的demo,gradle版本还是使用demo的gradle-wrapper.properties
里面的设置,jdk使用1.8。在我们的新项目里面或者现有项目里面就可以不用按照demo的来了。这里我创建的新项目语言是kotlin,gradle版本是7.4.2,当然jdk也相应的使用了jdk16。放一张我的配置
可以通过Use Gradle from
选择使用自己本地下载好的gradle,或者还是按照gradle-wrapper.properties
里面配置的去下载就行了。
组件集成
下载并导入 TUIKaraoke 组件
1.单击进入 GitHub – tencentyun/TUIKaraoke,选择克隆/下载代码,然后拷贝 Android目录下的 tuikaraoke 和 debug 目录到您的工程中(debug :调试相关, tuikaraoke : KTV业务逻辑)。
- 接着在
setting.gradle
中导入如下配置:
include ':tuikaraoke'
include ':debug'
3.在 app 的 build.gradle
文件中添加对 TUIKaraoke
的依赖:
api project(':tuikaraoke')
4.在根目录的 build.gradle
文件中添加 TRTC SDK
和 IM SDK
的依赖:
ext {
liteavSdk = "com.tencent.liteav:LiteAVSDK_TRTC:latest.release"
imSdk = "com.tencent.imsdk:imsdk-plus:latest.release"
}
配置权限及混淆规则
在 AndroidManifest.xml
中配置 App 的权限,SDK 需要以下权限(6.0以上的 Android 系统需要动态申请麦克风、读取存储权限等):
// 使用场景:悬浮窗功能需要此权限;
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
// 使用场景:使用蓝牙耳机时需要此权限;
<uses-permission android:name="android.permission.BLUETOOTH" />
在 proguard-rules.pro 文件,将 SDK 相关类加入不混淆名单:
-keep class com.tencent.** { *; }
配置工程
编译下载完成后项目里面已经有了tuikaraoke
和debug
两个模块了
- 在项目里找到并打开
debug/src/main/java/com/tencent/liteav/debug/GenerateTestUserSig.java
文件。
配置GenerateTestUserSig.java
文件中的SDKAppID 和 Secretkey 为上面从腾讯云实时音视频控制台里面获取到的SDKAppID和秘钥。
至此,项目的前期准备已经完成,试着编译下,不出意外的话应该可以编译成功。
接下来我们就一起一步一步来实现在线KTV场景啦。
实现在线KTV场景
初始化并登录
1.设置登录用户信息
用户进入应用时,需要收集登录用户信息,包括userId,userName还有头像等信息。
我们可以构造一个简单的登录界面,输入框只允许输入字符串类型,长度不超过32字节,不支持使用特殊字符,使用英文或数字来设置userId。大致如下:
当然,我们可以根据自己具体的项目结合业务实际账号体系自行设置。
TUIKaraoke提供了两个类,UserModel
模型类和UserModelManager
管理类来管理用户信息。
构造好用户模型信息后就可以使用UserModelManager实例来存储为后续使用:
private fun login() {val userId = mEditUserId.text.toString().trim()val userModel = UserModel()userModel.apply {this.userId = userIduserName = userIduserSig = GenerateTestUserSig.genTestUserSig(userId)val index = Random().nextInt(AvatarConstant.USER_AVATAR_ARRAY.count())val coverUrl = AvatarConstant.USER_AVATAR_ARRAY[index]userAvatar = coverUrl}val manager = UserModelManager.getInstance()manager.userModel = userModelval intent = Intent(this, MainActivity::class.java)startActivity(intent)finish()}
其中 userSig:根据 SDKAppId、userId,Secretkey 等信息计算得到的安全保护签名,可以使用TUIKaraoke 提供的GenerateTestUserSig.genTestUserSig
计算,或者参考 如何计算及使用 UserSig实现。
2.配置TRTCKaraokeRoom
组件,TRTCKaraokeRoom
是基于腾讯云实时音视频(TRTC)和即时通信 IM 服务组合而成的组件,支持提供一系列房间列表、房间热度、主播列表等功能,比如创建房间,管理点歌上麦,发送礼物和各种文本、自定义消息,自定义消息可用于实现弹幕、点赞等。
首先通过sharedInstance
来获取TRTCKaraokeRoom
单例对象。
public static synchronized TRTCKaraokeRoom sharedInstance(Context context);
接着通过TRTCKaraokeRoom
的login
方法登录到服务:
public abstract void login(int sdkAppId,String userId, String userSig,
TRTCKaraokeRoomCallback.ActionCallback callback);
userId和userSig可以从我们前面登录的信息里面拿到,接下来就简单了,代码如下:
/*** 初始化实例并登录*/private fun initData() {// 1.初始化 获取 TRTCKaraokeRoom 单例对象mTRTCKaraokeRoom = TRTCKaraokeRoom.sharedInstance(this)// 2.登录mTRTCKaraokeRoom.login(GenerateTestUserSig.SDKAPPID,userModel.userId, //当前用户的 ID,字符串类型,只允许包含英文字母(a-z 和 A-Z)、数字(0-9)、连词符(-)和下划线(_)userModel.userSig //签名) { code, _ ->if (code == 0) {//登录成功回调,成功时 code 为0。//修改个人信息mTRTCKaraokeRoom.setSelfProfile(userModel.userName,userModel.userAvatar) { code, _ ->if (code == 0) {Log.d(TAG, "修改个人信息成功")}}}}}
TRTCKaraokeRoom服务配置好了后,我们就可以管理房间了,创建房间或者进入房间,也可以获取房间列表。
其中创建房间和进入房间需要按两步走,只有房主才能创建房间,销毁房间,听众只能进入房间,退出房间。
创建房间
创建房间我们使用TUIKaraoke
提供的KaraokeRoomCreateDialog
弹窗就可以了,我们只需要提供登录的房主信息,具体的创建房间就由TUIKaraoke
来完成就好了。
调用弹窗的代码如下:
/*** 创建房间(房主调用),若房间不存在,系统将自动创建一个新房间。*/private fun createRoom() {val dialog = KaraokeRoomCreateDialog(this)dialog.showRoomCreateDialog(userModel.userId,userModel.userId,userModel.userAvatar,TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT,true)}
不幸的是,在这里,大家打开弹窗的时候可能会报错。
com.tencent.liteav.tuikaraoke.ui.room.KaraokeRoomBaseActivity
的requestFeature
使用报错。报错信息是
java.lang.RuntimeException:
Unable to start activity ComponentInfo{com.mariko.karaoke/com.tencent.liteav.tuikaraoke.ui.room.KaraokeRoomAnchorActivity}:
android.util.AndroidRuntimeException: requestFeature()must be called before adding content
需要修改KaraokeRoomBaseActivity
由继承 AppCompatActivity
改为 Activity
。
创建歌曲管理实现类
1.拷贝歌曲管理类实现。
在打开弹窗的时候还有个错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo {com.mariko.karaoke/com.tencent.liteav.tuikaraoke.ui.room.KaraokeRoomAnchorActivity}: java.lang.NullPointerException:Attempt to invoke virtual method 'void com.tencent.liteav.tuikaraoke.ui.music.KaraokeMusicService.setRoomInfo(com.tencent.liteav.tuikaraoke.model.TRTCKaraokeRoomDef$RoomInfo)'on a null object reference
原因是在KaraokeRoomAnchorActivity
里面KaraokeMusicService.setRoomInfo
调用崩溃了,为什么会崩溃呢?原来通过KaraokeMusicService是通过 mPakcageName
反射创建管理实现的:
// 通过反射创建歌曲管理实现类的实例public void createKTVMusicImpl() {try {Class clz = Class.forName(mPakcageName);Constructor constructor = clz.getConstructor(Context.class);mKaraokeMusicService = (KaraokeMusicService) constructor.newInstance(this);} catch (Exception e) {e.printStackTrace();}}
找到mPakcageName:
private String mPakcageName = "com.tencent.liteav.demo.karaokeimpl.KaraokeMusicServiceImpl";
在我们的项目的里面是没有的,提示我们要实现这个歌曲管理类,然后替换。
为了快速实现,我们从 GitHub – tencentyun/TUIKaraoke, 选择已经下载的demo代码里面,找到TUIKaraoke/Android/app/src/main/java/com/tencent/liteav/demo/karaokeimpl
的karaokeimpl文件夹,拷贝到我们的项目里面,记得更改下包名,最后如下图所示:
2.拷贝本地音频文件。
从demo项目里面拷贝assets
目录里面的音频文件和字幕。
3.加载音频文件。
在进入房间之前,也就是打开弹窗之前需要将本地的音频文件预先加载到内存里面。
使用一个公共方法加载音频或者字幕:
public static void copyAssetsToFile(Context context, String name) {String savePath = ContextCompat.getExternalFilesDirs(context, null)[0].getAbsolutePath();String filename = savePath + "/" + name;File dir = new File(savePath);// 如果目录不存在,创建这个目录if (!dir.exists()) {dir.mkdir();}try {if (!(new File(filename)).exists()) {InputStream is = context.getResources().getAssets().open(name);FileOutputStream fos = new FileOutputStream(filename);byte[] buffer = new byte[7168];int count = 0;while ((count = is.read(buffer)) > 0) {fos.write(buffer, 0, count);}fos.close();is.close();}} catch (Exception e) {e.printStackTrace();}}
然后再分别加载所有文件:
public static void initLocalData(Context context) {copyAssetsToFile(context, "houlai_bz.mp3");copyAssetsToFile(context, "houlai_yc.mp3");copyAssetsToFile(context, "qfdy_yc.mp3");copyAssetsToFile(context, "qfdy_bz.mp3");copyAssetsToFile(context, "xq_bz.mp3");copyAssetsToFile(context, "xq_yc.mp3");copyAssetsToFile(context, "nuannuan_bz.mp3");copyAssetsToFile(context, "nuannuan_yc.mp3");copyAssetsToFile(context, "jda.mp3");copyAssetsToFile(context, "jda_bz.mp3");copyAssetsToFile(context, "houlai_lrc.vtt");copyAssetsToFile(context, "qfdy_lrc.vtt");copyAssetsToFile(context, "xq_lrc.vtt");copyAssetsToFile(context, "nuannuan_lrc.vtt");copyAssetsToFile(context, "jda_lrc.vtt");}
我们使用的歌曲来自本地的,当然可以增加自己的实现,调用api从腾讯云正版曲库获取歌曲。
至此创建房间的弹窗应该可以打开了,K歌房间也可以进去啦。
房间主界面
打开弹窗后TUIKaraoke
是通过KaraokeRoomAnchorActivity
来创建房间和K歌主界面的,KaraokeRoomAnchorActivity
继承自KaraokeRoomBaseActivity
,KaraokeRoomBaseActivity
主要是加载界面和处理一些事件等,位于tuikaraoke.ui.room
目录下。页面布局是R.layout.trtckaraoke_activity_main
。
我们要做一些定制可以从布局上面顺藤摸瓜了。
消息回显
很想把它换掉或者去掉对不对?
其实他就是一个欢迎消息的回显。
在房间里面我们有很多消息类型,有的是文本消息,还有的是带同意按钮的邀请等待的消息,消息的实体tuikaraoke.ui.widget.msg.MsgEntity
的MsgEntity
实体类:
package com.tencent.liteav.tuikaraoke.ui.widget.msg;public class MsgEntity {public static final int TYPE_NORMAL = 0;public static final int TYPE_WAIT_AGREE = 1;public static final int TYPE_AGREED = 2;public static final int TYPE_WELCOME = 3;public static final int TYPE_ORDERED_SONG = 4;public static final int TYPE_ERROR = -1;public String userId;public String userName;public String content;public String invitedId;public String linkUrl;public int type;public int color;public boolean isChat;public String songName;
}
有6种类型:
* 普通消息: TYPE_NORMAL 消息的内容会在界面显示出来* 邀请等待的消息: TYPE_WAIT_AGREE 消息中会有同意的按钮,可以进行事件处理* 邀请已同意消息: TYPE_AGREED 邀请消息已被处理,事件按钮被隐藏* 欢迎消息: TYPE_WELCOME 会出现在界面中,同时有跳转的链接url* 点歌消息: TYPE_ORDERED_SONG 消息中会有管理点歌的按钮,房主可以进行事件处理
TUIKaraoke
提供了一个消息互动显示的适配器MsgListAdapter
,根据消息的类型显示不同的样式,消息的发送者的username可以对颜色进行设置,而且实现了监听按钮等的点击事件,当有消息添加到mList,就通知适配器刷新。
同时使用一个mRvImMsg
的RecyclerView
来展示消息的。涉及到消息的几个属性如下:
KaraokeRoomBaseActivity文件:
protected RecyclerView mRvImMsg;
protected MsgListAdapter mMsgListAdapter;
protected List<MsgEntity> mMsgEntityList;
统一添加消息的入口是在KaraokeRoomBaseActivity
的showImMsg
方法里面:
protected void showImMsg(final MsgEntity entity)
到这里我们就可以找到在KaraokeRoomBaseActivity
的onCreate
里面,开始加载页面的时候就新增了一条欢迎消息了:
消息的类型是TYPE_WELCOME,找到欢迎的文本和文本点击的链接是R.string.trtckaraoke_welcome_visit
,R.string.trtckaraoke_welcome_visit_link
,在string.xml资源文件里面我们就可以重新设置为我们自己的,或者也可以不显示欢迎信息,把上面那段欢迎消息注释掉即可。
<string name="trtckaraoke_welcome_visit">"欢迎体验TRTC Karaoke!进一步了解如何快速搭建Karaoke,请点击: "</string>
<string name="trtckaraoke_welcome_visit_link">"https://cloud.tencent.com/document/product/647/59403"</string>
礼物面板
- 更换查询礼物信息的实现
首先在KTV界面的xml 布局 trtckaraoke_activity_main.xml
中找到礼物按钮
<androidx.appcompat.widget.AppCompatImageButtonandroid:id="@+id/btn_more_gift"style="@style/TRTCKtvRoomButtonStyle"android:layout_marginEnd="20dp"android:background="@drawable/trtckaraoke_ic_gift" />
接着查看礼物按钮的点击事件:
mBtnGift.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {showGiftPanel();}});
事件中打开的就是展示礼物面板
//展示礼物面板private void showGiftPanel() {IGiftPanelView giftPanelView = new GiftPanelViewImp(this);giftPanelView.init(mGiftInfoDataHandler);giftPanelView.setGiftPanelDelegate(new GiftPanelDelegate() {@Overridepublic void onGiftItemClick(GiftInfo giftInfo) {sendGift(giftInfo);}@Overridepublic void onChargeClick() {}});giftPanelView.show();}
可以看到我们的礼物面板是一个弹窗GiftPanelViewImp
,继承自BottomSheetDialog
。它完整实现了礼物的接口IGiftPanelView
,我们完全要定制礼物面板的话也需要实现这套接口:
public interface IGiftPanelView {/*** 面板通用接口*/void init(GiftInfoDataHandler giftInfoDataHandler);/*** 打开礼物面板*/void show();/*** 关闭礼物面板*/void hide();//订阅礼物面板事件void setGiftPanelDelegate(GiftPanelDelegate delegate);}
创建一个实例就是通过void init(GiftInfoDataHandler giftInfoDataHandler)
来初始化的,入参是一个GiftInfoDataHandler
,它包含了如何获取礼物信息和获取成功失败后的回调。
看下GiftInfoDataHandler
类:
public class GiftInfoDataHandler {private static final String TAG = "GiftInfoManager";private GiftAdapter mGiftAdapter;private Map<String, GiftInfo> mGiftInfoMap = new HashMap<>();public void setGiftAdapter(GiftAdapter adapter) {mGiftAdapter = adapter;queryGiftInfoList(null);}
构造一个GiftInfoDataHandler
需要一个实现了GiftAdapter
的获取礼物信息的适配器mGiftAdapter
。
public abstract class GiftAdapter {/*** 查询礼物信息** @param callback*/public abstract void queryGiftInfoList(OnGiftListQueryCallback callback);
}
在KaraokeRoomBaseActivity
类里可以找到initData房里初始化了mGiftInfoDataHandler
,通过传入一个默认实现的DefaultGiftAdapterImp
来构造mGiftInfoDataHandler:
// 礼物GiftAdapter giftAdapter = new DefaultGiftAdapterImp();mGiftInfoDataHandler = new GiftInfoDataHandler();mGiftInfoDataHandler.setGiftAdapter(giftAdapter);
到这里已经是拨开云雾见青天啦,其实我们要找的就是这个DefaultGiftAdapterImp
,是它实现如何获取礼物的,那么先看下DefaultGiftAdapterImp 类:
public class DefaultGiftAdapterImp extends GiftAdapter implements HttpGetRequest.HttpListener {private static final String TAG = "DefaultGiftAdapterImp";private static final int CORE_POOL_SIZE = 5;private static final String GIFT_DATA_URL = "https://liteav.sdk.qcloud.com/app/res/picture/live/gift/gift_data.json";private GiftBeanThreadPool mGiftBeanThreadPool;private OnGiftListQueryCallback mOnGiftListQueryCallback;@Overridepublic void queryGiftInfoList(final OnGiftListQueryCallback callback) {mOnGiftListQueryCallback = callback;ThreadPoolExecutor threadPoolExecutor = getThreadExecutor();HttpGetRequest request = new HttpGetRequest(GIFT_DATA_URL, this);threadPoolExecutor.execute(request);}
我们看到它实现GiftAdapter接口的查询礼物信息的方法queryGiftInfoList
,在queryGiftInfoList方法里面我们看到它是通过http请求从网络服务器上获取到了礼物数据的,接口地址就是
private static final String GIFT_DATA_URL = "https://liteav.sdk.qcloud.com/app/res/picture/live/gift/gift_data.json";
试着从浏览器里面打开接口看下返回数据
接口返回的数据类型是GiftBean
,DefaultGiftAdapterImp又做了一层转换,转换成后面要方便处理的GiftData
类型:
public class GiftData {// 礼物idpublic String giftId;//礼物图片对应的urlpublic String giftPicUrl;//礼物全屏动画urlpublic String lottieUrl;//礼物的名称public String title;//礼物价格public int price;//礼物类型 0为普通礼物, 1为播放全屏动画public int type;
}
到这里我们其实就可以模仿DefaultGiftAdapterImp
做一套自己的实现,或者根据自己的业务需要实现自己的网络接口,按照GiftData
模型返回数据类型就行。
- 调整礼物面板显示
通过查看礼物面板GiftPanelViewImp
的代码,它是通过一个ViewPager
来切换不同页的,每页显示的礼物是一个List<View>
。
- 设置礼物多行显示。
默认的list是单行显示的,我们可以设置为多行。
在GiftPanelViewImp
类里面找到mDefalutPanelType
属性,它是个String
类型,默认值是一个常量GIFT_PANEL_TYPE_SINGLEROW
,指向的字符串是single_row
,也就是单行,我们可以修改为多行显示。
在定义GIFT_PANEL_TYPE_SINGLEROW
常量的文件里,我们找到多行显示的常量GIFT_PANEL_TYPE_MULTIROW
,替换下mDefalutPanelType
的值:
private String mDefalutPanelType = GIFT_PANEL_TYPE_MULTIROW;
运行项目显示的效果如下:
显示了两行礼物,随着礼物数量增多就可以实时适配多行显示了。
- 实现礼物点击和充值事件。
在礼物面板上我们已经看到了各种礼物还有右下角的充值按钮了。我们只需要订阅礼物面板的事件就可以实现我们自己的需求了。
礼物面板事件:
public interface GiftPanelDelegate {/*** 礼物点击事件*/void onGiftItemClick(GiftInfo giftInfo);/*** 充值点击事件*/void onChargeClick();
}
在实例化礼物面板的时候,KaraokeRoomBaseActivity
已经帮我们实现了礼物的点击事件了:
giftPanelView.setGiftPanelDelegate(new GiftPanelDelegate() {@Overridepublic void onGiftItemClick(GiftInfo giftInfo) {sendGift(giftInfo);}@Overridepublic void onChargeClick() {}});
sendGift
方法就是发送礼物消息出去同时展示礼物动画和弹幕,还有处理弹幕消息的handleGiftMsg
方法等。
充值点击事件就需要我们根据业务的需要自己实现啦。
播放礼物动画
查看TUIKaraoke并没有提供播放礼物动画,我们可以尝试着自己在TUIKaraoke的基础上简单实现一个使用Lottie
播放动画的需求。
Lottie
是支持Android, iOS, 和React Native,并且只需简单的代码就可以实现复杂动画效果的库,具体使用我们可以参考lottie-android。
在TUIKaraoke的build.gradle文件里面引入Lottie
库:
implementation 'com.airbnb.android:lottie:5.2.0'
在KTV主页面布局trtckaraoke_activity_main
里面最外层新增LottieAnimationView
控件:
<androidx.constraintlayout.widget.ConstraintLayout
...
....<com.airbnb.lottie.LottieAnimationViewandroid:id="@+id/lt_gift"android:layout_width="match_parent"android:layout_height="match_parent"app:lottie_autoPlay="false"app:lottie_loop="false"app:lottie_repeatMode="restart" />
</androidx.constraintlayout.widget.ConstraintLayout>
定义LottieAnimationView
属性,并新增监听动画完成事件,播放完动画后隐藏控件。
private LottieAnimationView mLottieAnimationView;mLottieAnimationView = findViewById(R.id.lt_gift);mLottieAnimationView.addAnimatorListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {mLottieAnimationView.setVisibility(View.VISIBLE);}@Overridepublic void onAnimationEnd(Animator animation) {mLottieAnimationView.setVisibility(View.GONE);}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});
新增一个方法来开始播放动画:
//展示礼物动画private void showGiftLottieAnimation(String lottieUrl) {mLottieAnimationView.setVisibility(View.VISIBLE);mLottieAnimationView.setAnimationFromUrl(lottieUrl);mLottieAnimationView.playAnimation();}
接下来需要在两个地方添加播放动画,一个就是点击礼物的时候播放,另一个是在收到别人发送礼物的时候播放动画了。
在打开礼物面板初始化的时候,礼物面板的点击礼物的delega里面:
//展示礼物面板private void showGiftPanel() {IGiftPanelView giftPanelView = new GiftPanelViewImp(this);giftPanelView.init(mGiftInfoDataHandler);giftPanelView.setGiftPanelDelegate(new GiftPanelDelegate() {@Overridepublic void onGiftItemClick(GiftInfo giftInfo) {sendGift(giftInfo);//播放动画if (!giftInfo.lottieUrl.isEmpty()) {showGiftLottieAnimation(giftInfo.lottieUrl);}}@Overridepublic void onChargeClick() {}});giftPanelView.show();}
在收到消息里面,TUIKaraoke通过handleGiftMsg
方法处理弹幕消息,在这个方法里面可以播放我们的礼物动画:
/*** 处理礼物弹幕消息*/private void handleGiftMsg(TRTCKaraokeRoomDef.UserInfo userInfo, String data) {if (mGiftInfoDataHandler != null) {Gson gson = new Gson();GiftSendJson jsonData = gson.fromJson(data, GiftSendJson.class);String giftId = jsonData.getGiftId();GiftInfo giftInfo = mGiftInfoDataHandler.getGiftInfo(giftId);if (giftInfo != null) {if (userInfo != null) {giftInfo.sendUserHeadIcon = userInfo.userAvatar;if (!TextUtils.isEmpty(userInfo.userName)) {giftInfo.sendUser = userInfo.userName;} else {giftInfo.sendUser = userInfo.userId;}}mGiftAnimatorLayout.show(giftInfo);//播放动画if (!giftInfo.lottieUrl.isEmpty()) {showGiftLottieAnimation(giftInfo.lottieUrl);}}}}
至此,当我们点击了含有lottieUrl的礼物的时候就可以看到礼物动画了。
回顾总结
总结一下,很多UI组件和功能TUIKaraoke都帮我们实现了,我们只需要在项目里面接入就行了,然后在TUIKaraoke里面修改下配置,通过接口增加我们的实现,也可以在TUIKaraoke的基础上稍加修改就可以基本上完成我们的需求了。