rammus_iml.dart 16.3 KB
Newer Older
张国庆's avatar
张国庆 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import 'cloud_push_message.dart';
import 'cloud_push_service_enums.dart';
import 'common_callback_result.dart';

final MethodChannel _channel = const MethodChannel('com.jarvanmo/rammus')
  ..setMethodCallHandler(_handler);

StreamController<CommonCallbackResult> _initCloudChannelResultController =
    StreamController.broadcast();

///注意可能被多次调用。
///Android SDK文档原话如下:
///如果设备成功注册,将回调callback.onSuccess()方法。
///但如果注册服务器连接失败,则调用callback.onFailed方法,并且自动进行重新注册,直到onSuccess为止。(重试规则会由网络切换等时间自动触发。)
///请在网络通畅的情况下进行相关的初始化调试,如果网络不通,或者App信息配置错误,在onFailed方法中,会有相应的错误码返回,可参考错误处理
Stream<CommonCallbackResult> get initCloudChannelResult =>
    _initCloudChannelResultController.stream;

///用于接收服务端推送的消息。
///消息不会弹窗,而是回调该方法。
StreamController<CloudPushMessage> _onMessageArrivedController =
    StreamController.broadcast();

Stream<CloudPushMessage> get onMessageArrived =>
    _onMessageArrivedController.stream;

///客户端接收到通知后,回调该方法。
///可获取到并处理通知相关的参数。
StreamController<OnNotification> _onNotificationController =
    StreamController.broadcast();

Stream<OnNotification> get onNotification => _onNotificationController.stream;

///打开通知时会回调该方法,通知打开上报由SDK自动完成。
StreamController<OnNotificationOpened> _onNotificationOpenedController =
    StreamController.broadcast();

Stream<OnNotificationOpened> get onNotificationOpened =>
    _onNotificationOpenedController.stream;

///删除通知时回调该方法,通知删除上报由SDK自动完成。
StreamController<String> _onNotificationRemovedController =
    StreamController.broadcast();

Stream<String> get onNotificationRemoved =>
    _onNotificationRemovedController.stream;

///打开无跳转逻辑(open=4)通知时回调该方法(v2.3.2及以上版本支持),通知打开上报由SDK自动完成。
StreamController<OnNotificationClickedWithNoAction>
    _onNotificationClickedWithNoActionController = StreamController.broadcast();

Stream<OnNotificationClickedWithNoAction>
    get onNotificationClickedWithNoAction =>
        _onNotificationClickedWithNoActionController.stream;

///当用户创建自定义通知样式,并且设置推送应用内到达不创建通知弹窗时调用该回调,且此时不调用onNotification回调(v2.3.3及以上版本支持)
StreamController<OnNotificationReceivedInApp>
    _onNotificationReceivedInAppController = StreamController.broadcast();

Stream<OnNotificationReceivedInApp> get onNotificationReceivedInApp =>
    _onNotificationReceivedInAppController.stream;

///确保注册成功以后调用获取[deviceId]
Future<String?> get deviceId async {
  return _channel.invokeMethod("deviceId");
}
73 74 75 76
/// 初始化服务
void initPushService() {
  if (Platform.isAndroid) _channel.invokeMethod("initPushService");
}
张国庆's avatar
张国庆 committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
Future<CommonCallbackResult> get pushChannelStatus async {
  var result = await _channel.invokeMethod("checkPushChannelStatus");

  return CommonCallbackResult(
    isSuccessful: result["isSuccessful"],
    response: result["response"],
    errorCode: result["errorCode"],
    errorMessage: result["errorMessage"],
  );
}

/// 注册设备
/// 仅在 Android 设备生效,且在 Android 端若希望插件正常工作,必须执行一次本方法
/// 分离插件初始化与注册的过程,例如实现在用户同意了隐私政策后再进行远端注册,防止影响应用上架。
void register() {
  if (Platform.isAndroid) _channel.invokeMethod("register");
}

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
///注册厂商通道 华为
void registerHW() {
  if (Platform.isAndroid) _channel.invokeMethod("registerHuaWei");
}

///注册厂商通道 小米
void registerXM(String appId, String appKey) {
  if (Platform.isAndroid) _channel.invokeMethod("registerXiaomi", {
    "appId": appId,
    "appKey": appKey,
  });
}
///注册厂商通道 oppo
void registerOPPO(String appId, String appKey) {
  if (Platform.isAndroid) _channel.invokeMethod("registerOppo", {
    "appId": appId,
    "appKey": appKey,
  });
}
///注册厂商通道 vivo
void registerVIVO(String appId, String appKey) {
  if (Platform.isAndroid) _channel.invokeMethod("registerVivo", {
    "appId": appId,
    "appKey": appKey,
  });
}
///注册厂商通道 荣耀
void registerHonor() {
  if (Platform.isAndroid) _channel.invokeMethod("registerHonor");
}

张国庆's avatar
张国庆 committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426

///这个返回结果永远都是[true],并不是SDK初始化结果
///初始化结果请监听[initCloudChannelResult]
///只能初始化ios
//Future<bool> initCloudChannel({String appKey, String appSecret}) async {
//  return await _channel.invokeMethod(
//      "initCloudChannel", {"appKey": appKey, "appSecret": appSecret});
//}

Future<CommonCallbackResult> turnOnPushChannel() async {
  var result = await _channel.invokeMethod("turnOnPushChannel");

  return CommonCallbackResult(
    isSuccessful: result["isSuccessful"],
    response: result["response"],
    errorCode: result["errorCode"],
    errorMessage: result["errorMessage"],
  );
}

Future<CommonCallbackResult> turnOffPushChannel() async {
  var result = await _channel.invokeMethod("turnOffPushChannel");
  return CommonCallbackResult(
    isSuccessful: result["isSuccessful"],
    response: result["response"],
    errorCode: result["errorCode"],
    errorMessage: result["errorMessage"],
  );
}

/// Android 文档
///将应用内账号和推送通道相关联,可以实现按账号的定点消息推送;
///设备只能绑定一个账号,同一账号可以绑定到多个设备;
///同一设备更换绑定账号时无需进行解绑,重新调用绑定账号接口即可生效;
///若业务场景需要先解绑后绑定,在解绑账号成功回调中进行绑定绑定操作,以此保证执行的顺序性;
///账户名设置支持64字节。
Future<CommonCallbackResult> bindAccount(String account) async {
  assert(account != null);

  var result = await _channel.invokeMethod("bindAccount", account);
  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

Future<CommonCallbackResult> unbindAccount() async {
  var result = await _channel.invokeMethod("unbindAccount");
  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

///Android only
Future<CommonCallbackResult> bindPhoneNumber(String phoneNumber) async {
  var result = await _channel.invokeMethod("bindPhoneNumber", phoneNumber);
  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

///Android only

Future<CommonCallbackResult> unbindPhoneNumber() async {
  var result = await _channel.invokeMethod("unbindPhoneNumber");
  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

//void bindTag(int target, String[] tags, String alias, CommonCallback callback);
///Android 文档
///绑定标签到指定目标;
///支持向设备、账号和别名绑定标签,绑定类型由参数target指定;
///绑定标签在10分钟内生效;
///App最多支持绑定1万个标签,单个标签最大支持128字符。
///target 目标类型,1:本设备; 2:本设备绑定账号; 3:别名
///target(V2.3.5及以上版本) 目标类型,CloudPushService.DEVICE_TARGET:本设备; CloudPushService.ACCOUNT_TARGET:本账号; CloudPushService.ALIAS_TARGET:别名
///tags 标签(数组输入)
///alias 别名(仅当target = 3时生效)
///callback 回调
Future<CommonCallbackResult> bindTag(
    {@required CloudPushServiceTarget? target,
    List<String>? tags,
    String? alias}) async {
  var result = await _channel.invokeMethod("bindTag", {
    "target": target!.index + 1,
    "tags": tags ?? <String>[],
    "alias": alias
  });

  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

///Android 文档
///解绑指定目标标签;
///支持解绑设备、账号和别名标签,解绑类型由参数target指定;
///解绑标签在10分钟内生效;
///解绑标签只是解除设备和标签的绑定关系,不等同于删除标签,即该APP下标签仍然存在,系统目前不支持标签的删除。
///target 目标类型,1:本设备; 2:本设备绑定账号; 3:别名
///target(V2.3.5及以上版本) 目标类型,CloudPushService.DEVICE_TARGET:本设备; CloudPushService.ACCOUNT_TARGET:本账号; CloudPushService.ALIAS_TARGET:别名
///tags 标签(数组输入)
///alias 别名(仅当target = 3时生效)
///callback 回调
Future<CommonCallbackResult> unbindTag(
    {@required CloudPushServiceTarget? target,
    List<String>? tags,
    String? alias}) async {
  var result = await _channel.invokeMethod("unbindTag", {
    "target": target!.index + 1,
    "tags": tags ?? <String>[],
    "alias": alias
  });

  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

///Android 文档
///查询目标绑定标签,当前仅支持查询设备标签;
///查询结果可从回调onSuccess(response)的response获取;
///标签绑定成功且生效(10分钟内)后即可查询。
Future<CommonCallbackResult> listTags(CloudPushServiceTarget target) async {
  var result = await _channel.invokeMethod("listTags", target.index + 1);
  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

///Android 文档
///添加别名
///设备添加别名;
///单个设备最多添加128个别名,且同一别名最多添加到128个设备;
///别名支持128字节。
Future<CommonCallbackResult> addAlias(String alias) async {
  var result = await _channel.invokeMethod("addAlias", alias);
  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

///Android 文档
///删除别名
///删除设备别名;
///支持删除指定别名和删除全部别名(alias = null || alias.length = 0)。
Future<CommonCallbackResult> removeAlias(String alias) async {
  var result = await _channel.invokeMethod("removeAlias", alias);
  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

///Android 文档
///查询设备别名;
///查询结果可从回调onSuccess(response)的response中获取;
///从V3.0.9及以上版本开始,接口内部有5s短缓存,5s内多次调用只会请求服务端一次。
Future<CommonCallbackResult> listAliases() async {
  var result = await _channel.invokeMethod("listAliases");
  return CommonCallbackResult(
      isSuccessful: result["isSuccessful"],
      response: result["response"],
      errorCode: result["errorCode"],
      errorMessage: result["errorMessage"],
      iosError: result["iosError"]);
}

class NotificationChannel {
  const NotificationChannel(this.id, this.name, this.description,
      {this.importance = AndroidNotificationImportance.DEFAULT});
  final String id;
  final String name;
  final String description;
  final AndroidNotificationImportance importance;

  Map<String, dynamic> toJson() {
    return {
      "id": id,
      "name": name,
      "description": description,
      "importance": importance.index + 1
    };
  }
}

///这个方法只对android有效
///最好调用这个方法以保证在Android 8以上推送通知好用。
///如果不调用这个方法,请确认你自己创建了NotificationChannel。
///为了更好的用户体验,一些参数请不要用传[null]。
///[id]一定要和后台推送时候设置的通知通道一样,否则Android8.0以上无法完成通知推送。
Future setupNotificationManager(List<NotificationChannel> channels) async {
  return _channel.invokeMethod(
      "setupNotificationManager", channels.map((e) => e.toJson()).toList());
}

///这个方法仅针对iOS
///设置推送通知显示方式
///    completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
Future configureNotificationPresentationOption(
    {bool none: false,
    bool sound: true,
    bool alert: true,
    bool badge: true}) async {
  return _channel.invokeMethod("configureNotificationPresentationOption",
      {"none": none, "sound": sound, "alert": alert, "badge": badge});
}

///这个方法仅针对iOS
///同步远程角标
Future badgeClean({int num: 0}) async {
  if (Platform.isIOS){
    return _channel.invokeMethod("badgeClean", {"num": num});
  }
}

///清理图标上的角标(包含ios,华为,其他平台需要自行实现)
Future applicationBadgeNumberClean({int num: 0}) async {
  return  _channel.invokeMethod("applicationBadgeNumberClean", {"num": num});
}

Future<dynamic> _handler(MethodCall methodCall) {
  if ("initCloudChannelResult" == methodCall.method) {
    _initCloudChannelResultController.add(CommonCallbackResult(
      isSuccessful: methodCall.arguments["isSuccessful"],
      response: methodCall.arguments["response"],
      errorCode: methodCall.arguments["errorCode"],
      errorMessage: methodCall.arguments["errorMessage"],
    ));
  } else if ("onMessageArrived" == methodCall.method) {
    _onMessageArrivedController.add(CloudPushMessage(
      messageId: methodCall.arguments["messageId"],
      appId: methodCall.arguments["appId"],
      title: methodCall.arguments["title"],
      content: methodCall.arguments["content"],
      traceInfo: methodCall.arguments["traceInfo"],
    ));
  } else if ("onNotification" == methodCall.method) {
    _onNotificationController.add(OnNotification(methodCall.arguments["title"],
        methodCall.arguments["summary"], methodCall.arguments["extras"]));
  } else if ("onNotificationOpened" == methodCall.method) {
    _onNotificationOpenedController.add(OnNotificationOpened(
        methodCall.arguments["title"],
        methodCall.arguments["summary"],
        methodCall.arguments["extras"],
        methodCall.arguments["subtitle"],
        methodCall.arguments["badge"]));
  } else if ("onNotificationRemoved" == methodCall.method) {
    _onNotificationRemovedController.add(methodCall.arguments);
  } else if ("onNotificationClickedWithNoAction" == methodCall.method) {
    _onNotificationClickedWithNoActionController.add(
        OnNotificationClickedWithNoAction(methodCall.arguments["title"],
            methodCall.arguments["summary"], methodCall.arguments["extras"]));
  } else if ("onNotificationReceivedInApp" == methodCall.method) {
    _onNotificationReceivedInAppController.add(OnNotificationReceivedInApp(
        methodCall.arguments["title"],
        methodCall.arguments["summary"],
        methodCall.arguments["extras"],
        methodCall.arguments["openType"],
        methodCall.arguments["openActivity"],
        methodCall.arguments["openUrl"]));
  }

  return Future.value(true);
}

dispose() {
  _initCloudChannelResultController.close();
  _onMessageArrivedController.close();
  _onNotificationController.close();
  _onNotificationRemovedController.close();
  _onNotificationClickedWithNoActionController.close();
  _onNotificationReceivedInAppController.close();
}