linkv_rtm 0.2.1 linkv_rtm: ^0.2.1 copied to clipboard
linkv_rtm Audio/Video/IM Flutter SDK is a flutter plugin wrapper based on LinkV LVIMSDK native Android/iOS SDK
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:linkv_rtm/linkv_api_defines.dart';
import 'dart:async';
import 'package:linkv_rtm/rtm_flutter_plugin.dart';
import 'package:rtm_flutter_plugin_example/live_page.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'linkv_ui.dart';
import 'package:linkv_rtm/linkv_error_code.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:linkv_rtm/linkv_rtm_callback.dart';
import 'help.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
debugShowCheckedModeBanner: false,
home: MainView(),
);
}
}
class MainView extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MainView> implements LVIMEventCallback {
final _roomIdFieldController = TextEditingController();
final _msgInputTextEdit = TextEditingController();
final _msgTargetIdTextEdit = TextEditingController();
final _msgListTextEdit = TextEditingController();
bool _isSDKInit = false;
String _version;
String userId;
var TAG = "main [Wing] ";
bool isTokenRequesting = false;
bool isIMAuthed = false;
@override
void initState() {
super.initState();
initSDK();
RtmFlutterPlugin.getSdkVersion().then((value) => {
this.setState(() {
_version = value;
})
});
RtmFlutterPlugin.setIMEventCallback(this);
_roomIdFieldController.text = "1352";
getUid().then((value) {
userId = value;
print("D/Wing own userId = " + userId);
RtmFlutterPlugin.loginUser(userId).then((value) {
print(value);
String loginResult = "";
if (value == 0) {
loginResult = "登录成功";
} else {
loginResult = "登录失败 code : " + value.toString();
}
Fluttertoast.showToast(
msg: loginResult,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER);
});
});
}
Future<String> getUid() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String uid = prefs.getString("uid");
if (uid == null || uid.length == 0) {
uid = Random().nextInt(10000).toString();
prefs.setString("uid", uid);
}
return uid;
}
void initSDK() {
RtmFlutterPlugin.initSDK(Your_App_Id, Your_App_Sign, false, true)
.then((result) {
print('initSDK result:$result');
if (result == LVErrorCode.SUCCESS) {
_isSDKInit = true;
}
});
}
void onClickHistoryMsg() async {
String tid = _msgTargetIdTextEdit.text;
List<LVIMMsg> list = await RtmFlutterPlugin.queryLocalPrivateHistoryMessage(tid, 0, 20);
if (list == null || list.length == 0) {
print("$TAG onClickHistoryMsg null");
return;
}
print("$TAG onClickHistoryMsg count = ${list.length} last dbid = ${list.first.dbid} send_State = ${list.first.sendState}");
}
void sendEventMsg() {
RtmFlutterPlugin.sendEventMessage(_msgTargetIdTextEdit.text, "flag_event_notify", _msgInputTextEdit.text).then((lvimMsg) {
print('[Wing] sendEventMsg end result = ${lvimMsg.eCode}, dbid = ${lvimMsg.msg.cmdType}, sendState = ${lvimMsg.msg.sendState} stime = ${lvimMsg.msg.stime}');
if (lvimMsg.eCode == 0) {
Fluttertoast.showToast(msg: "Send Msg Success");
} else {
Fluttertoast.showToast(msg: "Send Msg Failed code:${lvimMsg.eCode}");
}
});
}
void onClickSessionList() async {
List<LVIMSession> list = await RtmFlutterPlugin.querySessionList();
if (list == null || list.length == 0) {
print("$TAG onClickSessionList null");
return;
}
print("$TAG onClickSessionList count = ${list.length} last dbid = ${list.first.lastMsg.dbid}, send_State = ${list.first.lastMsg.sendState}, unread_count = ${list.first.unreadCount}");
}
void onClear1234Unread() async {
String tid = _msgTargetIdTextEdit.text;
int result = await RtmFlutterPlugin.clearPrivateSessionUnreadMsg(tid);
print(TAG + " onClear1234Unread result = $result");
}
void onClearAllUnread() async {
int result = await RtmFlutterPlugin.clearPrivateAllUnreadMsg();
print(TAG + " onClearAllUnread result = $result");
}
void sendMessageHasRead() async {
String tid = _msgTargetIdTextEdit.text;
int stime = new DateTime.now().millisecondsSinceEpoch;
var result = await RtmFlutterPlugin.sendMessageHasRead(tid, stime);
print(TAG + " sendMessageHasRead result = ${result.eCode}, tid = $tid, stime = $stime");
}
void onDeleteChat() async {
String tid = _msgTargetIdTextEdit.text;
int rs = await RtmFlutterPlugin.deleteLocalPrivateSession(tid);
print(TAG + " onDeleteChat result = $rs, tid = $tid");
}
void onClickSend() {
print("[Wing] sendPrivateMessage start to = ${_msgTargetIdTextEdit.text}, content = ${_msgInputTextEdit.text}");
RtmFlutterPlugin.sendPrivateMessage(MessageSubType.IM_SUBTYPE_TEXT,
_msgTargetIdTextEdit.text, "msgType", _msgInputTextEdit.text).then((lvimMsg) {
print('[Wing] sendPrivateMessage end result = ${lvimMsg.eCode}, dbid = ${lvimMsg.msg.dbid}, sendState = ${lvimMsg.msg.sendState} stime = ${lvimMsg.msg.stime}');
if (lvimMsg.eCode == 0) {
Fluttertoast.showToast(msg: "Send Msg Success");
} else {
Fluttertoast.showToast(msg: "Send Msg Failed code:${lvimMsg.eCode}");
}
// resend(lvimMsg.msg);
});
// RtmFlutterPlugin.setPrivateDBStorageMax(5);
}
// 消息重发
void resend(LVIMMsg msg) {
RtmFlutterPlugin.sendMessage(msg).then((lvimMsg) {
print('[Wing] sendMessage end result = ${lvimMsg.eCode}, dbid = ${lvimMsg.msg.dbid}, sendState = ${lvimMsg.msg.sendState} stime = ${lvimMsg.msg.stime}');
if (lvimMsg.eCode == 0) {
Fluttertoast.showToast(msg: "Send Msg Success");
} else {
Fluttertoast.showToast(msg: "Send Msg Failed code:${lvimMsg.eCode}");
}
});
}
void onClickWatchLive() async {
print("onClickWatchLive");
bool isCan = await canLive();
if (!isCan) return;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LivePage(false, _roomIdFieldController.text, userId)));
}
void onClickStartLive() async {
print("onClickStartLive");
bool isCan = await canLive();
if (!isCan) return;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LivePage(true, _roomIdFieldController.text, userId)));
}
Future<bool> canLive() async {
// 1. 相机权限
bool canLive = await checkPermission();
print("canlive = $canLive");
if (!canLive) return canLive;
// 2. 是否输入了房间id
if (_roomIdFieldController.text.length == 0) {
LinkvUi.showAlert(context, "Please enter your room number!");
return false;
}
// 3. SDK是否已经初始化成功了
if (!_isSDKInit) {
initSDK();
return false;
}
// 4. IM是否鉴权通过
if (!isIMAuthed) {
Fluttertoast.showToast(
msg: "请等待鉴权成功后进入房间",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER);
return false;
}
return true;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text("uid :$userId"),
),
body: SafeArea(
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => FocusScope.of(context).requestFocus(new FocusNode()),
child: Container(
padding: const EdgeInsets.only(left: 20, top: 20, right: 20),
child: ListView(
children: <Widget>[
Row(
children: <Widget>[
Text("Version: "),
Expanded(
child: Text("$_version"),
)
],
),
Padding(
padding: const EdgeInsets.only(top: 20),
),
TextField(
controller: _msgInputTextEdit,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(
left: 10, top: 12, bottom: 12),
hintText: "Please enter message Content",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.cyan))),
),
Padding(
padding: const EdgeInsets.only(top: 20),
),
TextField(
controller: _msgTargetIdTextEdit,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(
left: 10, top: 12, bottom: 12),
hintText: "Please enter target user id",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.cyan))),
),
Padding(
padding: const EdgeInsets.only(top: 20),
),
TextField(
controller: _msgListTextEdit,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(
left: 10, top: 12, bottom: 12),
hintText: "received message",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.cyan)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.cyan))),
),
Padding(
padding: const EdgeInsets.only(top: 20),
),
Container(
height: 50,
width: MediaQuery.of(context).size.width - 20,
color: Colors.cyan,
child: CupertinoButton(
child: Text(
"Send Private Message",
style: TextStyle(color: Colors.white),
),
onPressed: onClickSend,
),
),
Padding(padding: const EdgeInsets.only(top: 20),),
Row(
children: <Widget>[
Container(height: 50, width: (MediaQuery.of(context).size.width - 60) * 0.5, color: Colors.cyan,
child: CupertinoButton(child: Text("History Msg", style: TextStyle(color: Colors.white),), onPressed: onClickHistoryMsg),),
Container(width: 20,),
Container(height: 50, width: (MediaQuery.of(context).size.width - 60) * 0.5, color: Colors.cyan,
child: CupertinoButton(child: Text("Session List", style: TextStyle(color: Colors.white),), onPressed: onClickSessionList)),
],
),
Padding(padding: const EdgeInsets.only(top: 20),),
Row(
children: <Widget>[
Container(height: 50, width: (MediaQuery.of(context).size.width - 60) * 0.5, color: Colors.cyan,
child: CupertinoButton(child: Text("Clear 1234 Unread", style: TextStyle(color: Colors.white),), onPressed: onClear1234Unread)),
Container(width: 20,),
Container(height: 50, width: (MediaQuery.of(context).size.width - 60) * 0.5, color: Colors.cyan,
child: CupertinoButton(child: Text("Clear All Unread", style: TextStyle(color: Colors.white),), onPressed: onClearAllUnread)),
],
),
Padding(padding: const EdgeInsets.only(top: 20),),
Row(
children: <Widget>[
Container(height: 50, width: (MediaQuery.of(context).size.width - 60) * 0.5, color: Colors.cyan,
child: CupertinoButton(child: Text("delete chat", style: TextStyle(color: Colors.white),), onPressed: onDeleteChat)),
Container(width: 20,),
Container(height: 50, width: (MediaQuery.of(context).size.width - 60) * 0.5, color: Colors.cyan,
child: CupertinoButton(child: Text("send read receipt", style: TextStyle(color: Colors.white),), onPressed: sendMessageHasRead)),
],
),
Padding(
padding: const EdgeInsets.only(top: 50),
),
TextField(
controller: _roomIdFieldController,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(
left: 10, top: 12, bottom: 12),
hintText: "Please enter room_id",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.cyan))),
),
Padding(
padding: const EdgeInsets.only(top: 20),
),
Container(
height: 50,
width: MediaQuery.of(context).size.width - 20,
color: Colors.cyan,
child: CupertinoButton(
child: Text(
"Start Live",
style: TextStyle(color: Colors.white),
),
onPressed: onClickStartLive,
),
),
Padding(
padding: const EdgeInsets.only(top: 20),
),
Container(
height: 50,
width: MediaQuery.of(context).size.width - 20,
color: Colors.cyan,
child: CupertinoButton(
child: Text(
"Watch Live",
style: TextStyle(color: Colors.white),
),
onPressed: onClickWatchLive,
),
),
],
),
),
),
),
),
);
}
// MARK: - Permission
Future<bool> checkPermission() async {
Permission _camera = Permission.camera;
Permission _microphone = Permission.microphone;
PermissionStatus status;
status = await _camera.request();
if (status != PermissionStatus.granted) return false;
status = await _microphone.request();
if (status != PermissionStatus.granted) return false;
return true;
}
@override
void onIMMessageReceive(LVIMMsg msg) {
var msgContent = msg.msgContent.toString();
print(TAG + " onIMMessageReceive" + msg.toString());
_msgListTextEdit.text = msg.fromID + " : " + msgContent;
// 发送该消息已读
RtmFlutterPlugin.sendMessageHasRead(msg.fromID, msg.stime);
}
@override
void onEventMessageReceive(LVIMMsg msg) {
print(TAG + " onEventMessageReceive content = ${msg.msgContent} type = ${msg.msgType} ");
}
@override
void onReadMessageReceive(LVIMMsg msg, int stime) {
// TODO: stime之前的消息皆为已读
print(TAG+"onReadMessageReceive : $stime");
_msgListTextEdit.text = msg.fromID + " : 已读时间戳为 $stime 的消息";
}
@override
void onIMTokenExpired(String uid, String token) {
isIMAuthed = false;
print(TAG + "onIMTokenExpired uid = " + uid);
}
@override
void onIMAuthSucceed(String uid, String token, int unReadMsgSize) {
isIMAuthed = true;
print(TAG + "onIMAuthSucceed uid = " + uid + " token = " + token);
Fluttertoast.showToast(
msg: "IM 鉴权成功",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER);
}
@override
void onIMAuthFailed(String uid, String token, int ecode, int rcode, bool isTokenExpired) {
isIMAuthed = false;
print(TAG + "onIMAuthFailed uid = " + uid + " ecode =$ecode ");
}
@override
void onQueryIMToken() {
requestReleaseIMToken();
// requestDebugIMToken();
}
void requestDebugIMToken() {
if (isTokenRequesting) return;
print(TAG + "requestDebugToken start");
isTokenRequesting = true;
RtmFlutterPlugin.requestDebugToken(userId, "Test").then((result) {
isTokenRequesting = false;
int code = result["code"];
String resultMsg = result["result"];
print(TAG + "requestDebugToken end msg = " + resultMsg + " code = $code");
/// 获取debug token 成功
if (code == 0) {
RtmFlutterPlugin.setIMToken(userId, resultMsg);
}
});
}
void requestReleaseIMToken() {
if (isTokenRequesting) return;
print(TAG + "requestReleaseIMToken start");
isTokenRequesting = true;
Help.requestReleaseIMToken(userId).then((value) {
isTokenRequesting = true;
if (value["code"] == "200") {
print(TAG + "setIMToken token = ${value["token"]}");
RtmFlutterPlugin.setIMToken(userId, value["token"]);
}
print(TAG + "requestReleaseIMToken end data = $value");
});
}
}