├── MobPush-4.6.30-flutter-1.3.9.apk ├── README.md └── mobpush_plugin ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── android ├── .gitignore ├── .project ├── build.gradle ├── gradle.properties ├── libs │ ├── MobCommonsMCFP-2022.0218.1419.jar │ ├── MobGUI-2019.0306.1850.jar │ ├── MobGuardMCFP-2022.0218.1419.aar │ ├── MobToolsMCFP-2022.0218.1419.jar │ ├── PushSDK-4.6.25.aar │ └── xiaomi-6.0.1.aar ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── mob │ └── flutter │ └── mobpush │ ├── MobpushPlugin.java │ └── impl │ ├── Const.java │ ├── Log.java │ ├── MethodCallHandlerImpl.java │ ├── OnRemoveReceiverListener.java │ ├── StreamHandlerImpl.java │ └── req │ └── SimulateRequest.java ├── example ├── .flutter-plugins-dependencies ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .project │ ├── app │ │ ├── agconnect-services.json │ │ ├── build.gradle │ │ ├── demokey.keystore │ │ ├── google-services.json │ │ └── src │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── mob │ │ │ │ │ └── mobpush_example │ │ │ │ │ ├── LinkOneActivity.java │ │ │ │ │ ├── LinkTwoActivity.java │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ ├── utils │ │ │ │ │ ├── PlayloadDelegate.java │ │ │ │ │ └── SizeHelper.java │ │ │ │ │ └── web │ │ │ │ │ ├── BaseWebView.java │ │ │ │ │ └── WebViewPage.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ ├── launch_background.xml │ │ │ │ └── webview_progressbar_bg.xml │ │ │ │ ├── layout │ │ │ │ ├── act_link_one.xml │ │ │ │ ├── act_link_two.xml │ │ │ │ └── title_bar.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_back.png │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ └── settings.gradle ├── assets │ └── images │ │ ├── ic_item_app_nitify.png │ │ ├── ic_item_local.png │ │ ├── ic_item_media.png │ │ ├── ic_item_notify.png │ │ ├── ic_item_open_act.png │ │ └── ic_item_timing.png ├── ios │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ ├── Flutter.podspec │ │ ├── Release.xcconfig │ │ └── flutter_export_environment.sh │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── Runner.entitlements │ │ └── main.m ├── lib │ ├── app_notify_page.dart │ ├── click_container.dart │ ├── local_notify_page.dart │ ├── main.dart │ ├── notify_page.dart │ ├── other_api_page.dart │ └── timing_notify_page.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── widget_test.dart ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── MobpushPlugin.h │ └── MobpushPlugin.m └── mobpush_plugin.podspec ├── lib ├── mobpush_custom_message.dart ├── mobpush_local_notification.dart ├── mobpush_notify_message.dart └── mobpush_plugin.dart ├── pubspec.lock ├── pubspec.yaml └── test └── mobpush_plugin_test.dart /MobPush-4.6.30-flutter-1.3.9.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/MobPush-4.6.30-flutter-1.3.9.apk -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MobPush-For-Flutter 2 | 3 | ### 注意: 4 | #### 老版本插件mobpush([https://pub.dartlang.org/packages/mobpush](https://pub.dartlang.org/packages/mobpush))不再更新, 5 | #### 请使用最新插件mobpush_plugin([https://pub.dartlang.org/packages/mobpush_plugin](https://pub.dartlang.org/packages/mobpush_plugin)) 6 | > 7 | 8 | -------------------------------------------------------------------------------- /mobpush_plugin/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | -------------------------------------------------------------------------------- /mobpush_plugin/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 20e59316b8b8474554b38493b8ca888794b0234a 8 | channel: stable 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /mobpush_plugin/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.1 2 | 3 | * 1. Describe initial release. 4 | 5 | ## 1.0.1 6 | 7 | * Support for mobpush. 8 | 9 | ## 1.0.2 10 | 11 | * Support all API for MobPush. 12 | 13 | ## 1.0.3 14 | 15 | * Add How to Use Demo for MobPush. 16 | 17 | ## 1.0.4 18 | 19 | * 1.完善所有iOS API; 20 | * 2.提供完整Demo示例; 21 | 22 | ## 1.0.5 23 | 24 | * 1.iOS 新增设置前台通知展示类型(Badge.Sound.Alert); 25 | * 2.更新Demo其他API界面为列表展示; 26 | 27 | ## 1.0.6 28 | 29 | * 1.调整普通接口通过result回调; 30 | * 2.接口回调改为Map类型用于提供接口错误信息回调; 31 | 32 | ## 1.0.7 33 | 34 | * 1.iOS 消息点击回调 bug fixed. 35 | 36 | ## 1.0.9 37 | 38 | * 1.BUG 修复 39 | 40 | ## 1.1.2 41 | 42 | * 1.优化体验 43 | * 2.demo厂商更新 44 | * 3.修复已知BUG 45 | 46 | ## 1.1.3 47 | 48 | * 1.优化体验 49 | * 2.demo厂商更新 50 | * 3.修复已知BUG 51 | 52 | ## 1.1.4 53 | 54 | * 1.bug修复 55 | 56 | ## 1.1.5 57 | 58 | * 1.优化体验 59 | * 2.demo更新华为厂商 60 | 61 | ## 1.1.6 62 | 63 | * 1.优化别名获取 64 | 65 | ## 1.2.1 66 | 67 | * 1.upgrade Android embedding from v1 to v2 68 | 69 | ## 1.2.2 70 | 71 | * 1.提升插件稳定性。 72 | 73 | ## 1.2.3 74 | 75 | * 1.提升插件稳定性。 76 | 77 | ## 1.2.4 78 | 79 | * 1. SDK性能优化 80 | 81 | ## 1.2.5 82 | 83 | * 1. SDK性能优化 84 | 85 | ## 1.2.6 86 | 87 | * 1. 优化消息回调方法 88 | 89 | ## 1.2.7 90 | 91 | * 1. 优化异步消息结果回调 92 | 93 | ## 1.2.8 94 | 95 | * 1. 优化点击消息回调方法 96 | 97 | ## 1.2.9 98 | 99 | * 1. 适配Gradle8.0+ namespace 100 | 101 | ## 1.3.0 102 | 103 | * 1. 适配v4.2.6并且优化相关代码逻辑 104 | -------------------------------------------------------------------------------- /mobpush_plugin/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2015-2030, MobTech. -------------------------------------------------------------------------------- /mobpush_plugin/README.md: -------------------------------------------------------------------------------- 1 | # MobPush For Flutter 2 | 3 | 这是一个基于 MobPush 功能的扩展的 Flutter 插件。使用此插件能够帮助您在使用 Flutter 开发应用时,快速地实现推送功能。 4 | 5 | 插件主页:https://pub.dartlang.org/packages/mobpush_plugin 6 | 7 | Demo例子:https://github.com/MobClub/MobPush-for-Flutter/mobpush_plugin 8 | 9 | >注意:老版本插件mobpush([https://pub.dartlang.org/packages/mobpush](https://pub.dartlang.org/packages/mobpush))不再更新,请使用当前插件mobpush_plugin([https://pub.dartlang.org/packages/mobpush_plugin](https://pub.dartlang.org/packages/mobpush_plugin)) 10 | > 11 | 12 | 开始集成 13 | 14 | 1.参考 Flutter 官方插件集成文档 15 | 16 | 在pubspec.yaml文件中加入下面依赖 17 | 18 | ``` 19 | dependencies: 20 | mobpush_plugin: 21 | ``` 22 | 然后执行:flutter packages get 导入package 23 | 在你的dart工程文件中,导入下面头文件,开始使用 24 | 25 | ``` 26 | import 'package:mobpush_plugin/mobpush_plugin.dart'; 27 | ``` 28 | 29 | **iOS:** 30 | 31 | 平台配置参考[ iOS 集成文档](http://wiki.mob.com/mobpush-for-ios/) 32 | 33 | 实现 1. :获取 appKey 和 appSecret 34 | 实现 5.1:配置 appkey 和 appSecret 35 | 36 | **Android:** 37 | 38 | 导入 MobPush 相关依赖 39 | 40 | 在项目根目录的build.gradle中添加以下代码: 41 | 42 | ``` 43 | dependencies { 44 | classpath 'com.android.tools.build:gradle:3.2.1' 45 | classpath 'com.mob.sdk:MobSDK:+' 46 | classpath 'com.google.gms:google-services:4.0.1' //不需要FCM厂商推送无需配置 47 | } 48 | ``` 49 | 在 /android/app/build.gradle 中添加以下代码: 50 | 51 | ``` 52 | apply plugin: 'com.android.application' 53 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 54 | // 导入MobSDK 55 | apply plugin: 'com.mob.sdk' 56 | 57 | MobSDK { 58 | appKey "您的Mob平台appKey" 59 | appSecret "您的Mob平台appSecret" 60 | 61 | //配置MobPush 62 | MobPush { 63 | //配置厂商推送(可选配置,不需要厂商推送可不配置,需要哪些厂商推送只需配置哪些厂商配置即可) 64 | devInfo { 65 | //配置小米厂商推送 66 | XIAOMI { 67 | appId "您的小米平台appId" 68 | appKey "您的小米平台appKey" 69 | } 70 | 71 | //配置华为厂商推送 72 | HUAWEI { 73 | appId "您的华为平台appId" 74 | } 75 | 76 | //配置魅族厂商推送 77 | MEIZU { 78 | appId "您的魅族平台appId" 79 | appKey "您的魅族平台appKey" 80 | } 81 | 82 | //配置FCM厂商推送 83 | FCM { 84 | //设置默认推送通知显示图标 85 | iconRes "@mipmap/default_ic_launcher" 86 | } 87 | 88 | //配置OPPO厂商推送 89 | OPPO { 90 | appKey "您的OPPO平台appKey" 91 | appSecret "您的OPPO平台appSecret" 92 | } 93 | 94 | //配置VIVO厂商推送 95 | VIVO { 96 | appId "您的VIVO平台appId" 97 | appKey "您的VIVO平台appKey" 98 | } 99 | } 100 | } 101 | } 102 | ``` 103 | 3. 在MainActivity的onCreate中添加以下代码: 104 | 105 | 106 | ``` 107 | @Override 108 | protected void onCreate(Bundle savedInstanceState) { 109 | super.onCreate(savedInstanceState); 110 | GeneratedPluginRegistrant.registerWith(this); 111 | } 112 | ``` 113 | 在项目的/android/app的AndroidManifest.xml文件中添加: 114 | 115 | ``` 116 | 120 | ... 121 | 122 | ``` 123 | 124 | **接口方法说明** 125 | 126 | (1)设置隐私协议授权状态 : 127 | updatePrivacyPermissionStatus 128 | 129 | ``` 130 | MobpushPlugin.updatePrivacyPermissionStatus(true); 131 | ``` 132 | 133 | 134 | (2)设置远程推送环境,向用户授权(仅 iOS): 135 | 136 | setCustomNotification 137 | 138 | ``` 139 | if (Platform.isIOS) { 140 | MobpushPlugin.setCustomNotification(); 141 | } 142 | ``` 143 | 144 | (3)设置远程推送环境 (仅 iOS): 145 | 146 | setAPNsForProduction 147 | 148 | ``` 149 | if (Platform.isIOS) { 150 | // 开发环境 false, 线上环境 true 151 | MobpushPlugin.setAPNsForProduction(false) 152 | } 153 | ``` 154 | (4)添加推送回调监听(接收自定义透传消息回调、接收通知消息回调、接收点击通知消息回调) 155 | 156 | addPushReceiver 157 | 158 | ``` 159 | MobpushPlugin.addPushReceiver(_onEvent, _onError); 160 | 161 | void _onEvent(Object event) { 162 | 163 | } 164 | 165 | void _onError(Object event) { 166 | 167 | } 168 | ``` 169 | 170 | (5)停止推送 171 | 172 | stopPush 173 | 174 | ``` 175 | MobpushPlugin.stopPush(); 176 | ``` 177 | 178 | (6)重新打开推送服务 179 | 180 | restartPush 181 | 182 | ``` 183 | MobpushPlugin.restartPush(); 184 | ``` 185 | (7)是否已停止接收推送 186 | 187 | isPushStopped 188 | 189 | ``` 190 | MobpushPlugin.isPushStopped(); 191 | ``` 192 | 193 | (8)设置别名 194 | 195 | setAlias 196 | 197 | ``` 198 | MobpushPlugin.setAlias("别名").then((Map aliasMap){ 199 | String res = aliasMap['res']; 200 | String error = aliasMap['error']; 201 | String errorCode = aliasMap['errorCode']; 202 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> setAlias -> res: $res error: $error"); 203 | }); 204 | ``` 205 | 206 | (9)获取别名 207 | 208 | getAlias 209 | 210 | ``` 211 | MobpushPlugin.getAlias().then((Map aliasMap){ 212 | String res = aliasMap['res']; 213 | String error = aliasMap['error']; 214 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> getAlias -> res: $res error: $error"); 215 | }); 216 | ``` 217 | 218 | (10)删除别名 219 | 220 | deleteAlias 221 | 222 | ``` 223 | MobpushPlugin.deleteAlias("别名").then((Map aliasMap){ 224 | String res = aliasMap['res']; 225 | String error = aliasMap['error']; 226 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> deleteAlias -> res: $res error: $error"); 227 | }); 228 | ``` 229 | 230 | (11)添加标签 231 | 232 | addTags 233 | 234 | ``` 235 | List tags = new List(); 236 | tags.add("tag1"); 237 | tags.add("tag2"); 238 | MobpushPlugin.addTags(tags).then((Map tagsMap){ 239 | String res = tagsMap['res']; 240 | String error = tagsMap['error']; 241 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> addTags -> res: $res error: $error"); 242 | }); 243 | ``` 244 | 245 | (12)获取标签 246 | 247 | getTags 248 | 249 | ``` 250 | MobpushPlugin.getTags().then((Map tagsMap){ 251 | List resList = List.from(tagsMap['res']); 252 | String error = tagsMap['error']; 253 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> getTags -> res: $resList error: $error"); 254 | });; 255 | ``` 256 | 257 | (13)删除标签 258 | 259 | deleteTags 260 | 261 | ``` 262 | List tags = new List(); 263 | tags.add("tag1"); 264 | tags.add("tag2"); 265 | MobpushPlugin.deleteTags(tags).then((Map tagsMap){ 266 | String res = tagsMap['res']; 267 | String error = tagsMap['error']; 268 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> deleteTags -> res: $res error: $error"); 269 | }); 270 | ``` 271 | 272 | (14)清空标签 273 | 274 | cleanTags 275 | 276 | ``` 277 | MobpushPlugin.cleanTags().then((Map tagsMap){ 278 | String res = tagsMap['res']; 279 | String error = tagsMap['error']; 280 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> cleanTags -> res: $res error: $error"); 281 | }); 282 | ``` 283 | 284 | (15)发送本地通知 285 | 286 | addLocalNotification 287 | 288 | ``` 289 | MobpushPlugin.addLocalNotification(); 290 | ``` 291 | 292 | (16)绑定手机号 293 | 294 | bindPhoneNum 295 | 296 | ``` 297 | MobpushPlugin.bindPhoneNum("110"); 298 | ``` 299 | 300 | (17)测试模拟推送,用于测试 301 | 302 | send 303 | 304 | ``` 305 | /** 306 | * 测试模拟推送,用于测试 307 | * type:模拟消息类型,1、通知测试;2、内推测试;3、定时 308 | * content:模拟发送内容,500字节以内,UTF-8 309 | * space:仅对定时消息有效,单位分钟,默认1分钟 310 | * extras: 附加数据,json字符串 311 | */ 312 | MobpushPlugin.send(int type, String content, int space, String extras).then((Map sendMap){ 313 | String res = sendMap['res']; 314 | String error = sendMap['error']; 315 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> send -> res: $res error: $error"); 316 | }); 317 | ``` 318 | 319 | (18)设置点击通知是否跳转默认页 (仅andorid) 320 | 321 | setClickNotificationToLaunchMainActivity 322 | 323 | ``` 324 | MobpushPlugin.setClickNotificationToLaunchMainActivity (bool enable); 325 | ``` 326 | 327 | (19)移除本地通知(仅andorid) 328 | 329 | removeLocalNotification 330 | 331 | ``` 332 | MobpushPlugin.removeLocalNotification(int notificationId); 333 | ``` 334 | 335 | (20)清空本地通知(仅andorid) 336 | 337 | clearLocalNotifications 338 | 339 | ``` 340 | MobpushPlugin.clearLocalNotifications(); 341 | ``` 342 | 343 | (21)设置通知栏icon,不设置默认取应用icon(仅andorid) 344 | 345 | setNotifyIcon 346 | 347 | ``` 348 | MobpushPlugin.setNotifyIcon(String resId); 349 | ``` 350 | 351 | (22)设置应用在前台时是否隐藏通知不进行显示,不设置默认不隐藏通知(仅andorid) 352 | 353 | setAppForegroundHiddenNotification 354 | 355 | ``` 356 | MobpushPlugin.setAppForegroundHiddenNotification(bool hidden); 357 | ``` 358 | 359 | (23)设置通知静音时段(推送选项)(仅andorid) 360 | 361 | setSilenceTime 362 | 363 | ``` 364 | /** 365 | * 设置通知静音时段(推送选项)(仅andorid) 366 | * @param startHour 开始时间[0~23] (小时) 367 | * @param startMinute 开始时间[0~59](分钟) 368 | * @param endHour 结束时间[0~23](小时) 369 | * @param endMinute 结束时间[0~59](分钟) 370 | */ 371 | MobpushPlugin.setSilenceTime(int startHour, int startMinute, int endHour, int endMinute) 372 | ``` 373 | 374 | (24)设置角标 (仅 iOS) 375 | 376 | setBadge 377 | 378 | 379 | ``` 380 | MobpushPlugin.setBadge(int badge); 381 | ``` 382 | 383 | (25)清空角标,不清除通知栏消息记录 (仅 iOS) 384 | 385 | clearBadge 386 | 387 | ``` 388 | MobpushPlugin.clearBadge(); 389 | ``` 390 | 391 | 392 | (26)获取注册Id 393 | 394 | getRegistrationId 395 | 396 | ``` 397 | MobpushPlugin.getRegistrationId().then((Map ridMap) { 398 | print(ridMap); 399 | String regId = ridMap['res'].toString(); 400 | print('------>#### registrationId: ' + regId); 401 | }); 402 | 403 | ``` 404 | 405 | ## 技术支持 406 | 如有问题请联系技术支持: 407 | 408 | ``` 409 | 服务电话: 400-685-2216 410 | QQ: 4006852216 411 | 节假日值班电话: 412 | iOS:185-1664-1951 413 | Android: 185-1664-1950 414 | 电子邮箱: support@mob.com 415 | 市场合作: 021-54623100 416 | ``` -------------------------------------------------------------------------------- /mobpush_plugin/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /mobpush_plugin/android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | mobpush_plugin 4 | Project android_ created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | 25 | 1632622945702 26 | 27 | 30 28 | 29 | org.eclipse.core.resources.regexFilterMatcher 30 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /mobpush_plugin/android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.mob.mobpush' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.2.1' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | 24 | android { 25 | compileSdkVersion 28 26 | if (project.android.hasProperty("namespace")) { 27 | namespace 'com.mob.flutter.mobpush' 28 | } 29 | 30 | defaultConfig { 31 | minSdkVersion 17 32 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 33 | } 34 | lintOptions { 35 | disable 'InvalidPackage' 36 | } 37 | } 38 | dependencies { 39 | compileOnly fileTree(include: ['*.jar','*.aar'], dir: 'libs',excludes: []) 40 | } -------------------------------------------------------------------------------- /mobpush_plugin/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /mobpush_plugin/android/libs/MobCommonsMCFP-2022.0218.1419.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/android/libs/MobCommonsMCFP-2022.0218.1419.jar -------------------------------------------------------------------------------- /mobpush_plugin/android/libs/MobGUI-2019.0306.1850.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/android/libs/MobGUI-2019.0306.1850.jar -------------------------------------------------------------------------------- /mobpush_plugin/android/libs/MobGuardMCFP-2022.0218.1419.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/android/libs/MobGuardMCFP-2022.0218.1419.aar -------------------------------------------------------------------------------- /mobpush_plugin/android/libs/MobToolsMCFP-2022.0218.1419.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/android/libs/MobToolsMCFP-2022.0218.1419.jar -------------------------------------------------------------------------------- /mobpush_plugin/android/libs/PushSDK-4.6.25.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/android/libs/PushSDK-4.6.25.aar -------------------------------------------------------------------------------- /mobpush_plugin/android/libs/xiaomi-6.0.1.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/android/libs/xiaomi-6.0.1.aar -------------------------------------------------------------------------------- /mobpush_plugin/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'mobpush_plugin' 2 | -------------------------------------------------------------------------------- /mobpush_plugin/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /mobpush_plugin/android/src/main/java/com/mob/flutter/mobpush/MobpushPlugin.java: -------------------------------------------------------------------------------- 1 | package com.mob.flutter.mobpush; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.text.TextUtils; 8 | 9 | import androidx.annotation.NonNull; 10 | 11 | import com.mob.MobSDK; 12 | import com.mob.commons.MOBPUSH; 13 | import com.mob.flutter.mobpush.impl.Const; 14 | import com.mob.flutter.mobpush.impl.Log; 15 | import com.mob.flutter.mobpush.impl.MethodCallHandlerImpl; 16 | import com.mob.flutter.mobpush.impl.StreamHandlerImpl; 17 | import com.mob.pushsdk.MobPush; 18 | import com.mob.pushsdk.MobPushCustomMessage; 19 | import com.mob.pushsdk.MobPushNotifyMessage; 20 | import com.mob.pushsdk.MobPushReceiver; 21 | import com.mob.tools.MobLog; 22 | import com.mob.tools.utils.Hashon; 23 | import com.xiaomi.mipush.sdk.MiPushMessage; 24 | 25 | import org.json.JSONObject; 26 | 27 | import java.util.HashMap; 28 | import java.util.HashSet; 29 | import java.util.Set; 30 | import java.util.concurrent.ExecutorService; 31 | import java.util.concurrent.Executors; 32 | 33 | import io.flutter.embedding.engine.plugins.FlutterPlugin; 34 | import io.flutter.plugin.common.EventChannel; 35 | import io.flutter.plugin.common.MethodChannel; 36 | 37 | public class MobpushPlugin implements FlutterPlugin { 38 | 39 | private MethodChannel methodChannel; 40 | private MethodChannel.MethodCallHandler methodCallHandler; 41 | private EventChannel eventChannel; 42 | private EventChannel.StreamHandler streamHandler; 43 | private final Hashon hashon = new Hashon(); 44 | private static StreamHandlerImpl callbackStreamHandlerImpl; 45 | private static final Set cacheObjectList = new HashSet<>(); 46 | private static final ExecutorService executorService = Executors.newSingleThreadExecutor(); 47 | 48 | @Override 49 | public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { 50 | try { 51 | new Thread() { 52 | @Override 53 | public void run() { 54 | super.run(); 55 | try { 56 | MobSDK.setChannel(new MOBPUSH(), MobSDK.CHANNEL_FLUTTER); 57 | } catch (Throwable throwable) { 58 | 59 | } 60 | } 61 | }.start(); 62 | 63 | // 标准: MethodChannel 统一命名:com.mob.项目xx.功能 64 | methodChannel = new MethodChannel(binding.getBinaryMessenger(), "com.mob.mobpush.methodChannel"); 65 | final MethodCallHandlerImpl methodCallHandlerImpl = new MethodCallHandlerImpl(); 66 | methodCallHandler = methodCallHandlerImpl; 67 | methodChannel.setMethodCallHandler(methodCallHandler); 68 | 69 | eventChannel = new EventChannel(binding.getBinaryMessenger(), "com.mob.mobpush.reciever"); 70 | final StreamHandlerImpl streamHandlerImpl = new StreamHandlerImpl(); 71 | streamHandler = streamHandlerImpl; 72 | eventChannel.setStreamHandler(streamHandler); 73 | methodCallHandlerImpl.setRemoveReceiverListener(streamHandlerImpl); 74 | callbackStreamHandlerImpl = streamHandlerImpl; 75 | 76 | MobPush.addPushReceiver(new MobPushReceiver() { 77 | @Override 78 | public void onCustomMessageReceive(Context context, MobPushCustomMessage mobPushCustomMessage) { 79 | try { 80 | MobLog.getInstance().i("onCustomMessageReceive:" + hashon.fromObject(mobPushCustomMessage)); 81 | if (streamHandlerImpl != null) { 82 | MobLog.getInstance().i("onCustomMessageReceive messageCallback"); 83 | streamHandlerImpl.onCustomMessageReceive(context, mobPushCustomMessage); 84 | } 85 | } catch (Throwable throwable) { 86 | MobLog.getInstance().i(throwable); 87 | } 88 | } 89 | 90 | @Override 91 | public void onNotifyMessageReceive(Context context, MobPushNotifyMessage mobPushNotifyMessage) { 92 | try { 93 | MobLog.getInstance().i("onCustomMessageReceive:" + hashon.fromObject(mobPushNotifyMessage)); 94 | if (streamHandlerImpl != null) { 95 | MobLog.getInstance().i("onCustomMessageReceive messageCallback"); 96 | streamHandlerImpl.onNotifyMessageReceive(context, mobPushNotifyMessage); 97 | } 98 | } catch (Throwable throwable) { 99 | MobLog.getInstance().i(throwable); 100 | } 101 | } 102 | 103 | @Override 104 | public void onNotifyMessageOpenedReceive(Context context, MobPushNotifyMessage mobPushNotifyMessage) { 105 | try { 106 | MobLog.getInstance().i("onNotifyMessageOpenedReceive:" + hashon.fromObject(mobPushNotifyMessage)); 107 | if (streamHandlerImpl != null) { 108 | MobLog.getInstance().i("onNotifyMessageOpenedReceive messageCallback"); 109 | streamHandlerImpl.onNotifyMessageOpenedReceive(context, mobPushNotifyMessage); 110 | } 111 | } catch (Throwable throwable) { 112 | MobLog.getInstance().i(throwable); 113 | } 114 | } 115 | 116 | @Override 117 | public void onTagsCallback(Context context, String[] tags, int operation, int errorCode) { 118 | try { 119 | MobLog.getInstance().i("onTagsCallback:" + operation); 120 | if (methodCallHandlerImpl != null) { 121 | MobLog.getInstance().i("onTagsCallback messageCallback"); 122 | methodCallHandlerImpl.onTagsCallback(context, tags, operation, errorCode); 123 | } 124 | } catch (Throwable e) { 125 | MobLog.getInstance().i(e); 126 | } 127 | } 128 | 129 | @Override 130 | public void onAliasCallback(Context context, String alias, int operation, int errorCode) { 131 | try { 132 | MobLog.getInstance().i("onAliasCallback:" + operation); 133 | if (methodCallHandlerImpl != null) { 134 | MobLog.getInstance().i("onAliasCallback messageCallback"); 135 | methodCallHandlerImpl.onAliasCallback(context, alias, operation, errorCode); 136 | } 137 | } catch (Throwable e) { 138 | MobLog.getInstance().i(e); 139 | } 140 | } 141 | }); 142 | if (!cacheObjectList.isEmpty()) { 143 | MobLog.getInstance().d("cacheObjectList count:" + cacheObjectList.size()); 144 | Set dealObject = new HashSet<>(); 145 | for (JSONObject jsonObject : cacheObjectList) { 146 | try { 147 | realParseManufacturerMessage(jsonObject); 148 | dealObject.add(jsonObject); 149 | } catch (Throwable t) { 150 | MobLog.getInstance().e(t); 151 | } 152 | } 153 | if (!dealObject.isEmpty()) { 154 | cacheObjectList.removeAll(dealObject); 155 | } 156 | } 157 | } catch (Throwable e) { 158 | MobLog.getInstance().i(e); 159 | } 160 | } 161 | 162 | @Override 163 | public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { 164 | try { 165 | methodChannel.setMethodCallHandler(null); 166 | eventChannel.setStreamHandler(null); 167 | } catch (Exception e) { 168 | 169 | } 170 | } 171 | 172 | public static void parseManufacturerMessage(final Intent intent) { 173 | try { 174 | if (intent == null) { 175 | Log.d("MobPushPlugin", "intent is null"); 176 | return; 177 | } 178 | /*禁止统一回调*/ 179 | boolean forbidCallback = intent.getBooleanExtra(Const.FORBID_CALLBACK, false); 180 | if (forbidCallback) { 181 | MobLog.getInstance().d("fob cal"); 182 | return; 183 | } 184 | JSONObject jsonObject = parsePushIntent(intent, false); 185 | MobLog.getInstance().d("ManufacturerMessage:" + jsonObject); 186 | if (jsonObject == null || jsonObject.length() <= 0) { 187 | MobLog.getInstance().i("no manu data"); 188 | return; 189 | } 190 | if (callbackStreamHandlerImpl == null) { 191 | cacheObjectList.add(jsonObject); 192 | } else { 193 | MobLog.getInstance().i("realParseManufacturerMessage"); 194 | realParseManufacturerMessage(jsonObject); 195 | } 196 | } catch (Throwable throwable) { 197 | MobLog.getInstance().e(throwable); 198 | } 199 | } 200 | 201 | private static void realParseManufacturerMessage(final JSONObject jsonObject) { 202 | try { 203 | executorService.execute(new Runnable() { 204 | @Override 205 | public void run() { 206 | try { 207 | if (MobSDK.isForb()) { 208 | MobLog.getInstance().d("Forb"); 209 | return; 210 | } 211 | if (jsonObject == null || jsonObject.length() <= 0) { 212 | MobLog.getInstance().i("no manu data"); 213 | return; 214 | } 215 | boolean fromTcp = false; 216 | if (jsonObject.has(Const.FROM_TCP)) { 217 | fromTcp = jsonObject.getBoolean(Const.FROM_TCP); 218 | } 219 | if (fromTcp) { 220 | MobLog.getInstance().e("not handle pct"); 221 | return; 222 | } 223 | /*本地回调开发者*/ 224 | String messageId = ""; 225 | if (jsonObject.has(Const.ID)) { 226 | messageId = jsonObject.getString(Const.ID); 227 | } 228 | MobPushNotifyMessage message = new MobPushNotifyMessage(); 229 | HashMap extra = new HashMap<>(); 230 | message.setMessageId(messageId); 231 | if (jsonObject.has(Const.CHANNEL)) { 232 | extra.put(Const.CHANNEL, jsonObject.getString(Const.CHANNEL)); 233 | } 234 | if (jsonObject.has(Const.SCHEME_DATA)) { 235 | extra.put(Const.SCHEME_DATA, jsonObject.getString(Const.SCHEME_DATA)); 236 | } 237 | if (jsonObject.has(Const.PUSH_DATA)) { 238 | extra.put(Const.PUSH_DATA, jsonObject.getString(Const.PUSH_DATA)); 239 | } 240 | message.setExtrasMap(extra); 241 | if (callbackStreamHandlerImpl != null) { 242 | MobLog.getInstance().i("onNotifyMessageOpenedReceive messageCallback"); 243 | callbackStreamHandlerImpl.onNotifyMessageOpenedReceive(MobSDK.getContext(), message); 244 | } else { 245 | MobLog.getInstance().d("callbackStreamHandlerImpl null"); 246 | } 247 | } catch (Throwable throwable) { 248 | MobLog.getInstance().d(throwable); 249 | } 250 | } 251 | }); 252 | }catch (Throwable throwable){ 253 | MobLog.getInstance().d(throwable); 254 | } 255 | } 256 | 257 | 258 | public static JSONObject parsePushIntent(Intent intent, boolean needMsgIfExist) { 259 | try { 260 | JSONObject result = new JSONObject(); 261 | MobLog.getInstance().d("MobPush parsePushIntent uri:" + intent.toUri(Intent.URI_INTENT_SCHEME)); 262 | boolean isFromTcp = intent.getBooleanExtra(Const.FROM_TCP, false); 263 | Bundle bundle = intent.getExtras(); 264 | if (bundle != null) { 265 | for (String key : bundle.keySet()) { 266 | boolean hasGetPushData = result.has(Const.PUSH_DATA); 267 | if (!hasGetPushData && Const.PUSH_DATA.equals(key)) { 268 | String content = bundle.getString(key); 269 | JSONObject pushDataJson = new JSONObject(content); 270 | result.put(Const.PUSH_DATA, pushDataJson); 271 | } 272 | boolean hasGetSchemeData = result.has(Const.SCHEME_DATA); 273 | if (!hasGetSchemeData && Const.SCHEME_DATA.equals(key)) { 274 | String content = bundle.getString(key); 275 | JSONObject schemeDataJson = new JSONObject(content); 276 | result.put(Const.SCHEME_DATA, schemeDataJson); 277 | } 278 | 279 | boolean hasGetId = result.has(Const.ID); 280 | if (!hasGetId && Const.ID.equals(key)) { 281 | String content = bundle.getString(key); 282 | result.put(Const.ID, content); 283 | } 284 | 285 | boolean hasGeTtChannel = result.has(Const.CHANNEL); 286 | if (!hasGeTtChannel && Const.CHANNEL.equals(key)) { 287 | String content = bundle.getString(key); 288 | result.put(Const.CHANNEL, content); 289 | } 290 | 291 | boolean hasGetMsg = result.has(Const.MSG); 292 | if (!hasGetMsg && needMsgIfExist && Const.MSG.equalsIgnoreCase(key)) { 293 | Object msg = bundle.get(Const.MSG); 294 | if (msg != null) { 295 | result.put(Const.MSG, msg); 296 | } 297 | } 298 | } 299 | } 300 | //fcm 厂商id 特殊处理 301 | try { 302 | if (bundle != null) { 303 | String id = bundle.getString(Const.ID); 304 | if (id != null && !TextUtils.isEmpty(id) && !isFromTcp && id.contains("_")) { 305 | id = id.split("_")[0]; 306 | result.put(Const.ID, id); 307 | } 308 | } 309 | } catch (Throwable e) { 310 | MobLog.getInstance().d(e); 311 | } 312 | //OPPO 313 | Uri uri = intent.getData(); 314 | if (uri != null && !isFromTcp) { 315 | try { 316 | String pushData = uri.getQueryParameter(Const.PUSH_DATA); 317 | MobLog.getInstance().d("MobPush oppo pushdata" + pushData); 318 | if (!TextUtils.isEmpty(pushData)) { 319 | JSONObject pushDataJson = new JSONObject(pushData); 320 | result.put(Const.PUSH_DATA, pushDataJson); 321 | } 322 | String schemeData = uri.getQueryParameter(Const.SCHEME_DATA); 323 | MobLog.getInstance().d("MobPush oppo schemeData" + schemeData); 324 | if (!TextUtils.isEmpty(schemeData)) { 325 | JSONObject schemeDataJson = new JSONObject(schemeData); 326 | result.put(Const.SCHEME_DATA, schemeDataJson); 327 | } 328 | String id = uri.getQueryParameter(Const.ID); 329 | MobLog.getInstance().d("MobPush oppo id" + id); 330 | if (!TextUtils.isEmpty(id)) { 331 | result.put(Const.ID, id); 332 | } 333 | String channel = uri.getQueryParameter(Const.CHANNEL); 334 | MobLog.getInstance().d("MobPush oppo channel" + channel); 335 | if (!TextUtils.isEmpty(channel)) { 336 | result.put(Const.CHANNEL, channel); 337 | } 338 | } catch (Throwable throwable) { 339 | MobLog.getInstance().d("OPPO" + throwable); 340 | } 341 | } 342 | //XIAOMI 343 | try { 344 | if (Class.forName("com.xiaomi.mipush.sdk.MiPushMessage") != null && !isFromTcp) { 345 | if (bundle != null && bundle.containsKey(Const.KEY_MESSAGE)) { 346 | HashMap miPushMessage = getMiPushMessage(bundle); 347 | if (miPushMessage != null && !miPushMessage.isEmpty()) { 348 | if (miPushMessage.containsKey(Const.PUSH_DATA)) { 349 | String pushData = miPushMessage.get(Const.PUSH_DATA); 350 | if (!TextUtils.isEmpty(pushData)) { 351 | JSONObject pushDataJson = new JSONObject(pushData); 352 | result.put(Const.PUSH_DATA, pushDataJson); 353 | } 354 | } 355 | if (miPushMessage.containsKey(Const.ID)) { 356 | String id = miPushMessage.get(Const.ID); 357 | if (!TextUtils.isEmpty(id)) { 358 | result.put(Const.ID, id); 359 | } 360 | } 361 | if (miPushMessage.containsKey(Const.CHANNEL)) { 362 | String channel = miPushMessage.get(Const.CHANNEL); 363 | if (!TextUtils.isEmpty(channel)) { 364 | result.put(Const.CHANNEL, channel); 365 | } 366 | } 367 | } 368 | } 369 | } 370 | } catch (Throwable throwable) { 371 | MobLog.getInstance().e(throwable); 372 | } 373 | MobLog.getInstance().d("MobPush parsePushIntent JSONArray:" + result); 374 | if (result.length() > 0) { 375 | result.put(Const.FROM_TCP, isFromTcp); 376 | } 377 | return result; 378 | } catch (Throwable throwable) { 379 | MobLog.getInstance().e(throwable); 380 | } 381 | return null; 382 | } 383 | 384 | private static HashMap getMiPushMessage(Bundle bundle) { 385 | HashMap map = new HashMap<>(); 386 | try { 387 | for (String key : bundle.keySet()) { 388 | if ((Const.KEY_MESSAGE.equals(key))) { 389 | MiPushMessage message = (MiPushMessage) bundle.getSerializable(key); 390 | if (message != null && message.getExtra() != null) { 391 | map.putAll(message.getExtra()); 392 | } 393 | } 394 | } 395 | return map; 396 | } catch (Throwable throwable) { 397 | MobLog.getInstance().d(throwable); 398 | return null; 399 | } 400 | } 401 | 402 | } 403 | -------------------------------------------------------------------------------- /mobpush_plugin/android/src/main/java/com/mob/flutter/mobpush/impl/Const.java: -------------------------------------------------------------------------------- 1 | package com.mob.flutter.mobpush.impl; 2 | 3 | public class Const { 4 | public static final String FROM_TCP = "from_tcp"; 5 | public static final String PUSH_DATA = "pushData"; 6 | public static final String EXTRA = "extra"; 7 | public static final String CONTENT = "content"; 8 | public static final String SCHEME_DATA = "schemeData"; 9 | public static final String ID = "id"; 10 | public static final String MSG = "msg"; 11 | public static final String CHANNEL = "channel"; 12 | public static final String KEY_MESSAGE = "key_message"; 13 | 14 | /** 15 | * 厂商解析工具解析到此字段时,禁止回调 16 | */ 17 | public static final String FORBID_CALLBACK = "fbcb"; 18 | } 19 | -------------------------------------------------------------------------------- /mobpush_plugin/android/src/main/java/com/mob/flutter/mobpush/impl/Log.java: -------------------------------------------------------------------------------- 1 | package com.mob.flutter.mobpush.impl; 2 | 3 | import android.text.TextUtils; 4 | 5 | public class Log { 6 | private static boolean isDebug = true; 7 | public static final String TAG = "MobPushPlugin"; 8 | 9 | public static void e(String tag, String msg) { 10 | if (!isDebug) { 11 | return; 12 | } 13 | if (TextUtils.isEmpty(tag)) { 14 | tag = TAG; 15 | } 16 | android.util.Log.e(tag, msg); 17 | } 18 | 19 | public static void d(String tag, String msg) { 20 | if (!isDebug) { 21 | return; 22 | } 23 | if (TextUtils.isEmpty(tag)) { 24 | tag = TAG; 25 | } 26 | android.util.Log.d(tag, msg); 27 | } 28 | 29 | public static void setIsDebug(boolean isDebug) { 30 | Log.isDebug = isDebug; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /mobpush_plugin/android/src/main/java/com/mob/flutter/mobpush/impl/MethodCallHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package com.mob.flutter.mobpush.impl; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | 7 | import com.mob.MobSDK; 8 | import com.mob.OperationCallback; 9 | import com.mob.flutter.mobpush.impl.req.SimulateRequest; 10 | import com.mob.pushsdk.MobPush; 11 | import com.mob.pushsdk.MobPushCallback; 12 | import com.mob.pushsdk.MobPushCustomMessage; 13 | import com.mob.pushsdk.MobPushLocalNotification; 14 | import com.mob.pushsdk.MobPushNotifyMessage; 15 | import com.mob.pushsdk.MobPushReceiver; 16 | import com.mob.tools.MobLog; 17 | import com.mob.tools.utils.Hashon; 18 | import com.mob.tools.utils.ResHelper; 19 | 20 | import java.lang.reflect.Field; 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.HashMap; 24 | 25 | import io.flutter.plugin.common.MethodCall; 26 | import io.flutter.plugin.common.MethodChannel; 27 | 28 | public class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler, MobPushReceiver { 29 | private static final Hashon hashon = new Hashon(); 30 | private OnRemoveReceiverListener removeReceiverListener; 31 | private static ArrayList setAliasCallback = new ArrayList<>(); 32 | private static ArrayList getAliasCallback = new ArrayList<>(); 33 | private static ArrayList getTagsCallback = new ArrayList<>(); 34 | private static ArrayList deleteAliasCallback = new ArrayList<>(); 35 | private static ArrayList addTagsCallback = new ArrayList<>(); 36 | private static ArrayList deleteTagsCallback = new ArrayList<>(); 37 | private static ArrayList cleanTagsCallback = new ArrayList<>(); 38 | 39 | @Override 40 | public void onMethodCall(@NonNull MethodCall call, @NonNull final MethodChannel.Result result) { 41 | try { 42 | Log.e("",call.method); 43 | if (call.method.equals("getPlatformVersion")) { 44 | result.success("Android " + android.os.Build.VERSION.RELEASE); 45 | } else if (call.method.equals("getSDKVersion")) { 46 | result.success(getMobPushSdkVersion()); 47 | } else if (call.method.equals("getRegistrationId")) { 48 | MobPush.getRegistrationId(new MobPushCallback() { 49 | @Override 50 | public void onCallback(String data) { 51 | HashMap map = new HashMap(); 52 | map.put("res", data); 53 | result.success(map); 54 | } 55 | }); 56 | } else if (call.method.equals("removePushReceiver")) { 57 | if (removeReceiverListener != null) { 58 | removeReceiverListener.onRemoveReceiver(); 59 | } 60 | } else if (call.method.equals("setClickNotificationToLaunchMainActivity")) { 61 | boolean enable = call.argument("enable"); 62 | MobPush.setClickNotificationToLaunchMainActivity(enable); 63 | } else if (call.method.equals("stopPush")) { 64 | MobPush.stopPush(); 65 | } else if (call.method.equals("restartPush")) { 66 | MobPush.restartPush(); 67 | } else if (call.method.equals("isPushStopped")) { 68 | result.success(MobPush.isPushStopped()); 69 | } else if (call.method.equals("setAlias")) { 70 | String alias = call.argument("alias"); 71 | setAliasCallback.add(result); 72 | MobPush.setAlias(alias); 73 | } else if (call.method.equals("getAlias")) { 74 | getAliasCallback.add(result); 75 | MobPush.getAlias(); 76 | } else if (call.method.equals("deleteAlias")) { 77 | deleteAliasCallback.add(result); 78 | MobPush.deleteAlias(); 79 | } else if (call.method.equals("addTags")) { 80 | ArrayList tags = call.argument("tags"); 81 | addTagsCallback.add(result); 82 | MobPush.addTags(tags.toArray(new String[tags.size()])); 83 | } else if (call.method.equals("getTags")) { 84 | getTagsCallback.add(result); 85 | MobPush.getTags(); 86 | } else if (call.method.equals("deleteTags")) { 87 | ArrayList tags = call.argument("tags"); 88 | deleteTagsCallback.add(result); 89 | MobPush.deleteTags(tags.toArray(new String[tags.size()])); 90 | } else if (call.method.equals("cleanTags")) { 91 | cleanTagsCallback.add(result); 92 | MobPush.cleanTags(); 93 | } else if (call.method.equals("setSilenceTime")) { 94 | int startHour = call.argument("startHour"); 95 | int startMinute = call.argument("startMinute"); 96 | int endHour = call.argument("endHour"); 97 | int endMinute = call.argument("endMinute"); 98 | MobPush.setSilenceTime(startHour, startMinute, endHour, endMinute); 99 | } else if (call.method.equals("setTailorNotification")) { 100 | 101 | } else if (call.method.equals("removeLocalNotification")) { 102 | int notificationId = call.argument("notificationId"); 103 | result.success(MobPush.removeLocalNotification(notificationId)); 104 | } else if (call.method.equals("addLocalNotification")) { 105 | String json = call.argument("localNotification"); 106 | MobPushLocalNotification notification = hashon.fromJson(json, MobPushLocalNotification.class); 107 | result.success(MobPush.addLocalNotification(notification)); 108 | } else if (call.method.equals("clearLocalNotifications")) { 109 | result.success(MobPush.clearLocalNotifications()); 110 | } else if (call.method.equals("setNotifyIcon")) { 111 | String iconRes = call.argument("iconRes"); 112 | int iconResId = ResHelper.getBitmapRes(MobSDK.getContext(), iconRes); 113 | if (iconResId > 0) { 114 | MobPush.setNotifyIcon(iconResId); 115 | } 116 | } else if (call.method.equals("setAppForegroundHiddenNotification")) { 117 | boolean hidden = call.argument("hidden"); 118 | MobPush.setAppForegroundHiddenNotification(hidden); 119 | } else if (call.method.equals("setShowBadge")) { 120 | boolean show = call.argument("show"); 121 | MobPush.setShowBadge(show); 122 | } else if (call.method.equals("bindPhoneNum")) { 123 | String phoneNum = call.argument("phoneNum"); 124 | MobPush.bindPhoneNum(phoneNum, new MobPushCallback() { 125 | @Override 126 | public void onCallback(Boolean data) { 127 | if (data != null) { 128 | HashMap map = new HashMap(); 129 | map.put("res", data.booleanValue() ? "success" : "failed"); 130 | map.put("error", ""); 131 | result.success(map); 132 | } 133 | } 134 | }); 135 | } else if (call.method.equals("send")) { 136 | int type = call.argument("type"); 137 | int space = call.argument("space"); 138 | String content = call.argument("content"); 139 | String extras = call.argument("extrasMap"); 140 | SimulateRequest.sendPush(type, content, space, extras, new MobPushCallback() { 141 | @Override 142 | public void onCallback(Boolean aBoolean) { 143 | if (aBoolean != null) { 144 | HashMap map = new HashMap(); 145 | map.put("res", aBoolean.booleanValue() ? "success" : "failed"); 146 | map.put("error", ""); 147 | result.success(map); 148 | } 149 | } 150 | }); 151 | } else if (call.method.equals("updatePrivacyPermissionStatus")) { 152 | boolean status = call.argument("status"); 153 | MobSDK.submitPolicyGrantResult(status, new OperationCallback() { 154 | @Override 155 | public void onComplete(Void aVoid) { 156 | result.success(true); 157 | System.out.println("updatePrivacyPermissionStatus onComplete"); 158 | } 159 | 160 | @Override 161 | public void onFailure(Throwable throwable) { 162 | result.error(throwable.toString(), null, null); 163 | System.out.println("updatePrivacyPermissionStatus onFailure:" + throwable.getMessage()); 164 | } 165 | }); 166 | } else { 167 | result.notImplemented(); 168 | } 169 | } catch (Exception e) { 170 | Log.e("", e.getMessage()); 171 | } 172 | } 173 | 174 | public void setRemoveReceiverListener(OnRemoveReceiverListener removeReceiverListener) { 175 | this.removeReceiverListener = removeReceiverListener; 176 | } 177 | 178 | private String getMobPushSdkVersion() { 179 | try { 180 | Class mobpushClass = MobPush.class; 181 | Field versionField = mobpushClass.getDeclaredField("SDK_VERSION_NAME"); 182 | if (!versionField.isAccessible()) { 183 | versionField.setAccessible(true); 184 | } 185 | return (String) versionField.get(mobpushClass); 186 | } catch (Throwable e) { 187 | e.printStackTrace(); 188 | } 189 | return MobPush.SDK_VERSION_NAME; 190 | } 191 | 192 | @Override 193 | public void onCustomMessageReceive(Context context, MobPushCustomMessage mobPushCustomMessage) { 194 | 195 | } 196 | 197 | @Override 198 | public void onNotifyMessageReceive(Context context, MobPushNotifyMessage mobPushNotifyMessage) { 199 | 200 | } 201 | 202 | @Override 203 | public void onNotifyMessageOpenedReceive(Context context, MobPushNotifyMessage mobPushNotifyMessage) { 204 | 205 | } 206 | 207 | @Override 208 | public void onTagsCallback(Context context, String[] tags, int operation, int errorCode) { 209 | try { 210 | HashMap map = new HashMap<>(); 211 | MethodChannel.Result result = null; 212 | // 0 获取, 1 设置, 2 删除,3 清空 213 | switch (operation) { 214 | case 0: 215 | result = getTagsCallback.remove(0); 216 | map.put("res", tags == null ? new ArrayList() : Arrays.asList(tags)); 217 | map.put("error", ""); 218 | map.put("errorCode", String.valueOf(errorCode)); 219 | break; 220 | case 1: 221 | result = addTagsCallback.remove(0); 222 | map.put("res", errorCode == 0 ? "success" : "failed"); 223 | map.put("error", ""); 224 | map.put("errorCode", String.valueOf(errorCode)); 225 | break; 226 | case 2: 227 | result = deleteTagsCallback.remove(0); 228 | map.put("res", errorCode == 0 ? "success" : "failed"); 229 | map.put("error", ""); 230 | map.put("errorCode", String.valueOf(errorCode)); 231 | break; 232 | case 3: 233 | result = cleanTagsCallback.remove(0); 234 | map.put("res", errorCode == 0 ? "success" : "failed"); 235 | map.put("error", ""); 236 | map.put("errorCode", String.valueOf(errorCode)); 237 | break; 238 | } 239 | if (result != null) { 240 | MobLog.getInstance().i("tag result success"); 241 | result.success(map); 242 | } 243 | } catch (Throwable e) { 244 | MobLog.getInstance().e(e); 245 | } 246 | } 247 | 248 | @Override 249 | public void onAliasCallback(Context context, String alias, int operation, int errorCode) { 250 | try { 251 | HashMap map = new HashMap<>(); 252 | MethodChannel.Result result = null; 253 | // 0 获取, 1 设置, 2 删除 254 | switch (operation) { 255 | case 0: 256 | result = getAliasCallback.remove(0); 257 | map.put("res", alias); 258 | map.put("error", ""); 259 | map.put("errorCode", String.valueOf(errorCode)); 260 | break; 261 | case 1: 262 | result = setAliasCallback.remove(0); 263 | map.put("res", errorCode == 0 ? "success" : "failed"); 264 | map.put("error", ""); 265 | map.put("errorCode", String.valueOf(errorCode)); 266 | break; 267 | case 2: 268 | result = deleteAliasCallback.remove(0); 269 | map.put("res", errorCode == 0 ? "success" : "failed"); 270 | map.put("error", ""); 271 | map.put("errorCode", String.valueOf(errorCode)); 272 | break; 273 | } 274 | if (result != null) { 275 | MobLog.getInstance().i("alias result success"); 276 | result.success(map); 277 | } 278 | } catch (Throwable e) { 279 | MobLog.getInstance().e(e); 280 | } 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /mobpush_plugin/android/src/main/java/com/mob/flutter/mobpush/impl/OnRemoveReceiverListener.java: -------------------------------------------------------------------------------- 1 | package com.mob.flutter.mobpush.impl; 2 | 3 | public interface OnRemoveReceiverListener { 4 | void onRemoveReceiver(); 5 | } 6 | -------------------------------------------------------------------------------- /mobpush_plugin/android/src/main/java/com/mob/flutter/mobpush/impl/StreamHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package com.mob.flutter.mobpush.impl; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.os.Message; 6 | 7 | import com.mob.pushsdk.MobPushCustomMessage; 8 | import com.mob.pushsdk.MobPushNotifyMessage; 9 | import com.mob.pushsdk.MobPushReceiver; 10 | import com.mob.tools.MobLog; 11 | import com.mob.tools.utils.Hashon; 12 | import com.mob.tools.utils.UIHandler; 13 | 14 | import java.util.HashMap; 15 | import java.util.concurrent.LinkedBlockingQueue; 16 | import java.util.concurrent.ThreadPoolExecutor; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | import io.flutter.plugin.common.EventChannel; 20 | 21 | public class StreamHandlerImpl implements EventChannel.StreamHandler, OnRemoveReceiverListener, MobPushReceiver { 22 | 23 | private EventChannel.EventSink eventSink; 24 | private volatile boolean isRemoved = false; 25 | private final Object lock = new Object(); 26 | private final Hashon hashon = new Hashon(); 27 | private final ThreadPoolExecutor singleExecutor = new ThreadPoolExecutor(0, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); 28 | 29 | @Override 30 | public void onListen(final Object o, EventChannel.EventSink eventSink) { 31 | MobLog.getInstance().i("onListen"); 32 | this.eventSink = eventSink; 33 | this.isRemoved = false; 34 | try { 35 | synchronized (lock) { 36 | lock.notifyAll(); 37 | } 38 | } catch (Throwable throwable) { 39 | MobLog.getInstance().e(throwable); 40 | } 41 | } 42 | 43 | @Override 44 | public void onCancel(Object o) { 45 | 46 | } 47 | 48 | @Override 49 | public void onRemoveReceiver() { 50 | MobLog.getInstance().e("onRemoveReceiver"); 51 | isRemoved = true; 52 | eventSink = null; 53 | try { 54 | synchronized (lock) { 55 | lock.notifyAll(); 56 | } 57 | } catch (Throwable throwable) { 58 | MobLog.getInstance().e(throwable); 59 | } 60 | } 61 | 62 | @Override 63 | public void onCustomMessageReceive(Context context, MobPushCustomMessage mobPushCustomMessage) { 64 | try { 65 | HashMap map = new HashMap<>(); 66 | map.put("action", 0); 67 | map.put("result", hashon.fromJson(hashon.fromObject(mobPushCustomMessage))); 68 | messageCallback(map); 69 | } catch (Throwable t) { 70 | MobLog.getInstance().e(t); 71 | } 72 | } 73 | 74 | @Override 75 | public void onNotifyMessageReceive(Context context, MobPushNotifyMessage mobPushNotifyMessage) { 76 | try { 77 | HashMap map = new HashMap<>(); 78 | map.put("action", 1); 79 | map.put("result", hashon.fromJson(hashon.fromObject(mobPushNotifyMessage))); 80 | messageCallback(map); 81 | } catch (Throwable throwable) { 82 | MobLog.getInstance().e(throwable); 83 | } 84 | } 85 | 86 | @Override 87 | public void onNotifyMessageOpenedReceive(Context context, MobPushNotifyMessage mobPushNotifyMessage) { 88 | try { 89 | HashMap map = new HashMap<>(); 90 | map.put("action", 2); 91 | map.put("result", hashon.fromJson(hashon.fromObject(mobPushNotifyMessage))); 92 | messageCallback(map); 93 | } catch (Throwable throwable) { 94 | MobLog.getInstance().e(throwable); 95 | } 96 | } 97 | 98 | @Override 99 | public void onTagsCallback(Context context, String[] strings, int i, int i1) { 100 | 101 | } 102 | 103 | @Override 104 | public void onAliasCallback(Context context, String s, int i, int i1) { 105 | 106 | } 107 | 108 | 109 | public void messageCallback(final HashMap map) { 110 | singleExecutor.execute(new Runnable() { 111 | @Override 112 | public void run() { 113 | try { 114 | MobLog.getInstance().i("Stream messageCallback"); 115 | if (isRemoved) { 116 | MobLog.getInstance().i("isRemoved"); 117 | return; 118 | } 119 | if (eventSink == null) { 120 | synchronized (lock) { 121 | MobLog.getInstance().i("wait"); 122 | lock.wait(); 123 | } 124 | } 125 | MobLog.getInstance().i("isRemoved:" + isRemoved); 126 | if (eventSink != null && !isRemoved) { 127 | UIHandler.sendEmptyMessage(0, new Handler.Callback() { 128 | @Override 129 | public boolean handleMessage(Message message) { 130 | try { 131 | eventSink.success(hashon.fromHashMap(map)); 132 | MobLog.getInstance().i("eventSink success"); 133 | } catch (Throwable throwable) { 134 | MobLog.getInstance().e(throwable); 135 | } 136 | return false; 137 | } 138 | }); 139 | } 140 | } catch (Throwable throwable) { 141 | MobLog.getInstance().e(throwable); 142 | } 143 | } 144 | }); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /mobpush_plugin/android/src/main/java/com/mob/flutter/mobpush/impl/req/SimulateRequest.java: -------------------------------------------------------------------------------- 1 | package com.mob.flutter.mobpush.impl.req; 2 | 3 | import android.text.TextUtils; 4 | import com.mob.MobCommunicator; 5 | import com.mob.MobSDK; 6 | import com.mob.pushsdk.MobPush; 7 | import com.mob.pushsdk.MobPushCallback; 8 | import java.util.HashMap; 9 | 10 | public class SimulateRequest { 11 | private static final String PUB_KEY = "009cbd92ccef123be840deec0c6ed0547194c1e471d11b6f375e56038458fb18833e5bab2e1206b261495d7e2d1d9e5aa859e6d4b" 12 | + "671a8ca5d78efede48e291a3f"; 13 | private static final String MODULUS = "1dfd1d615cb891ce9a76f42d036af7fce5f8b8efaa11b2f42590ecc4ea4cff28f5f6b0726aeb76254ab5b02a58c1d5b486c39d9da" 14 | + "1a58fa6ba2f22196493b3a4cbc283dcf749bf63679ee24d185de70c8dfe05605886c9b53e9f569082eabdf98c4fb0dcf07eb9bb3e647903489ff0b5d933bd004af5be" 15 | + "4a1022fdda41f347f1"; 16 | 17 | protected final static String SERVER_URL = "https://sdk.push.mob.com/demo/v2/push"; 18 | private static MobCommunicator mobCommunicator; 19 | 20 | private synchronized static MobCommunicator getMobCommunicator() { 21 | if (mobCommunicator == null) { 22 | mobCommunicator = new MobCommunicator(1024, PUB_KEY, MODULUS); 23 | } 24 | return mobCommunicator; 25 | } 26 | 27 | /** 28 | * 模拟发送推送消息 29 | * 30 | * @param type 消息类型:1、通知测试;2、内推测试;3、定时 31 | * @param text 模拟发送内容,500字节以内,UTF-8 32 | * @param space 仅对定时消息有效,单位分钟,默认1分钟 33 | */ 34 | public static void sendPush(final int type, final String text, final int space, final String extras, final MobPushCallback callback) { 35 | sendPush(type, text, space, extras, null, null, callback); 36 | } 37 | 38 | /** 39 | * 模拟发送推送消息 40 | * @param type 消息类型:1、通知测试;2、内推测试;3、定时 41 | * @param text 模拟发送内容,500字节以内,UTF-8 42 | * @param space 仅对定时消息有效,单位分钟,默认1分钟 43 | * @param extras 推送消息附加数据 44 | * @param scheme 推送Link指定界面scheme 45 | * @param data 推送Link指定界面需传输的数据 46 | */ 47 | public static void sendPush(final int type, final String text, final int space, final String extras, final String scheme, final String data, final MobPushCallback callback) { 48 | final String content; 49 | if (text != null && text.length() > 35) { 50 | content = text.substring(0, 35); 51 | } else { 52 | content = text; 53 | } 54 | MobPush.getRegistrationId(new MobPushCallback() { 55 | public void onCallback(String regId) { 56 | if (TextUtils.isEmpty(regId)) { 57 | if (callback != null) { 58 | callback.onCallback(false); 59 | } 60 | return; 61 | } 62 | HashMap commonMap = new HashMap(); 63 | commonMap.put("plat", 1); 64 | commonMap.put("registrationId", regId); 65 | commonMap.put("msgType", type); 66 | commonMap.put("content", content); 67 | commonMap.put("space", space); 68 | commonMap.put("appkey", MobSDK.getAppkey()); 69 | if(!TextUtils.isEmpty(extras)){ 70 | commonMap.put("extras", extras); 71 | } 72 | if(!TextUtils.isEmpty(scheme)){ 73 | commonMap.put("scheme", scheme); 74 | } 75 | if(!TextUtils.isEmpty(data)){ 76 | commonMap.put("data", data); 77 | } 78 | getMobCommunicator().request(commonMap, SERVER_URL, false, new MobCommunicator.Callback>() { 79 | public void onResultOk(HashMap data) { 80 | if (callback != null) { 81 | callback.onCallback(true); 82 | } 83 | } 84 | 85 | public void onResultError(Throwable e) { 86 | if (callback != null) { 87 | callback.onCallback(false); 88 | } 89 | } 90 | }); 91 | } 92 | }); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /mobpush_plugin/example/.flutter-plugins-dependencies: -------------------------------------------------------------------------------- 1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"mobpush_plugin","path":"/Users/mobtech-ios/Documents/Projects/Push_Flutter/mobpush_plugin/","dependencies":[]}],"android":[{"name":"mobpush_plugin","path":"/Users/mobtech-ios/Documents/Projects/Push_Flutter/mobpush_plugin/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"mobpush_plugin","dependencies":[]}],"date_created":"2025-03-21 15:53:50.399959","version":"2.10.5"} -------------------------------------------------------------------------------- /mobpush_plugin/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .packages 28 | .pub-cache/ 29 | .pub/ 30 | /build/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Generated.xcconfig 62 | **/ios/Flutter/app.flx 63 | **/ios/Flutter/app.zip 64 | **/ios/Flutter/flutter_assets/ 65 | **/ios/ServiceDefinitions.json 66 | **/ios/Runner/GeneratedPluginRegistrant.* 67 | 68 | # Exceptions to above rules. 69 | !**/ios/**/default.mode1v3 70 | !**/ios/**/default.mode2v3 71 | !**/ios/**/default.pbxuser 72 | !**/ios/**/default.perspectivev3 73 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 74 | -------------------------------------------------------------------------------- /mobpush_plugin/example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 20e59316b8b8474554b38493b8ca888794b0234a 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /mobpush_plugin/example/README.md: -------------------------------------------------------------------------------- 1 | # mobpush_plugin_example 2 | 3 | Demonstrates how to use the mobpush_plugin plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | android 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | 19 | 1632622945694 20 | 21 | 30 22 | 23 | org.eclipse.core.resources.regexFilterMatcher 24 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/agconnect-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "agcgw":{ 3 | "backurl":"connect-drcn.dbankcloud.cn", 4 | "url":"connect-drcn.hispace.hicloud.com" 5 | }, 6 | "client":{ 7 | "cp_id":"890086000300355532", 8 | "product_id":"9105385871708387450", 9 | "client_id":"270119338319545472", 10 | "client_secret":"6DB92E821E63785141F7B6567A0FACA72A3D1162C8ADFCE3D8EB89F453BFB9A4", 11 | "app_id":"101595257", 12 | "package_name":"com.mob.mobpush.demo", 13 | "api_key":"CV5EvYN2K4olyeoxSb1vtUCAPIU09hxIfr30ydHgufgBBygiAV3oQ7Y6O/MevideHH7thj9mI+tqEMKepw/nGuCGK6MI" 14 | }, 15 | "service":{ 16 | "analytics":{ 17 | "collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn", 18 | "resource_id":"p1", 19 | "channel_id":"" 20 | }, 21 | "ml":{ 22 | "mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn" 23 | } 24 | }, 25 | "region":"CN", 26 | "configuration_version":"1.0" 27 | } -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | // 标准: 必须添加, apply plugin: 'com.android.application' 25 | // apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | // apply plugin: 'com.mob.sdk' 27 | // 其他根据业务需要添加 28 | 29 | apply plugin: 'com.android.application' 30 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 31 | apply plugin: 'com.mob.sdk' 32 | apply plugin: 'com.huawei.agconnect' 33 | 34 | android { 35 | compileSdkVersion 31 36 | 37 | lintOptions { 38 | disable 'InvalidPackage' 39 | } 40 | 41 | defaultConfig { 42 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 43 | applicationId "com.mob.mobpush.demo" 44 | minSdkVersion 21 45 | targetSdkVersion 31 46 | versionCode flutterVersionCode.toInteger() 47 | versionName flutterVersionName 48 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 49 | } 50 | 51 | signingConfigs { 52 | release { 53 | keyAlias 'demokey.keystore' 54 | keyPassword '123456' 55 | storeFile file('demokey.keystore') 56 | storePassword '123456' 57 | } 58 | } 59 | 60 | buildTypes { 61 | release { 62 | zipAlignEnabled false 63 | minifyEnabled false// 是否混淆 64 | shrinkResources false// 是否去除无效的资源文件 65 | signingConfig signingConfigs.release 66 | } 67 | 68 | debug { 69 | minifyEnabled false 70 | signingConfig signingConfigs.release 71 | } 72 | } 73 | } 74 | 75 | flutter { 76 | source '../..' 77 | } 78 | 79 | dependencies { 80 | testImplementation 'junit:junit:4.12' 81 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 82 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 83 | } 84 | 85 | // 标准: 必须添加, 86 | // MobSDK { 87 | // appKey "替换为mob官方申请的appkey" 88 | // appSecret "替换为mob官方申请的appkey对应的appSecret" 89 | // [各SDK gradle] {} 90 | // } 91 | 92 | MobSDK { 93 | appKey "2dbe655e88c80" 94 | appSecret "a7b9f1918c596eacbff8a172ba8ed158" 95 | 96 | MobPush { 97 | debugLevel 4 98 | devInfo { 99 | XIAOMI { 100 | appId "2882303761518360245" 101 | appKey "5501836067245" 102 | } 103 | 104 | HUAWEI { 105 | appId "101595257" 106 | } 107 | 108 | MEIZU { 109 | appId "127372" 110 | appKey "3fc6d1acc7ea4f90a0304967ee3a74ae" 111 | } 112 | 113 | FCM { 114 | //设置默认推送通知显示图标 115 | iconRes "@mipmap/ic_launcher" 116 | } 117 | 118 | OPPO { 119 | appKey "6303014506164557acc69df6ef14300b" 120 | appSecret "c850609d8a0f492f8b9eeca1189aaec2" 121 | } 122 | 123 | VIVO { 124 | appId "18568" 125 | appKey "9b01729c-6140-4ad3-ac79-4c4543e12130" 126 | } 127 | HONOR { 128 | appId '220949336' 129 | } 130 | } 131 | } 132 | } 133 | 134 | 135 | apply plugin: 'com.google.gms.google-services' 136 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/demokey.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/android/app/demokey.keystore -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "250330963074", 4 | "firebase_url": "https://mobpushdemo.firebaseio.com", 5 | "project_id": "mobpushdemo", 6 | "storage_bucket": "mobpushdemo.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:250330963074:android:c5f0a867c065fb8a2ee89b", 12 | "android_client_info": { 13 | "package_name": "com.mob.mobpush.demo" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "250330963074-9fcivp990cnldrjf0ll5lrremlf3mmt1.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzaSyCdPCNyFWJTuc5Ozyk68339Eis-N0ffMjA" 25 | } 26 | ], 27 | "services": { 28 | "appinvite_service": { 29 | "other_platform_oauth_client": [ 30 | { 31 | "client_id": "250330963074-9fcivp990cnldrjf0ll5lrremlf3mmt1.apps.googleusercontent.com", 32 | "client_type": 3 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | ], 39 | "configuration_version": "1" 40 | } -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 12 | 20 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | 49 | 50 | 51 | 52 | 55 | 56 | 57 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/java/com/mob/mobpush_example/LinkOneActivity.java: -------------------------------------------------------------------------------- 1 | package com.mob.mobpush_example; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | import com.mob.pushsdk.MobPush; 13 | import com.mob.pushsdk.MobPushUtils; 14 | 15 | import java.util.Set; 16 | 17 | /** 18 | * scheme指定界面跳转目标页-指定界面1 19 | * 推送时通过scheme指定界面跳转,在AndroidManifest.xml文件中配置示例: 20 | * 23 | * 24 | * 25 | * 26 | * 29 | * 30 | *

31 | * 32 | * 需添加intent-filter,配置相关action、category和data信息 33 | * 通过scheme://host格式填写scheme字段信息来进行指定界面推送。 34 | * 如果scheme指定界面携带附加数据,MobPush、魅族、小米、华为等四个推送通道进行了默认处理,把指定界面的附加数据统一放入了"data"的intent extra中, 35 | * 可通过getIntent().getExtras.get("data")获取附加数据; 36 | * 而FCM(应用非前台情况下)、OPPO通道的特殊性,无法进行默认处理,需在启动页中获取附加字段单独处理界面跳转和附加数据的传入。 37 | */ 38 | public class LinkOneActivity extends Activity implements View.OnClickListener { 39 | private final static String MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY = "data"; 40 | 41 | private TextView tvTitle; 42 | private ImageView ivBack; 43 | private TextView tv; 44 | 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | setContentView(R.layout.act_link_one); 49 | findView(); 50 | initView(); 51 | initData(); 52 | } 53 | 54 | @Override 55 | protected void onNewIntent(Intent intent) { 56 | super.onNewIntent(intent); 57 | setIntent(intent); 58 | initData(); 59 | } 60 | 61 | private void findView() { 62 | tvTitle = findViewById(R.id.tvTitle); 63 | ivBack = findViewById(R.id.ivBack); 64 | tv = findViewById(R.id.tv); 65 | } 66 | 67 | private void initView() { 68 | tvTitle.setText(R.string.link_one_title); 69 | ivBack.setOnClickListener(this); 70 | } 71 | 72 | private void initData() { 73 | Intent intent = getIntent(); 74 | Uri uri = intent.getData(); 75 | if (intent != null) { 76 | MobPushUtils.parseSchemePluginPushIntent(intent); 77 | MobPush.notificationClickAck(intent); 78 | System.out.println("MobPush linkone intent---" + intent.toUri(Intent.URI_INTENT_SCHEME)); 79 | } 80 | 81 | StringBuilder sb = new StringBuilder(); 82 | if (uri != null) { 83 | sb.append(" scheme:" + uri.getScheme() + "\n"); 84 | sb.append(" host:" + uri.getHost() + "\n"); 85 | sb.append(" port:" + uri.getPort() + "\n"); 86 | sb.append(" query:" + uri.getQuery() + "\n"); 87 | } 88 | 89 | //获取link界面传输的数据,取字段data数据 90 | Bundle bundle = intent.getExtras(); 91 | if (bundle != null && bundle.containsKey(MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY)) { 92 | sb.append(" extras:" + (bundle.containsKey(MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY) 93 | ? bundle.get(MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY).toString() : "")); 94 | } 95 | if (bundle != null) { 96 | sb.append("\n" + "bundle toString :" + bundle.toString()); 97 | Set keySet = bundle.keySet(); 98 | for (String key : keySet) { 99 | System.out.println("MobPush linkone bundle------------->" + key); 100 | System.out.println("MobPush linkone bundle------------->" + bundle.get(key)); 101 | } 102 | } 103 | tv.setText(sb); 104 | } 105 | 106 | @Override 107 | public void onClick(View v) { 108 | switch (v.getId()) { 109 | case R.id.ivBack: { 110 | finish(); 111 | } 112 | break; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/java/com/mob/mobpush_example/LinkTwoActivity.java: -------------------------------------------------------------------------------- 1 | package com.mob.mobpush_example; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | /** 12 | * scheme指定界面跳转目标页-指定界面2 13 | * 推送时通过scheme指定界面跳转,在AndroidManifest.xml文件中配置示例: 14 | * 16 | * 17 | * 18 | * 19 | * 22 | * 23 | * 24 | * 需添加intent-filter,配置相关action、category和data信息 25 | * 通过scheme://host格式填写scheme字段信息来进行指定界面推送。 26 | * 如果scheme指定界面携带附加数据,MobPush、魅族、小米、华为等四个推送通道进行了默认处理,把指定界面的附加数据统一放入了"data"的intent extra中, 27 | * 可通过getIntent().getExtras.get("data")获取附加数据; 28 | * 而FCM(应用非前台情况下)、OPPO通道的特殊性,无法进行默认处理,需在启动页中获取附加字段单独处理界面跳转和附加数据的传入。 29 | */ 30 | public class LinkTwoActivity extends Activity implements View.OnClickListener { 31 | private final static String MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY = "data"; 32 | 33 | private TextView tvTitle; 34 | private ImageView ivBack; 35 | private TextView tv; 36 | 37 | @Override 38 | protected void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.act_link_two); 41 | findView(); 42 | initView(); 43 | initData(); 44 | } 45 | 46 | private void findView() { 47 | tvTitle = findViewById(R.id.tvTitle); 48 | ivBack = findViewById(R.id.ivBack); 49 | tv = findViewById(R.id.tv); 50 | } 51 | 52 | private void initView() { 53 | tvTitle.setText(R.string.link_two_title); 54 | ivBack.setOnClickListener(this); 55 | } 56 | 57 | private void initData() { 58 | Intent intent = getIntent(); 59 | Uri uri = intent.getData(); 60 | StringBuilder sb = new StringBuilder(); 61 | if (uri != null) { 62 | sb.append(" scheme:" + uri.getScheme() + "\n"); 63 | sb.append(" host:" + uri.getHost() + "\n"); 64 | // sb.append(" port:" + uri.getPort() + "\n"); 65 | // sb.append(" query:" + uri.getQuery() + "\n"); 66 | } 67 | 68 | //获取link界面传输的数据,取字段data数据 69 | Bundle bundle = intent.getExtras(); 70 | if (bundle != null && bundle.containsKey(MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY)) { 71 | sb.append(" extras:" + (bundle.containsKey(MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY) 72 | ? bundle.get(MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY).toString() : "")); 73 | } 74 | tv.setText(sb); 75 | } 76 | 77 | @Override 78 | public void onClick(View v) { 79 | switch (v.getId()) { 80 | case R.id.ivBack: { 81 | finish(); 82 | } 83 | break; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/java/com/mob/mobpush_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.mob.mobpush_example; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | 9 | import com.mob.flutter.mobpush.MobpushPlugin; 10 | import com.mob.mobpush_example.utils.PlayloadDelegate; 11 | import com.mob.pushsdk.MobPush; 12 | import com.mob.pushsdk.MobPushUtils; 13 | 14 | import io.flutter.embedding.android.FlutterActivity; 15 | import io.flutter.embedding.engine.FlutterEngine; 16 | import io.flutter.plugins.GeneratedPluginRegistrant; 17 | 18 | public class MainActivity extends FlutterActivity { 19 | @Override 20 | public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { 21 | super.configureFlutterEngine(flutterEngine); 22 | GeneratedPluginRegistrant.registerWith(flutterEngine); 23 | } 24 | 25 | @Override 26 | protected void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | MobpushPlugin.parseManufacturerMessage(getIntent()); 29 | dealPushResponse(getIntent()); 30 | } 31 | 32 | @Override 33 | protected void onNewIntent(Intent intent) { 34 | super.onNewIntent(intent); 35 | //需要调用setIntent方法,不然后面获取到的getIntent都试上一次传的数据 36 | setIntent(intent); 37 | MobpushPlugin.parseManufacturerMessage(intent); 38 | dealPushResponse(intent); 39 | } 40 | private void dealPushResponse(Intent intent) { 41 | Bundle bundle = null; 42 | if (intent != null) { 43 | MobPush.notificationClickAck(intent); 44 | MobPushUtils.parseMainPluginPushIntent(intent); 45 | bundle = intent.getExtras(); 46 | new PlayloadDelegate().playload(this, bundle); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/java/com/mob/mobpush_example/utils/PlayloadDelegate.java: -------------------------------------------------------------------------------- 1 | package com.mob.mobpush_example.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.text.TextUtils; 8 | import android.util.Log; 9 | 10 | import com.mob.mobpush_example.web.WebViewPage; 11 | import com.mob.pushsdk.MobPushNotifyMessage; 12 | import com.mob.tools.utils.Hashon; 13 | 14 | import java.util.HashMap; 15 | import java.util.Set; 16 | 17 | 18 | /** 19 | * 推送消息携带附加数据处理类 20 | * >.附加数据的获取可在点击通知的落地页里的onCreate()或onNewIntent()里通过相关Intent的getExtras进行获取 21 | * >.落地页的附加数据大致分两种情况:1>MobPush自身通道和小米、魅族、华为三大厂商通道: 22 | * 1>默认落地页的情况下,针对MobPush自身通道和小米、魅族、华为三大厂商通道,需通过[msg]固定的key来获取数据 23 | * 2>配置scheme指定页的情况下,针对MobPush自身通道和小米、魅族、华为三大厂商通道,MobPush内部已经处理跳转指定页,并可通过Intent的getExtras用[data]进行获取指定页的附加数据 24 | *

25 | * 2>OPPO通道:默认落地页和配置scheme指定页都是打开默认启动页(OPPO系统控制打开默认启动页),在默认启动页中 26 | * 附加数据都在[pluginExtra]的固定key中获取,如果配置了scheme指定页,对于OPPO通道来说是不生效的,需自行在代码 27 | * 中通过[mobpush_link_k]来获取scheme处理跳转,如果同时携带了scheme的附加数据则需通过[mobpush_link_v]获取数据 28 | *

29 | * 3>FCM通道: 默认落地页和配置scheme指定页都是打开默认启动页(google 服务控制打开默认启动页),而且附加字段完全暴露在从Intent的getExtras的Bundle中, 30 | * 配置了scheme,对于FCM通道来说也是不生效的,需自行在代码中通过[mobpush_link_k]来获取scheme处理跳转,如果同时携带了scheme的附加数据则需通过[mobpush_link_v]获取数据 31 | */ 32 | public class PlayloadDelegate { 33 | //固定推送附加字段: 34 | private final static String MOB_PUSH_SCHEME_KEY = "mobpush_link_k"; 35 | private final static String MOB_PUSH_SCHEME_PLAYLOAD_KEY = "mobpush_link_v"; 36 | private final static String MOB_PUSH_OPPO_EXTRA_DATA = "pluginExtra"; 37 | private final static String MOB_PUSH_NORMAL_PLAYLOAD_KEY = "msg"; 38 | private final static String MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY = "data"; 39 | 40 | //如果是从后台的扩展参数传,则可以随意定义: 41 | private final static String MOB_PUSH_DEMO_URL = "url"; 42 | 43 | public void playload(Context context, Bundle bundle) { 44 | try { 45 | if (bundle == null) { 46 | return; 47 | } 48 | 49 | Set keySet = bundle.keySet(); 50 | if (keySet == null || keySet.isEmpty()) { 51 | return; 52 | } 53 | HashMap map = new HashMap(); 54 | for (String key : keySet) { 55 | System.out.println("MobPush playload bundle------------->" + key); 56 | System.out.println("MobPush playload bundle------------->" + bundle.get(key)); 57 | 58 | if (key.equals(MOB_PUSH_OPPO_EXTRA_DATA)) { 59 | map = parseOPPOPlayload(bundle); 60 | 61 | } else if (key.equals(MOB_PUSH_NORMAL_PLAYLOAD_KEY)) { 62 | map = parseNormalPlayload(bundle); 63 | 64 | } else { 65 | Object object = bundle.get(key); 66 | System.out.println(">>>>>>key: " + key + ", object: " + object); 67 | map.put(key, String.valueOf(object)); 68 | } 69 | } 70 | 71 | if (map != null && !map.isEmpty()) { 72 | realPerform(context, map); 73 | } 74 | } catch (Throwable throwable) { 75 | Log.e("MobPush playload", throwable.getMessage()); 76 | } 77 | } 78 | 79 | private void realPerform(Context context, HashMap map) { 80 | if (map == null) { 81 | return; 82 | } 83 | String json = ""; 84 | 85 | Set keys = map.keySet(); 86 | for (String key : keys) { 87 | System.out.println(">>>>>>>>>>all key: " + key + ", value: " + map.get(key)); 88 | } 89 | 90 | if (keys != null && keys.size() == 1 && (keys.contains("profile") || keys.contains("workId"))) { 91 | return; 92 | } 93 | 94 | for (String key : keys) { 95 | if (!"profile".equals(key) && !"workId".equals(key) 96 | && !"collapse_key".equals(key) && !key.startsWith("google.") && !"from".equals(key)) { 97 | json += "key: " + key + ", value: " + map.get(key) + "\n"; 98 | } 99 | } 100 | // Toast.makeText(context, json, Toast.LENGTH_SHORT).show(); 101 | 102 | //通过配置scheme跳转指定界面则需使用固定的key来获取相关数据 103 | if (map.containsKey(MOB_PUSH_SCHEME_KEY)) { 104 | openAct(context, map); 105 | } else { 106 | //处理其他自定义数据的业务逻辑,例如打开网页:通过自定义的key来获取对应的数据 107 | if (map.containsKey(MOB_PUSH_DEMO_URL)) { 108 | openUrl(context, map); 109 | } else if (map.containsKey(MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY)) { 110 | System.out.println(">>>>>>>>>>scheme Activity with playload data: " + MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY + ", value: " + map.get(MOB_PUSH_NORMAL_SCHEME_PLAYLOAD_KEY)); 111 | } else { 112 | 113 | } 114 | } 115 | } 116 | 117 | private HashMap parseOPPOPlayload(Bundle bundle) { 118 | HashMap hashMap = null; 119 | String v = String.valueOf(bundle.get(MOB_PUSH_OPPO_EXTRA_DATA)); 120 | if (!TextUtils.isEmpty(v)) { 121 | hashMap = new Hashon().fromJson(v); 122 | } 123 | return hashMap; 124 | } 125 | 126 | private HashMap parseNormalPlayload(Bundle bundle) { 127 | HashMap hashMap = null; 128 | try { 129 | MobPushNotifyMessage notifyMessage = (MobPushNotifyMessage) bundle.getSerializable(MOB_PUSH_NORMAL_PLAYLOAD_KEY); 130 | if (notifyMessage != null) { 131 | hashMap = notifyMessage.getExtrasMap(); 132 | } 133 | } catch (Throwable throwable) { 134 | Log.e("MobPush", throwable.getMessage()); 135 | hashMap = new HashMap(); 136 | } 137 | return hashMap; 138 | } 139 | 140 | private void openUrl(Context context, HashMap params) { 141 | String url; 142 | if (!TextUtils.isEmpty((CharSequence) params.get(MOB_PUSH_DEMO_URL))) { 143 | url = (String) params.get(MOB_PUSH_DEMO_URL); 144 | } else { 145 | url = "http://m.mob.com"; 146 | } 147 | if (!url.startsWith("http://") && !url.startsWith("https://")) { 148 | url = "http://" + url; 149 | } 150 | System.out.println("url:" + url); 151 | WebViewPage webViewPage = new WebViewPage(); 152 | webViewPage.setJumpUrl(url); 153 | webViewPage.show(context, null); 154 | } 155 | 156 | private void openAct(Context context, HashMap params) { 157 | String uri = params.containsKey(MOB_PUSH_SCHEME_KEY) ? (String) params.get(MOB_PUSH_SCHEME_KEY) : ""; 158 | if (TextUtils.isEmpty(uri)) { 159 | return; 160 | } 161 | Intent intent = new Intent(null, Uri.parse(uri)); 162 | intent.setPackage(context.getPackageName()); 163 | if (params.containsKey(MOB_PUSH_SCHEME_PLAYLOAD_KEY) && params.get(MOB_PUSH_SCHEME_PLAYLOAD_KEY) != null) { 164 | intent.putExtra("data", (String) params.get(MOB_PUSH_SCHEME_PLAYLOAD_KEY)); 165 | } 166 | context.startActivity(intent); 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/java/com/mob/mobpush_example/utils/SizeHelper.java: -------------------------------------------------------------------------------- 1 | package com.mob.mobpush_example.utils; 2 | 3 | import android.content.Context; 4 | 5 | import com.mob.tools.utils.ResHelper; 6 | 7 | 8 | public class SizeHelper { 9 | public static float designedDensity = 1.5f; 10 | public static int designedScreenWidth = 540; 11 | private static Context context = null; 12 | 13 | protected static SizeHelper helper; 14 | 15 | private SizeHelper() { 16 | } 17 | 18 | public static void prepare(Context c) { 19 | if (context == null || context != c.getApplicationContext()) { 20 | context = c; 21 | } 22 | } 23 | 24 | /** 25 | * 根据density转换设计的px到目标机器,返回px大小 26 | * 27 | * @return 像素大小 28 | */ 29 | public static int fromPx(int px) { 30 | return ResHelper.designToDevice(context, designedDensity, px); 31 | } 32 | 33 | /** 34 | * 根据屏幕宽度转换设计的px到目标机器,返回px大小 35 | * 36 | * @return 像素大小 37 | */ 38 | public static int fromPxWidth(int px) { 39 | return ResHelper.designToDevice(context, designedScreenWidth, px); 40 | } 41 | 42 | /** 43 | * 根据density转换设计的dp到目标机器,返回px大小 44 | * 45 | * @return 像素大小 46 | */ 47 | public static int fromDp(int dp) { 48 | int px = ResHelper.dipToPx(context, dp); 49 | return ResHelper.designToDevice(context, designedDensity, px); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/java/com/mob/mobpush_example/web/BaseWebView.java: -------------------------------------------------------------------------------- 1 | package com.mob.mobpush_example.web; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.util.AttributeSet; 6 | import android.webkit.WebSettings; 7 | import android.webkit.WebView; 8 | 9 | public class BaseWebView extends WebView { 10 | 11 | public BaseWebView(Context context) { 12 | super(context); 13 | initSettings(); 14 | } 15 | 16 | public BaseWebView(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | initSettings(); 19 | } 20 | 21 | public BaseWebView(Context context, AttributeSet attrs, int defStyleAttr) { 22 | super(context, attrs, defStyleAttr); 23 | initSettings(); 24 | if (Build.VERSION.SDK_INT >= 11) { 25 | removeJavascriptInterface("searchBoxJavaBridge_"); 26 | removeJavascriptInterface("accessibility"); 27 | removeJavascriptInterface("accessibilityTraversal"); 28 | } 29 | } 30 | 31 | private void initSettings() { 32 | WebSettings settings = getSettings(); 33 | settings.setCacheMode(WebSettings.LOAD_NO_CACHE); 34 | settings.setUseWideViewPort(true); 35 | settings.setJavaScriptEnabled(true); 36 | // settings.setDomStorageEnabled(true); 37 | setVerticalScrollBarEnabled(false); 38 | setHorizontalScrollBarEnabled(false); 39 | settings.setAppCacheEnabled(false); 40 | // settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); 41 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 42 | getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/java/com/mob/mobpush_example/web/WebViewPage.java: -------------------------------------------------------------------------------- 1 | package com.mob.mobpush_example.web; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.graphics.Bitmap; 7 | import android.graphics.drawable.ColorDrawable; 8 | import android.net.Uri; 9 | import android.net.http.SslError; 10 | import android.util.TypedValue; 11 | import android.view.Gravity; 12 | import android.view.KeyEvent; 13 | import android.view.View; 14 | import android.view.Window; 15 | import android.webkit.SslErrorHandler; 16 | import android.webkit.WebChromeClient; 17 | import android.webkit.WebView; 18 | import android.webkit.WebViewClient; 19 | import android.widget.ImageView; 20 | import android.widget.LinearLayout; 21 | import android.widget.LinearLayout.LayoutParams; 22 | import android.widget.ProgressBar; 23 | import android.widget.TextView; 24 | 25 | import com.mob.mobpush_example.utils.SizeHelper; 26 | import com.mob.tools.FakeActivity; 27 | import com.mob.tools.utils.ResHelper; 28 | 29 | /** 30 | * Created by yychen on 2017/11/2. 31 | */ 32 | 33 | public class WebViewPage extends FakeActivity { 34 | private LinearLayout mainlayout; 35 | private ImageView ivBack; 36 | private TextView tvTitle; 37 | private ProgressBar progressBar; 38 | private BaseWebView webView; 39 | private String url; 40 | 41 | @Override 42 | public void onCreate() { 43 | Window window = activity.getWindow(); 44 | window.setBackgroundDrawable(new ColorDrawable(0xFFFFFFFF)); 45 | initPage(activity); 46 | activity.setContentView(mainlayout); 47 | } 48 | 49 | public void setJumpUrl(String url) { 50 | this.url = url; 51 | } 52 | 53 | private void initPage(final Activity activity) { 54 | initView(); 55 | 56 | webView.setWebViewClient(new WebViewClient() { 57 | private String startUrl; 58 | 59 | @Override 60 | public void onPageStarted(WebView view, String url, Bitmap favicon) { 61 | super.onPageStarted(view, url, favicon); 62 | startUrl = url; 63 | } 64 | 65 | public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 66 | handler.proceed(); 67 | } 68 | 69 | @Override 70 | public boolean shouldOverrideUrlLoading(WebView view, String url1) { 71 | if (url1 == null) return false; 72 | try { 73 | if (!url1.startsWith("http://") && !url1.startsWith("https://")) { 74 | Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url1)); 75 | startActivity(intent); 76 | return false; 77 | } 78 | } catch (Exception e) { 79 | // //防止crash (如果手机上没有安装处理某个scheme开头的url的APP, 会导致crash) 80 | return true;//没有安装该app时,返回true,表示拦截自定义链接,但不跳转,避免弹出上面的错误页面 81 | } 82 | 83 | //返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器 84 | if (startUrl != null && startUrl.equals(url)) { 85 | view.loadUrl(url); 86 | } else { 87 | //交给系统处理 88 | return super.shouldOverrideUrlLoading(view, url); 89 | } 90 | return true; 91 | } 92 | 93 | public void onPageFinished(WebView view, String url) { 94 | super.onPageFinished(view, url); 95 | if (view != null) { 96 | tvTitle.setText(view.getTitle()); 97 | } 98 | } 99 | }); 100 | webView.setWebChromeClient(new WebChromeClient() { 101 | public void onProgressChanged(WebView view, int newProgress) { 102 | progressBar.setProgress(newProgress); 103 | if (newProgress == 100) { 104 | progressBar.setVisibility(View.GONE); 105 | } else if (progressBar.getVisibility() == View.GONE) { 106 | progressBar.setVisibility(View.VISIBLE); 107 | } 108 | super.onProgressChanged(view, newProgress); 109 | } 110 | }); 111 | 112 | webView.loadUrl(url); 113 | ivBack.setOnClickListener(new View.OnClickListener() { 114 | @Override 115 | public void onClick(View view) { 116 | if (webView != null && webView.canGoBack()) { 117 | webView.goBack(); 118 | } else { 119 | finishOnSuccess(); 120 | } 121 | } 122 | }); 123 | } 124 | 125 | @SuppressLint("WrongConstant") 126 | private void initView() { 127 | SizeHelper.prepare(getContext()); 128 | int px2 = SizeHelper.fromPxWidth(2); 129 | int px3 = SizeHelper.fromPxWidth(3); 130 | int px15 = SizeHelper.fromPxWidth(15); 131 | int px30 = SizeHelper.fromPxWidth(30); 132 | 133 | mainlayout = new LinearLayout(getContext()); 134 | mainlayout.setOrientation(LinearLayout.VERTICAL); 135 | LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 136 | 137 | LinearLayout titlelayout = new LinearLayout(getContext()); 138 | titlelayout.setPadding(px15, 0, px15, 0); 139 | lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0, 1); 140 | mainlayout.addView(titlelayout, lp); 141 | 142 | ivBack = new ImageView(getContext()); 143 | ivBack.setScaleType(ImageView.ScaleType.CENTER_CROP); 144 | ivBack.setImageResource(ResHelper.getBitmapRes(getContext(), "ic_back")); 145 | lp = new LayoutParams(px30, px30); 146 | lp.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL; 147 | titlelayout.addView(ivBack, lp); 148 | 149 | tvTitle = new TextView(getContext()); 150 | tvTitle.setGravity(Gravity.CENTER); 151 | tvTitle.setMaxLines(1); 152 | tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, SizeHelper.fromPxWidth(22)); 153 | tvTitle.setTextColor(0xff1e1e1e); 154 | lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 155 | lp.gravity = Gravity.CENTER_VERTICAL; 156 | lp.leftMargin = px15; 157 | titlelayout.addView(tvTitle, lp); 158 | 159 | //分割线 160 | View line = new View(getContext()); 161 | line.setBackgroundColor(0xffe8e8e8); 162 | lp = new LayoutParams(LayoutParams.MATCH_PARENT, px2); 163 | mainlayout.addView(line, lp); 164 | 165 | progressBar = new ProgressBar(getContext(), null, android.R.style.Widget_ProgressBar_Horizontal); 166 | progressBar.setMax(100); 167 | progressBar.setIndeterminate(false); 168 | lp = new LayoutParams(LayoutParams.MATCH_PARENT, px3); 169 | mainlayout.addView(progressBar, lp); 170 | progressBar.setProgressDrawable(activity.getResources().getDrawable(ResHelper.getBitmapRes(getContext(), "webview_progressbar_bg"))); 171 | 172 | webView = new BaseWebView(getContext()); 173 | lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0, 11); 174 | mainlayout.addView(webView, lp); 175 | } 176 | 177 | public boolean onKeyEvent(int keyCode, KeyEvent event) { 178 | if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { 179 | if (webView != null && webView.canGoBack()) { 180 | webView.goBack(); 181 | } else { 182 | finishOnSuccess(); 183 | } 184 | return true; 185 | } 186 | return super.onKeyEvent(keyCode, event); 187 | } 188 | 189 | public void finishOnSuccess() { 190 | finish(); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/drawable/webview_progressbar_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/layout/act_link_one.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/layout/act_link_two.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/layout/title_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 15 | 22 | 23 | 28 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_back.png -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MobPush 3 | 选择你想测试的推送类型 4 | App内推送 5 | App内推送测试 6 | 通知 7 | 通知测试 8 | 定时通知 9 | 定时通知测试 10 | 本地通知 11 | 通过推送打开指定链接页面 12 | 设置 13 | 创建NotificationChannel 14 | 本地通知提醒测试 15 | 点击测试按钮后,你将立即收到一条app内推送 16 | 填写推送内容(不超过35个字) 17 | 点击测试 18 | 跳转URL 19 | 请填写URL地址,为空则跳转至mob官网 20 | 系统推送通知内容 21 | 点击测试按钮后,请在前台关闭App,5s后你将收到一条测试通知 22 | 点击测试按钮后,请在前台关闭App,在你设定的时间到了时你将收到一条测试通知 23 | 编辑完成后,点击测试按钮,你将立即收到一条推送消息,点击后可跳转至指定页面。 24 | 设置时间后点击测试按钮,请在前台关闭App,在你设定的时间到了时你将收到本地通知提醒 25 | 此时间只为方便测试功能,后台使用时不可设定1小时内的定时推送 26 | 立即 27 | 1分钟后 28 | 2分钟后 29 | 3分钟后 30 | 4分钟后 31 | 5分钟后 32 | 推送内容不能为空 33 | 发送成功 34 | 发送失败,请检查网络重试 35 | 收到推送 36 | 我知道了 37 | 此推送服务由MobPush提供 38 | 推送发送成功!请在前台关闭app,5S后你将收到一条测试通知 39 | 推送发送成功!请在前台关闭app,%s后你将收到一条测试通知 40 | 推送发送成功!请在前台关闭app,5S后你将收到一条打开链接的消息 41 | 42 | 程序抢修中,请稍后重试~ 43 | 网络不给力,请检查网络后再试~ 44 | mobPush 45 | 46 | 47 | 推送打开应用内指定页面 48 | 打开应用内指定页面测试 49 | 编辑完成后,点击测试按钮后,你将立即收到一条推送消息,点击后可跳转至指定的应用内页面 50 | 填写推送内容(字数不超过35个字) 51 | 推送打开首页 52 | 推送打开指定界面1 53 | 推送打开指定界面2 54 | 通知测试页面 55 | 推送发送成功!你将收到一条能跳转至应用内指定页面的通知 56 | Link打开指定界面1 57 | Link打开指定界面2 58 | Link Activity Success. 59 | 通知权限已关闭 60 | 61 | 设置 62 | 隐私协议开关 63 | 获取rid 64 | 获取厂商token 65 | 设置大图标 66 | 去除大图标 67 | 设置自定义通知 68 | 移除自定义通知 69 | 设置前台时不显示推送 70 | 设置前台时显示推送 71 | 绑定手机号 72 | 获取手机号 73 | 请输入内容 74 | 取消 75 | 确定 76 | 设置手机号成功 77 | 设置手机号失败 78 | 请输入正确的手机号 79 | 设置别名 80 | 删除别名 81 | 获取别名 82 | 添加标签 83 | 删除标签 84 | 获取标签 85 | 清空标签 86 | 87 | 显示角标 88 | 不显示角标 89 | 获取是否显示角标 90 | 设置角标数 91 | 请输入角标数 92 | 93 | 推送本地通知 94 | 移除本地通知 95 | 清除本地通知 96 | 清除所有通知(包括MobPush通道和厂商通道通知,其中华为、小米、魅族厂商通道有效,其他厂商通道无效) 97 | 清除角标 98 | 99 | 启用Push 100 | 停用Push 101 | 102 | 通知通道ID 103 | 通知通道Name 104 | 通知通道重要性 105 | 创建通知通道 106 | tcp状态检测 107 | 开启通知栏权限监控 108 | 关闭通知栏权限监控 109 | startTest 110 | 显示最大通知个数 111 | 请输入最大通知个数 112 | 是否设置notification group属性 113 | 请输入通知事件1~9,以英文,隔开 114 | 设置刷新触发事件 115 | 116 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { 4 | url "https://mvn.mob.com/android" 5 | } 6 | maven { url 'https://developer.huawei.com/repo/' } 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | // 标准: 必须添加 classpath 'com.android.tools.build:gradle:3.2.1' 12 | // classpath 'com.mob.sdk:MobSDK:+' 13 | // 其他根据业务需要添加 14 | dependencies { 15 | classpath 'com.android.tools.build:gradle:3.6.0' 16 | classpath 'com.mob.sdk:MobSDK:+' 17 | classpath 'com.google.gms:google-services:4.3.3' // google-services plugin 18 | classpath 'com.huawei.agconnect:agcp:1.2.0.300' 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | maven { 25 | url "https://mvn.mob.com/android" 26 | } 27 | maven { url 'https://developer.huawei.com/repo/' } 28 | google() 29 | mavenCentral() 30 | } 31 | } 32 | 33 | rootProject.buildDir = '../build' 34 | subprojects { 35 | project.buildDir = "${rootProject.buildDir}/${project.name}" 36 | } 37 | subprojects { 38 | project.evaluationDependsOn(':app') 39 | } 40 | 41 | tasks.register('clean', Delete) { 42 | delete rootProject.buildDir 43 | } 44 | 45 | -------------------------------------------------------------------------------- /mobpush_plugin/example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true -------------------------------------------------------------------------------- /mobpush_plugin/example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /mobpush_plugin/example/assets/images/ic_item_app_nitify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/assets/images/ic_item_app_nitify.png -------------------------------------------------------------------------------- /mobpush_plugin/example/assets/images/ic_item_local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/assets/images/ic_item_local.png -------------------------------------------------------------------------------- /mobpush_plugin/example/assets/images/ic_item_media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/assets/images/ic_item_media.png -------------------------------------------------------------------------------- /mobpush_plugin/example/assets/images/ic_item_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/assets/images/ic_item_notify.png -------------------------------------------------------------------------------- /mobpush_plugin/example/assets/images/ic_item_open_act.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/assets/images/ic_item_open_act.png -------------------------------------------------------------------------------- /mobpush_plugin/example/assets/images/ic_item_timing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/assets/images/ic_item_timing.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Flutter/Flutter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: This podspec is NOT to be published. It is only used as a local source! 3 | # This is a generated file; do not edit or check into version control. 4 | # 5 | 6 | Pod::Spec.new do |s| 7 | s.name = 'Flutter' 8 | s.version = '1.0.0' 9 | s.summary = 'High-performance, high-fidelity mobile apps.' 10 | s.homepage = 'https://flutter.io' 11 | s.license = { :type => 'MIT' } 12 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } 13 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } 14 | s.ios.deployment_target = '9.0' 15 | # Framework linking is handled by Flutter tooling, not CocoaPods. 16 | # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. 17 | s.vendored_frameworks = 'path/to/nothing' 18 | end 19 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/Users/mobtech-ios/Documents/Projects/Flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Users/mobtech-ios/Documents/Projects/Push_Flutter/mobpush_plugin/example" 5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true" 6 | export "FLUTTER_TARGET=lib/main.dart" 7 | export "FLUTTER_BUILD_DIR=build" 8 | export "FLUTTER_BUILD_NAME=1.0.0" 9 | export "FLUTTER_BUILD_NUMBER=1" 10 | export "DART_OBFUSCATION=false" 11 | export "TRACK_WIDGET_CREATION=false" 12 | export "TREE_SHAKE_ICONS=true" 13 | export "PACKAGE_CONFIG=/Users/mobtech-ios/Documents/Projects/Push_Flutter/mobpush_plugin/example/.dart_tool/package_config.json" 14 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 32 | end 33 | 34 | post_install do |installer| 35 | installer.pods_project.targets.each do |target| 36 | flutter_additional_ios_build_settings(target) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - FlyVerifyCSDK (1.0.4) 4 | - mob_pushsdk (4.2.6): 5 | - mob_pushsdk/MobPush (= 4.2.6) 6 | - MOBFoundation 7 | - mob_pushsdk/MobPush (4.2.6): 8 | - MOBFoundation 9 | - MOBFoundation (20250221): 10 | - FlyVerifyCSDK (>= 0.0.7) 11 | - mobpush_plugin (1.1.0): 12 | - Flutter 13 | - mob_pushsdk 14 | 15 | DEPENDENCIES: 16 | - Flutter (from `Flutter`) 17 | - mobpush_plugin (from `.symlinks/plugins/mobpush_plugin/ios`) 18 | 19 | SPEC REPOS: 20 | trunk: 21 | - FlyVerifyCSDK 22 | - mob_pushsdk 23 | - MOBFoundation 24 | 25 | EXTERNAL SOURCES: 26 | Flutter: 27 | :path: Flutter 28 | mobpush_plugin: 29 | :path: ".symlinks/plugins/mobpush_plugin/ios" 30 | 31 | SPEC CHECKSUMS: 32 | Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a 33 | FlyVerifyCSDK: 6abc7ed81b332f69f72e1e113990cfd88fc335f0 34 | mob_pushsdk: 873fb39cd315ca2d342da25c00273a67273ea4b3 35 | MOBFoundation: 600c32f816bd0ebf5e2048c8e40357217d22ea9c 36 | mobpush_plugin: c7924c87d18b622e0bda192bb841fb3e1a13326a 37 | 38 | PODFILE CHECKSUM: 8e679eca47255a8ca8067c4c67aab20e64cb974d 39 | 40 | COCOAPODS: 1.16.2 41 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | mobpush_plugin_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UIBackgroundModes 31 | 32 | remote-notification 33 | fetch 34 | 35 | UILaunchStoryboardName 36 | LaunchScreen 37 | UIMainStoryboardFile 38 | Main 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | UISupportedInterfaceOrientations~ipad 46 | 47 | UIInterfaceOrientationPortrait 48 | UIInterfaceOrientationPortraitUpsideDown 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/Runner.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /mobpush_plugin/example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /mobpush_plugin/example/lib/app_notify_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:mobpush_plugin/mobpush_plugin.dart'; 3 | 4 | class AppNotifyPage extends StatefulWidget { 5 | @override 6 | _AppNotifyPageState createState() { 7 | return new _AppNotifyPageState(); 8 | } 9 | } 10 | 11 | class _AppNotifyPageState extends State { 12 | TextEditingController _controller = new TextEditingController(); 13 | 14 | void _send() async { 15 | if (_controller.text.isNotEmpty) { 16 | //发送消息类型为2的自定义透传消息,推送内容时输入框输入的内容,延迟推送时间为0(立即推送),附加数据为空 17 | MobpushPlugin.send(2, _controller.text, 0, '').then((Map sendMap){ 18 | String res = sendMap['res']; 19 | String error = sendMap['error']; 20 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> send -> res: $res error: $error"); 21 | }); 22 | } 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return Scaffold( 28 | appBar: AppBar( 29 | title: Text('App内推送测试'), 30 | iconTheme: IconThemeData(color: Colors.black), 31 | textTheme: TextTheme(headline6: TextStyle(color: Colors.black)), 32 | backgroundColor: Colors.white, 33 | centerTitle: true, 34 | ), 35 | body: Container( 36 | margin: EdgeInsets.all(15.0), 37 | child: Column( 38 | crossAxisAlignment: CrossAxisAlignment.start, 39 | children: [ 40 | Text( 41 | '点击测试按钮后,你将立即收到一条App内推送', 42 | textAlign: TextAlign.left, 43 | ), 44 | Container( 45 | margin: EdgeInsets.only(top: 10, bottom: 30), 46 | child: TextField( 47 | maxLines: 5, 48 | maxLength: 35, 49 | decoration: InputDecoration( 50 | hintText: '推送内容(不超过35个字)', 51 | contentPadding: EdgeInsets.all(10), 52 | border: OutlineInputBorder( 53 | borderRadius: BorderRadius.all(Radius.circular(5.0)), 54 | borderSide: BorderSide( 55 | color: Color(0xFFe1e1e1), 56 | width: 0.5, 57 | style: BorderStyle.solid, 58 | ) 59 | ) 60 | ), 61 | controller: _controller, 62 | ), 63 | ), 64 | Row( 65 | children: [ 66 | new Expanded( 67 | child: new ElevatedButton( 68 | child: Text( 69 | '点击测试', 70 | style: new TextStyle(color: Colors.white), 71 | ), 72 | onPressed: _send, 73 | ), 74 | // child: new RaisedButton( 75 | // padding: EdgeInsets.symmetric(vertical: 12), 76 | // color: Color(0xFF7B91FF), 77 | // child: Text( 78 | // '点击测试', 79 | // style: new TextStyle(color: Colors.white), 80 | // ), 81 | // onPressed: _send, 82 | // ), 83 | ) 84 | ], 85 | ) 86 | ], 87 | ), 88 | ), 89 | ); 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /mobpush_plugin/example/lib/click_container.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | 4 | class ClickContainer extends StatefulWidget { 5 | final double left; 6 | final double top; 7 | final double right; 8 | final double bottom; 9 | final String res; 10 | final String content; 11 | final GestureTapCallback onTap; 12 | 13 | ClickContainer( 14 | { 15 | required this.content, 16 | required this.res, 17 | required this.left, 18 | required this.top, 19 | required this.right, 20 | required this.bottom, 21 | required this.onTap 22 | } 23 | ); 24 | 25 | @override 26 | _ClickContainerState createState() { 27 | return _ClickContainerState(); 28 | } 29 | } 30 | 31 | class _ClickContainerState extends State { 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return new GestureDetector( 36 | child: Container( 37 | margin: EdgeInsets.only(left:widget.left, top: widget.top, 38 | right: widget.right, bottom:widget.bottom), 39 | decoration: BoxDecoration( 40 | color: Color(0xFFebf2ff), 41 | borderRadius: new BorderRadius.all(new Radius.circular(8.0)), 42 | ), 43 | child: Column( 44 | mainAxisAlignment: MainAxisAlignment.center, 45 | children: [ 46 | Image.asset(widget.res), 47 | Text(widget.content) 48 | ], 49 | ), 50 | ), 51 | onTap: widget.onTap, 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /mobpush_plugin/example/lib/local_notify_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:math'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:mobpush_plugin/mobpush_plugin.dart'; 6 | import 'package:mobpush_plugin/mobpush_local_notification.dart'; 7 | 8 | class LocalNotifyPage extends StatefulWidget { 9 | @override 10 | _LocalNotifyPageState createState() { 11 | return new _LocalNotifyPageState(); 12 | } 13 | } 14 | 15 | class _LocalNotifyPageState extends State { 16 | TextEditingController _controller = new TextEditingController(); 17 | void _send() async { 18 | if (_controller.text.isNotEmpty) { 19 | if (Platform.isIOS) { // iOS 20 | MobPushLocalNotification localNotification = new MobPushLocalNotification( 21 | title: "正标题",//本地通知标题 22 | content: _controller.text, //本地通知内容 23 | timestamp: 0, //本地通知时间戳, 0立刻通知。其余为时间间隔 24 | badge: 1, // ios角标 25 | sound: "default", // ios声音 26 | subTitle: "副标题", 27 | extrasMap: {"extra":"testExtra"} // ios副标题 28 | );// ios副标题 29 | await MobpushPlugin.addLocalNotification(localNotification); 30 | } else { // Android 31 | MobPushLocalNotification localNotification = new MobPushLocalNotification( 32 | notificationId: new Random().nextInt(99),//notificationId 33 | title: "本地通知",//本地通知标题 34 | content: _controller.text,//本地通知内容 35 | messageId: new Random().nextInt(999).toString(),//消息id 36 | inboxStyleContent: null,//收件箱样式的内容 37 | timestamp: new DateTime.now().millisecondsSinceEpoch,//本地通知时间戳 38 | style: 0,//通知样式 39 | channel: 0,//消息通道 40 | extrasMap: null,//附加数据 41 | voice: true,//声音 42 | shake: true,//真的 43 | styleContent: null,//大段文本和大图模式的样式内容 44 | light: true,//呼吸灯 45 | ); 46 | await MobpushPlugin.addLocalNotification(localNotification); 47 | } 48 | } 49 | } 50 | 51 | @override 52 | Widget build(BuildContext context) { 53 | return Scaffold( 54 | appBar: AppBar( 55 | title: Text('本地通知提醒测试'), 56 | iconTheme: IconThemeData(color: Colors.black), 57 | textTheme: TextTheme(headline6: TextStyle(color: Colors.black)), 58 | backgroundColor: Colors.white, 59 | centerTitle: true, 60 | ), 61 | body: Container( 62 | margin: EdgeInsets.all(15.0), 63 | child: Column( 64 | crossAxisAlignment: CrossAxisAlignment.start, 65 | children: [ 66 | Text( 67 | "点击测试按钮后,在你设定的时间到了时将收到一条本地通知提醒", 68 | textAlign: TextAlign.left, 69 | ), 70 | Container( 71 | margin: EdgeInsets.only(top: 10, bottom: 30), 72 | child: TextField( 73 | maxLines: 5, 74 | maxLength: 35, 75 | decoration: InputDecoration( 76 | hintText: "填写推送内容(不超过35个字)", 77 | contentPadding: EdgeInsets.all(10), 78 | border: OutlineInputBorder( 79 | borderRadius: BorderRadius.all(Radius.circular(5.0)), 80 | borderSide: BorderSide( 81 | color: Color(0xFFe1e1e1), 82 | width: 0.5, 83 | style: BorderStyle.solid 84 | ) 85 | ) 86 | ), 87 | controller: _controller, 88 | ), 89 | ), 90 | Row( 91 | children: [ 92 | new Expanded( 93 | child: new ElevatedButton( 94 | child: Text( 95 | '点击测试', 96 | style: new TextStyle(color: Colors.white), 97 | ), 98 | onPressed: _send, 99 | ), 100 | // child: new RaisedButton( 101 | // padding: EdgeInsets.symmetric(vertical: 12), 102 | // color: Color(0xFFFF7D00), 103 | // child: Text( 104 | // '点击测试', 105 | // style: new TextStyle(color: Colors.white), 106 | // ), 107 | // onPressed: _send, 108 | // ) 109 | ), 110 | ], 111 | ), 112 | ], 113 | ), 114 | ) 115 | ); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /mobpush_plugin/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:ffi'; 3 | import 'dart:io'; 4 | 5 | import 'package:flutter/material.dart'; 6 | import 'dart:async'; 7 | 8 | import 'package:flutter/services.dart'; 9 | import 'package:mobpush_plugin/mobpush_plugin.dart'; 10 | import 'package:mobpush_plugin/mobpush_custom_message.dart'; 11 | import 'package:mobpush_plugin/mobpush_notify_message.dart'; 12 | import 'app_notify_page.dart'; 13 | import 'click_container.dart'; 14 | import 'local_notify_page.dart'; 15 | import 'notify_page.dart'; 16 | import 'other_api_page.dart'; 17 | import 'timing_notify_page.dart'; 18 | 19 | void main() => runApp(MyApp()); 20 | 21 | class MyApp extends StatelessWidget { 22 | @override 23 | Widget build(BuildContext context) { 24 | return new MaterialApp( 25 | home: MainApp(), 26 | ); 27 | } 28 | } 29 | 30 | class MainApp extends StatefulWidget { 31 | @override 32 | _MainAppState createState() { 33 | return _MainAppState(); 34 | } 35 | } 36 | 37 | class _MainAppState extends State { 38 | String _sdkVersion = 'Unknown'; 39 | String _registrationId = 'Unknown'; 40 | 41 | @override 42 | void initState() { 43 | super.initState(); 44 | //上传隐私协议许可 45 | MobpushPlugin.updatePrivacyPermissionStatus(true).then((value) { 46 | print(">>>>>>>>>>>>>>>>>>>updatePrivacyPermissionStatus:" + 47 | value.toString()); 48 | }); 49 | if (Platform.isIOS) { 50 | //设置地区:regionId 默认0(国内),1:海外 51 | MobpushPlugin.setRegionId(0); 52 | MobpushPlugin.registerApp("3276d3e413040", "4280a3a6df667cfce37528dec03fd9c3"); 53 | } 54 | 55 | initPlatformState(); 56 | 57 | if (Platform.isIOS) { 58 | MobpushPlugin.setCustomNotification(); 59 | MobpushPlugin.setAPNsForProduction(true); 60 | } 61 | MobpushPlugin.addPushReceiver(_onEvent, _onError); 62 | 63 | } 64 | 65 | void _onEvent(dynamic event) { 66 | print('>>>>>>>>>>>>>>>>>>>>>>>>>>>onEvent:' + event.toString()); 67 | setState(() { 68 | Map eventMap = json.decode(event as String); 69 | Map result = eventMap['result']; 70 | int action = eventMap['action']; 71 | 72 | switch (action) { 73 | case 0: 74 | MobPushCustomMessage message = 75 | new MobPushCustomMessage.fromJson(result); 76 | showDialog( 77 | context: context, 78 | builder: (context) { 79 | return AlertDialog( 80 | content: Text(message.content), 81 | actions: [ 82 | TextButton( 83 | onPressed: () { 84 | Navigator.pop(context); 85 | }, 86 | child: Text("确定") 87 | ) 88 | ], 89 | ); 90 | }); 91 | break; 92 | case 1: 93 | MobPushNotifyMessage message = 94 | new MobPushNotifyMessage.fromJson(result); 95 | break; 96 | case 2: 97 | MobPushNotifyMessage message = 98 | new MobPushNotifyMessage.fromJson(result); 99 | break; 100 | } 101 | }); 102 | } 103 | 104 | void _onError(dynamic event) { 105 | setState(() { 106 | print('>>>>>>>>>>>>>>>>>>>>>>>>>>>onError:' + event.toString()); 107 | }); 108 | } 109 | 110 | void _onAppNotifyPageTap() { 111 | setState(() { 112 | Navigator.push(context, 113 | new MaterialPageRoute(builder: (context) => new AppNotifyPage())); 114 | }); 115 | } 116 | 117 | void _onNotifyPageTap() { 118 | setState(() { 119 | Navigator.push(context, 120 | new MaterialPageRoute(builder: (context) => new NotifyPage())); 121 | }); 122 | } 123 | 124 | void _onTimingNotifyPageTap() { 125 | setState(() { 126 | Navigator.push(context, 127 | new MaterialPageRoute(builder: (context) => new TimingNotifyPage())); 128 | }); 129 | } 130 | 131 | void _onLocalNotifyPageTap() { 132 | setState(() { 133 | Navigator.push(context, 134 | new MaterialPageRoute(builder: (context) => new LocalNotifyPage())); 135 | }); 136 | } 137 | 138 | void _onOtherAPITap() { 139 | setState(() { 140 | Navigator.push(context, 141 | new MaterialPageRoute(builder: (context) => new OtherApiPage())); 142 | }); 143 | } 144 | 145 | Future initPlatformState() async { 146 | String sdkVersion; 147 | try { 148 | sdkVersion = await MobpushPlugin.getSDKVersion(); 149 | } on PlatformException { 150 | sdkVersion = 'Failed to get platform version.'; 151 | } 152 | try { 153 | Future.delayed(Duration(milliseconds: 500),(){ 154 | MobpushPlugin.getRegistrationId().then((Map ridMap) { 155 | print(ridMap); 156 | setState(() { 157 | _registrationId = ridMap['res'].toString(); 158 | print('------>#### registrationId: ' + _registrationId); 159 | }); 160 | }); 161 | }); 162 | 163 | } on PlatformException { 164 | _registrationId = 'Failed to get registrationId.'; 165 | } 166 | 167 | // If the widget was removed from the tree while the asynchronous platform 168 | // message was in flight, we want to discard the reply rather than calling 169 | // setState to update our non-existent appearance. 170 | if (!mounted) return; 171 | 172 | setState(() { 173 | _sdkVersion = sdkVersion; 174 | }); 175 | } 176 | 177 | // 复制到剪切板 178 | void _onCopyButtonClicked() { 179 | // 写入剪切板 180 | Clipboard.setData(ClipboardData(text: _registrationId)); 181 | // 验证是否写入成功 182 | Clipboard.getData(Clipboard.kTextPlain).then((data) { 183 | if (data != null) { 184 | String? text = data.text; 185 | print('------>#### copyed registrationId: $text'); 186 | if (text == _registrationId) { 187 | showDialog( 188 | context: context, 189 | builder: (context) { 190 | return AlertDialog( 191 | title: Text("恭喜🎉"), 192 | content: Container( 193 | margin: EdgeInsets.only(top: 10, bottom: 30), 194 | child: Text('复制成功!'), 195 | ), 196 | actions: [ 197 | new TextButton(onPressed: () { 198 | Navigator.pop(context); 199 | }, child: Text("OK")) 200 | ], 201 | ); 202 | } 203 | ); 204 | } 205 | } 206 | }); 207 | } 208 | 209 | @override 210 | Widget build(BuildContext context) { 211 | return MaterialApp( 212 | home: Scaffold( 213 | appBar: AppBar( 214 | title: const Text('MobPushPlugin Demo'), 215 | ), 216 | body: Column( 217 | children: [ 218 | Expanded( 219 | child: Row( 220 | children: [ 221 | Expanded( 222 | child: ClickContainer( 223 | content: 'App内推送', 224 | res: 'assets/images/ic_item_app_nitify.png', 225 | left: 15.0, 226 | top: 15.0, 227 | right: 7.5, 228 | bottom: 7.5, 229 | onTap: _onAppNotifyPageTap, 230 | ), 231 | ), 232 | Expanded( 233 | child: ClickContainer( 234 | content: '通知', 235 | res: 'assets/images/ic_item_notify.png', 236 | left: 7.5, 237 | top: 15.0, 238 | right: 15.0, 239 | bottom: 7.5, 240 | onTap: _onNotifyPageTap, 241 | ), 242 | ), 243 | ], 244 | ), 245 | ), 246 | Expanded( 247 | child: Row( 248 | children: [ 249 | Expanded( 250 | child: ClickContainer( 251 | content: '定时推送', 252 | res: 'assets/images/ic_item_timing.png', 253 | left: 15.0, 254 | top: 7.5, 255 | right: 7.5, 256 | bottom: 7.5, 257 | onTap: _onTimingNotifyPageTap, 258 | ), 259 | ), 260 | Expanded( 261 | child: ClickContainer( 262 | content: '本地通知', 263 | res: 'assets/images/ic_item_local.png', 264 | left: 7.5, 265 | top: 7.5, 266 | right: 15.0, 267 | bottom: 7.5, 268 | onTap: _onLocalNotifyPageTap, 269 | ), 270 | ), 271 | ], 272 | ), 273 | ), 274 | Expanded( 275 | child: Row( 276 | children: [ 277 | Expanded( 278 | child: ClickContainer( 279 | content: '其他API接口', 280 | res: 'assets/images/ic_item_media.png', 281 | left: 15.0, 282 | top: 7.5, 283 | right: 15.0, 284 | bottom: 7.5, 285 | onTap: _onOtherAPITap, 286 | ), 287 | ), 288 | ], 289 | ), 290 | ), 291 | Container( 292 | margin: EdgeInsets.only(left: 15.0, right: 15.0, bottom: 15.0), 293 | height: 60, 294 | child: Row( 295 | crossAxisAlignment: CrossAxisAlignment.start, 296 | children: [ 297 | Text( 298 | 'SDK Version: $_sdkVersion\nRegistrationId: $_registrationId', 299 | style: TextStyle(fontSize: 12), 300 | ), 301 | ElevatedButton( 302 | child: Text('复制'), 303 | onPressed: _onCopyButtonClicked, 304 | ) 305 | // RaisedButton( 306 | // child: Text('复制'), 307 | // onPressed: _onCopyButtonClicked, 308 | // ), 309 | ], 310 | ), 311 | ), 312 | ], 313 | ), 314 | ), 315 | ); 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /mobpush_plugin/example/lib/notify_page.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:mobpush_plugin/mobpush_plugin.dart'; 4 | 5 | class NotifyPage extends StatefulWidget { 6 | @override 7 | _NotifyPageState createState() { 8 | return new _NotifyPageState(); 9 | } 10 | } 11 | 12 | class _NotifyPageState extends State { 13 | TextEditingController _controller = new TextEditingController(); 14 | 15 | void _send() async { 16 | if (_controller.text.isNotEmpty) { 17 | //发送消息类型为1的通知消息,推送内容时输入框输入的内容,延迟推送时间为0(立即推送),附加数据为空 18 | MobpushPlugin.send(1, _controller.text, 0, "").then((Map sendMap){ 19 | String res = sendMap['res']; 20 | String error = sendMap['error']; 21 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> send -> res: $res error: $error"); 22 | }); 23 | } 24 | } 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Scaffold( 29 | appBar: AppBar( 30 | title: Text('通知测试'), 31 | iconTheme: IconThemeData(color: Colors.black), 32 | textTheme: TextTheme(headline6: TextStyle(color: Colors.black)), 33 | backgroundColor: Colors.white, 34 | centerTitle: true, 35 | ), 36 | body: Container( 37 | margin: EdgeInsets.all(15.0), 38 | child: Column( 39 | crossAxisAlignment: CrossAxisAlignment.start, 40 | children: [ 41 | Text( 42 | "点击测试按钮后,你将收到一条测试通知", 43 | textAlign: TextAlign.left, 44 | ), 45 | Container( 46 | margin: EdgeInsets.only(top: 10, bottom: 30), 47 | child: TextField( 48 | maxLines: 5, 49 | maxLength: 35, 50 | decoration: InputDecoration( 51 | hintText: "填写推送内容(不超过35个字)", 52 | contentPadding: EdgeInsets.all(10), 53 | border: OutlineInputBorder( 54 | borderRadius: BorderRadius.all(Radius.circular(5.0)), 55 | borderSide: BorderSide( 56 | color: Color(0xFFe1e1e1), 57 | width: 0.5, 58 | style: BorderStyle.solid 59 | ) 60 | ) 61 | ), 62 | controller: _controller, 63 | ), 64 | ), 65 | Row( 66 | children: [ 67 | new Expanded( 68 | child: new ElevatedButton( 69 | child: Text( 70 | '点击测试', 71 | style: new TextStyle(color: Colors.white), 72 | ), 73 | onPressed: _send, 74 | ), 75 | // child: new RaisedButton( 76 | // padding: EdgeInsets.symmetric(vertical: 12), 77 | // color: Color(0xFFFF7D00), 78 | // child: Text( 79 | // '点击测试', 80 | // style: new TextStyle(color: Colors.white), 81 | // ), 82 | // onPressed: _send, 83 | // ) 84 | ), 85 | ], 86 | ), 87 | ], 88 | ), 89 | ) 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /mobpush_plugin/example/lib/timing_notify_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:mobpush_plugin/mobpush_plugin.dart'; 3 | 4 | class TimingNotifyPage extends StatefulWidget { 5 | @override 6 | _TimingNotifyPageState createState() { 7 | return new _TimingNotifyPageState(); 8 | } 9 | } 10 | 11 | class _TimingNotifyPageState extends State { 12 | TextEditingController _controller = new TextEditingController(); 13 | 14 | @override 15 | void initState() { 16 | super.initState(); 17 | // MobpushPlugin.addPushReceiver(_onEvent, _onError); 18 | } 19 | 20 | // void _onEvent(Object event) { 21 | // setState(() { 22 | // print('>>>>>>>>>>>>>>>>>>>>>>>>>>>setStateONEvent:' + event.toString()); 23 | // }); 24 | // } 25 | 26 | // void _onError(Object event) { 27 | // setState(() { 28 | // print('>>>>>>>>>>>>>>>>>>>>>>>>>>>setStateonError:' + event.toString()); 29 | // }); 30 | // } 31 | 32 | void _send() async { 33 | if (_controller.text.isNotEmpty) { 34 | //发送消息类型为3的自延迟推送通知消息,推送内容时输入框输入的内容,延迟推送时间为1分钟(1分钟后推送),附加数据为空 35 | MobpushPlugin.send(3, _controller.text, 1, "").then((Map sendMap){ 36 | String res = sendMap['res']; 37 | String error = sendMap['error']; 38 | print(">>>>>>>>>>>>>>>>>>>>>>>>>>> send -> res: $res error: $error"); 39 | }); 40 | } 41 | } 42 | 43 | @override 44 | Widget build(BuildContext context) { 45 | return Scaffold( 46 | appBar: AppBar( 47 | title: Text('定时通知测试'), 48 | iconTheme: IconThemeData(color: Colors.black), 49 | textTheme: TextTheme(headline6: TextStyle(color: Colors.black)), 50 | backgroundColor: Colors.white, 51 | centerTitle: true, 52 | ), 53 | body: Container( 54 | margin: EdgeInsets.all(15.0), 55 | child: Column( 56 | crossAxisAlignment: CrossAxisAlignment.start, 57 | children: [ 58 | Text( 59 | "点击测试按钮后,在你设定的时间到了时将收到一条测试通知", 60 | textAlign: TextAlign.left, 61 | ), 62 | Container( 63 | margin: EdgeInsets.only(top: 10, bottom: 30), 64 | child: TextField( 65 | maxLines: 5, 66 | maxLength: 35, 67 | decoration: InputDecoration( 68 | hintText: "填写推送内容(不超过35个字)", 69 | contentPadding: EdgeInsets.all(10), 70 | border: OutlineInputBorder( 71 | borderRadius: BorderRadius.all(Radius.circular(5.0)), 72 | borderSide: BorderSide( 73 | color: Color(0xFFe1e1e1), 74 | width: 0.5, 75 | style: BorderStyle.solid 76 | ) 77 | ) 78 | ), 79 | controller: _controller, 80 | ), 81 | ), 82 | Row( 83 | children: [ 84 | new Expanded( 85 | child: new ElevatedButton( 86 | child: Text( 87 | '点击测试', 88 | style: new TextStyle(color: Colors.white), 89 | ), 90 | onPressed: _send, 91 | ), 92 | // child: new RaisedButton( 93 | // padding: EdgeInsets.symmetric(vertical: 12), 94 | // color: Color(0xFF29C18B), 95 | // child: Text( 96 | // '点击测试', 97 | // style: new TextStyle(color: Colors.white), 98 | // ), 99 | // onPressed: _send, 100 | // ) 101 | ), 102 | ], 103 | ), 104 | ], 105 | ), 106 | ) 107 | ); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /mobpush_plugin/example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.8.2" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "1.2.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.15.0" 46 | cupertino_icons: 47 | dependency: "direct main" 48 | description: 49 | name: cupertino_icons 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "0.1.3" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.flutter-io.cn" 58 | source: hosted 59 | version: "1.2.0" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_test: 66 | dependency: "direct dev" 67 | description: flutter 68 | source: sdk 69 | version: "0.0.0" 70 | matcher: 71 | dependency: transitive 72 | description: 73 | name: matcher 74 | url: "https://pub.flutter-io.cn" 75 | source: hosted 76 | version: "0.12.11" 77 | material_color_utilities: 78 | dependency: transitive 79 | description: 80 | name: material_color_utilities 81 | url: "https://pub.flutter-io.cn" 82 | source: hosted 83 | version: "0.1.3" 84 | meta: 85 | dependency: transitive 86 | description: 87 | name: meta 88 | url: "https://pub.flutter-io.cn" 89 | source: hosted 90 | version: "1.7.0" 91 | mobpush_plugin: 92 | dependency: "direct dev" 93 | description: 94 | path: ".." 95 | relative: true 96 | source: path 97 | version: "1.2.9" 98 | path: 99 | dependency: transitive 100 | description: 101 | name: path 102 | url: "https://pub.flutter-io.cn" 103 | source: hosted 104 | version: "1.8.0" 105 | sky_engine: 106 | dependency: transitive 107 | description: flutter 108 | source: sdk 109 | version: "0.0.99" 110 | source_span: 111 | dependency: transitive 112 | description: 113 | name: source_span 114 | url: "https://pub.flutter-io.cn" 115 | source: hosted 116 | version: "1.8.1" 117 | stack_trace: 118 | dependency: transitive 119 | description: 120 | name: stack_trace 121 | url: "https://pub.flutter-io.cn" 122 | source: hosted 123 | version: "1.10.0" 124 | stream_channel: 125 | dependency: transitive 126 | description: 127 | name: stream_channel 128 | url: "https://pub.flutter-io.cn" 129 | source: hosted 130 | version: "2.1.0" 131 | string_scanner: 132 | dependency: transitive 133 | description: 134 | name: string_scanner 135 | url: "https://pub.flutter-io.cn" 136 | source: hosted 137 | version: "1.1.0" 138 | term_glyph: 139 | dependency: transitive 140 | description: 141 | name: term_glyph 142 | url: "https://pub.flutter-io.cn" 143 | source: hosted 144 | version: "1.2.0" 145 | test_api: 146 | dependency: transitive 147 | description: 148 | name: test_api 149 | url: "https://pub.flutter-io.cn" 150 | source: hosted 151 | version: "0.4.8" 152 | typed_data: 153 | dependency: transitive 154 | description: 155 | name: typed_data 156 | url: "https://pub.flutter-io.cn" 157 | source: hosted 158 | version: "1.3.0" 159 | vector_math: 160 | dependency: transitive 161 | description: 162 | name: vector_math 163 | url: "https://pub.flutter-io.cn" 164 | source: hosted 165 | version: "2.1.1" 166 | sdks: 167 | dart: ">=2.14.0 <3.0.0" 168 | flutter: ">=1.12.0" 169 | -------------------------------------------------------------------------------- /mobpush_plugin/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: mobpush_plugin_example 2 | description: Demonstrates how to use the mobpush_plugin plugin. 3 | publish_to: 'none' 4 | 5 | environment: 6 | sdk: ">=2.12.0 <3.0.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | 12 | # The following adds the Cupertino Icons font to your application. 13 | # Use with the CupertinoIcons class for iOS style icons. 14 | cupertino_icons: ^0.1.2 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | mobpush_plugin: 21 | path: ../ 22 | 23 | # For information on the generic Dart part of this file, see the 24 | # following page: https://dart.dev/tools/pub/pubspec 25 | 26 | flutter: 27 | 28 | # The following line ensures that the Material Icons font is 29 | # included with your application, so that you can use the icons in 30 | # the material Icons class. 31 | uses-material-design: true 32 | 33 | # To add assets to your application, add an assets section, like this: 34 | assets: 35 | - assets/images/ic_item_app_nitify.png 36 | - assets/images/ic_item_local.png 37 | - assets/images/ic_item_media.png 38 | - assets/images/ic_item_notify.png 39 | - assets/images/ic_item_open_act.png 40 | - assets/images/ic_item_timing.png 41 | 42 | # An image asset can refer to one or more resolution-specific "variants", see 43 | # https://flutter.dev/assets-and-images/#resolution-aware. 44 | 45 | # For details regarding adding assets from package dependencies, see 46 | # https://flutter.dev/assets-and-images/#from-packages 47 | 48 | # To add custom fonts to your application, add a fonts section here, 49 | # in this "flutter" section. Each entry in this list should have a 50 | # "family" key with the font family name, and a "fonts" key with a 51 | # list giving the asset and other descriptors for the font. For 52 | # example: 53 | # fonts: 54 | # - family: Schyler 55 | # fonts: 56 | # - asset: fonts/Schyler-Regular.ttf 57 | # - asset: fonts/Schyler-Italic.ttf 58 | # style: italic 59 | # - family: Trajan Pro 60 | # fonts: 61 | # - asset: fonts/TrajanPro.ttf 62 | # - asset: fonts/TrajanPro_Bold.ttf 63 | # weight: 700 64 | # 65 | # For details regarding fonts from package dependencies, 66 | # see https://flutter.dev/custom-fonts/#from-packages 67 | -------------------------------------------------------------------------------- /mobpush_plugin/example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:mobpush_plugin_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => widget is Text && 22 | widget.data!.startsWith('Running on:'), 23 | ), 24 | findsOneWidget, 25 | ); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /mobpush_plugin/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | -------------------------------------------------------------------------------- /mobpush_plugin/ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MobClub/MobPush-For-Flutter/97a371e4b6339a28204761051302876b2e624b1c/mobpush_plugin/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /mobpush_plugin/ios/Classes/MobpushPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | // 标准: 对外桥接类命名,项目xx + Plugin. 例: MobpushPlugin 4 | @interface MobpushPlugin : NSObject 5 | @end 6 | -------------------------------------------------------------------------------- /mobpush_plugin/ios/Classes/MobpushPlugin.m: -------------------------------------------------------------------------------- 1 | #import "MobpushPlugin.h" 2 | #import 3 | #import 4 | #import 5 | #import 6 | #import 7 | 8 | @interface MobpushPlugin() 9 | // 是否是生产环境 10 | @property (nonatomic, assign) BOOL isPro; 11 | // 事件回调 12 | @property (nonatomic, copy) void (^callBack) (id _Nullable event); 13 | 14 | @property (nonatomic, strong) NSMutableArray *tmps; 15 | 16 | @end 17 | 18 | @implementation MobpushPlugin 19 | 20 | static NSString *const receiverStr = @"com.mob.mobpush.reciever"; 21 | 22 | + (void)registerWithRegistrar:(NSObject*)registrar { 23 | // 标准: MethodChannel 统一命名:com.mob.项目xx.功能 24 | FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"com.mob.mobpush.methodChannel" binaryMessenger:[registrar messenger]]; 25 | MobpushPlugin* instance = [[MobpushPlugin alloc] init]; 26 | [registrar addMethodCallDelegate:instance channel:channel]; 27 | 28 | FlutterEventChannel* e_channel = [FlutterEventChannel eventChannelWithName:receiverStr binaryMessenger:[registrar messenger]]; 29 | [e_channel setStreamHandler:instance]; 30 | 31 | [instance addObserver]; 32 | } 33 | 34 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 35 | if ([@"getPlatformVersion" isEqualToString:call.method]) { 36 | result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); 37 | } 38 | else if ([@"getSDKVersion" isEqualToString:call.method]) 39 | { 40 | //TODO: SDK 添加获取版本号接口 41 | result([MobPush sdkVersion]); 42 | } 43 | else if ([@"getRegistrationId" isEqualToString:call.method]) { 44 | [MobPush getRegistrationID:^(NSString *registrationID, NSError *error) { 45 | if (error) { 46 | result(@{@"res": @"", @"error": error.localizedDescription}); 47 | } else { 48 | result(@{@"res": registrationID, @"error": @""}); 49 | } 50 | }]; 51 | } 52 | else if ([@"stopPush" isEqualToString:call.method]) 53 | { 54 | [MobPush stopPush]; 55 | } 56 | else if ([@"restartPush" isEqualToString:call.method]) 57 | { 58 | [MobPush restartPush]; 59 | } 60 | else if ([@"isPushStopped" isEqualToString:call.method]) 61 | { 62 | result(@([MobPush isPushStopped])); 63 | } 64 | else if ([@"setAlias" isEqualToString:call.method]) 65 | { 66 | NSDictionary *arguments = (NSDictionary *)call.arguments; 67 | if (arguments && arguments[@"alias"] && [arguments[@"alias"] isKindOfClass:[NSString class]]) 68 | { 69 | [MobPush setAlias:arguments[@"alias"] result:^(NSError *error) { 70 | NSString *errorStr = error ? error.localizedDescription : @""; 71 | result(@{@"res": error ? @"failed": @"success", @"error": errorStr}); 72 | }]; 73 | } 74 | else 75 | { 76 | result(@{@"res": @"failed", @"error": @"Arguments Invaild."}); 77 | } 78 | } 79 | else if ([@"getAlias" isEqualToString:call.method]) 80 | { 81 | [MobPush getAliasWithResult:^(NSString *alias, NSError *error) { 82 | if (error) { 83 | result(@{@"res": @"", @"error": error.localizedDescription}); 84 | } else { 85 | NSString *rstAlias = alias; 86 | if (!alias) { 87 | rstAlias = @""; 88 | } 89 | result(@{@"res": rstAlias, @"error": @""}); 90 | } 91 | }]; 92 | } 93 | else if ([@"deleteAlias" isEqualToString:call.method]) 94 | { 95 | [MobPush deleteAlias:^(NSError *error) { 96 | NSString *errorStr = error ? error.localizedDescription : @""; 97 | result(@{@"res": error ? @"failed": @"success", @"error": errorStr}); 98 | }]; 99 | } 100 | else if ([@"addTags" isEqualToString:call.method]) 101 | { 102 | NSDictionary *arguments = (NSDictionary *)call.arguments; 103 | if (arguments && arguments[@"tags"]) { 104 | [MobPush addTags:arguments[@"tags"] result:^(NSError *error) { 105 | NSString *errorStr = error ? error.localizedDescription : @""; 106 | result(@{@"res": error ? @"failed": @"success", @"error": errorStr}); 107 | }]; 108 | } 109 | else 110 | { 111 | result(@{@"res": @"failed", @"error": @"Arguments Invaild."}); 112 | } 113 | 114 | } 115 | else if ([@"getTags" isEqualToString:call.method]) 116 | { 117 | [MobPush getTagsWithResult:^(NSArray *tags, NSError *error) { 118 | if (error) { 119 | result(@{@"res": @"", @"error": error.localizedDescription}); 120 | } else { 121 | result(@{@"res": tags, @"error": @""}); 122 | } 123 | }]; 124 | } 125 | else if ([@"deleteTags" isEqualToString:call.method]) 126 | { 127 | NSDictionary *arguments = (NSDictionary *)call.arguments; 128 | if (arguments && arguments[@"tags"]) { 129 | [MobPush deleteTags:arguments[@"tags"] result:^(NSError *error) { 130 | NSString *errorStr = error ? error.localizedDescription : @""; 131 | result(@{@"res": error ? @"failed": @"success", @"error": errorStr}); 132 | }]; 133 | } 134 | else 135 | { 136 | result(@{@"res": @"failed", @"error": @"Arguments Invaild."}); 137 | } 138 | } 139 | else if ([@"cleanTags" isEqualToString:call.method]) 140 | { 141 | [MobPush cleanAllTags:^(NSError *error) { 142 | NSString *errorStr = error ? error.localizedDescription : @""; 143 | result(@{@"res": error ? @"failed": @"success", @"error": errorStr}); 144 | }]; 145 | } 146 | else if ([@"addLocalNotification" isEqualToString:call.method]) 147 | { 148 | NSDictionary *arguments = (NSDictionary *)call.arguments; 149 | if (arguments && arguments[@"localNotification"]) 150 | { 151 | NSString *localStr = arguments[@"localNotification"]; 152 | NSDictionary *eventParams = [MOBFJson objectFromJSONString:localStr]; 153 | 154 | NSString *identifier = nil; 155 | 156 | MPushNotification *noti = [[MPushNotification alloc] init]; 157 | if (eventParams[@"title"] && ![eventParams[@"title"] isKindOfClass:[NSNull class]]) 158 | { 159 | noti.title = eventParams[@"title"]; 160 | } 161 | if (eventParams[@"content"] && ![eventParams[@"content"] isKindOfClass:[NSNull class]]) 162 | { 163 | noti.body = eventParams[@"content"]; 164 | } 165 | if (eventParams[@"sound"] && ![eventParams[@"sound"] isKindOfClass:[NSNull class]]) 166 | { 167 | noti.sound = eventParams[@"sound"]; 168 | 169 | } 170 | if (eventParams[@"badge"] && ![eventParams[@"badge"] isKindOfClass:[NSNull class]]) 171 | { 172 | noti.badge = [eventParams[@"badge"] integerValue]; 173 | } 174 | if (eventParams[@"subTitle"] && ![eventParams[@"subTitle"] isKindOfClass:[NSNull class]]) 175 | { 176 | noti.subTitle = eventParams[@"subTitle"]; 177 | } 178 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; 179 | if (eventParams[@"extrasMap"] && ![eventParams[@"extrasMap"] isKindOfClass:[NSNull class]]) 180 | { 181 | [userInfo addEntriesFromDictionary:eventParams[@"extrasMap"]]; 182 | 183 | } 184 | if (eventParams[@"messageId"] && ![eventParams[@"messageId"] isKindOfClass:[NSNull class]]) 185 | { 186 | NSString *messageId = eventParams[@"messageId"]; 187 | userInfo[@"messageId"] = messageId; 188 | identifier = messageId; 189 | } 190 | 191 | noti.userInfo = [userInfo copy]; 192 | 193 | if (eventParams[@"identifier"] && ![eventParams[@"identifier"] isKindOfClass:[NSNull class]]) 194 | { 195 | identifier = eventParams[@"messageId"]; 196 | } 197 | 198 | MPushNotificationTrigger *trigger = [MPushNotificationTrigger new]; 199 | 200 | if (eventParams[@"timestamp"] && ![eventParams[@"timestamp"] isKindOfClass:[NSNull class]]) 201 | { 202 | double timeStamp = [eventParams[@"timestamp"] doubleValue]; 203 | if (timeStamp > 0) 204 | { 205 | NSDate *currentDate = [NSDate dateWithTimeIntervalSinceNow:0]; 206 | NSTimeInterval nowtime = [currentDate timeIntervalSince1970] * 1000; 207 | NSTimeInterval tasktimeInterval = nowtime + (NSTimeInterval)timeStamp; 208 | 209 | if (@available(iOS 10.0, *)) 210 | { 211 | trigger.timeInterval = timeStamp; 212 | } 213 | else 214 | { 215 | trigger.fireDate = [NSDate dateWithTimeIntervalSince1970:tasktimeInterval]; 216 | } 217 | } 218 | } 219 | 220 | MPushNotificationRequest *request = [MPushNotificationRequest new]; 221 | request.requestIdentifier = identifier; 222 | request.content = noti; 223 | request.trigger = trigger; 224 | 225 | [MobPush addLocalNotification:request result:^(id res, NSError *error) { 226 | NSString *errorStr = error ? error.localizedDescription : @""; 227 | result(@{@"res": error ? @"failed": @"success", @"error": errorStr}); 228 | }]; 229 | } 230 | } 231 | else if ([@"bindPhoneNum" isEqualToString:call.method]) 232 | { 233 | NSDictionary *arguments = (NSDictionary *)call.arguments; 234 | if (arguments && arguments[@"phoneNum"]) 235 | { 236 | [MobPush bindPhoneNum:arguments[@"phoneNum"] result:^(NSError *error) { 237 | NSString *errorStr = error ? error.localizedDescription : @""; 238 | result(@{@"res": error ? @"failed": @"success", @"error": errorStr}); 239 | }]; 240 | } 241 | else 242 | { 243 | result(@{@"res": @"failed", @"error": @"Arguments Invaild."}); 244 | } 245 | } 246 | else if ([@"send" isEqualToString:call.method]) 247 | { 248 | NSDictionary *arguments = (NSDictionary *)call.arguments; 249 | if (arguments) { 250 | NSInteger type = [arguments[@"type"] integerValue]; 251 | NSString *content = arguments[@"content"]; 252 | NSNumber *space = arguments[@"space"]; 253 | NSDictionary *extras = (NSDictionary *)arguments[@"extrasMap"]; 254 | NSString *sound = arguments[@"sound"]; 255 | NSString *coverId = arguments[@"coverId"]; 256 | [MobPush sendMessageWithMessageType:type 257 | content:content 258 | space:space 259 | sound:sound 260 | isProductionEnvironment:_isPro 261 | extras:extras 262 | linkScheme:nil 263 | linkData:nil 264 | coverId:coverId 265 | result:^(NSString *workId, NSError *error) { 266 | NSString *errorStr = error ? error.localizedDescription : @""; 267 | NSString *workIdStr = workId?:@""; 268 | result(@{@"res": error ? @"failed": @"success", @"error": errorStr, @"workId" : workIdStr}); 269 | }]; 270 | } 271 | else 272 | { 273 | result(@{@"res": @"failed", @"error": @"Arguments Invaild."}); 274 | } 275 | } 276 | else if ([@"setAPNsForProduction" isEqualToString:call.method]) 277 | { 278 | NSDictionary *arguments = (NSDictionary *)call.arguments; 279 | _isPro = [arguments[@"isPro"] boolValue]; 280 | [MobPush setAPNsForProduction:_isPro]; 281 | } 282 | else if ([@"setBadge" isEqualToString:call.method]) 283 | { 284 | NSDictionary *arguments = (NSDictionary *)call.arguments; 285 | NSInteger badge = [arguments[@"badge"] integerValue]; 286 | UIApplication.sharedApplication.applicationIconBadgeNumber = badge; 287 | [MobPush setBadge:badge]; 288 | } 289 | else if ([@"clearBadge" isEqualToString:call.method]) 290 | { 291 | [MobPush clearBadge]; 292 | } 293 | else if ([@"setAPNsShowForegroundType" isEqualToString:call.method]) 294 | { 295 | NSDictionary *arguments = (NSDictionary *)call.arguments; 296 | NSInteger type = [arguments[@"type"] integerValue]; 297 | [MobPush setAPNsShowForegroundType:type]; 298 | } 299 | else if ([@"setCustomNotification" isEqualToString:call.method]) 300 | { 301 | MPushNotificationConfiguration *config = [[MPushNotificationConfiguration alloc] init]; 302 | config.types = MPushAuthorizationOptionsSound | MPushAuthorizationOptionsBadge | MPushAuthorizationOptionsAlert; 303 | [[MOBFDataService sharedInstance] setCacheData:config 304 | forKey:@"MPushNotificationConfiguration" 305 | domain:@"MOBPUSH_FLUTTER_PLUGIN"]; 306 | [MobPush setupNotification:config]; 307 | } 308 | else if ([@"updatePrivacyPermissionStatus" isEqualToString:call.method]) 309 | { 310 | NSDictionary *arguments = (NSDictionary *)call.arguments; 311 | NSInteger status = [arguments[@"status"] integerValue]; 312 | [MobSDK uploadPrivacyPermissionStatus:status onResult:^(BOOL success) { 313 | result(@(success)); 314 | }]; 315 | } 316 | else if ([@"setRegionId" isEqualToString:call.method]) { 317 | NSDictionary *arguments = (NSDictionary *)call.arguments; 318 | int regionId = [arguments[@"regionId"] intValue]; 319 | [MobPush setRegionID:regionId]; 320 | } 321 | else if ([@"registerApp" isEqualToString:call.method]) { 322 | NSDictionary *arguments = (NSDictionary *)call.arguments; 323 | NSString *appKey = arguments[@"appKey"]; 324 | NSString *appSecret = arguments[@"appSecret"]; 325 | [MobSDK registerAppKey:appKey appSecret:appSecret]; 326 | } 327 | else 328 | { 329 | result(FlutterMethodNotImplemented); 330 | } 331 | } 332 | 333 | #pragma mark - FlutterStreamHandler Protocol 334 | 335 | - (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events 336 | { 337 | self.callBack = events; 338 | return nil; 339 | } 340 | 341 | - (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments 342 | { 343 | return nil; 344 | } 345 | 346 | #pragma mark - 监听消息通知 347 | 348 | - (void)addObserver 349 | { 350 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMessage:) name:MobPushDidReceiveMessageNotification object:nil]; 351 | MPushNotificationConfiguration *config = [[MOBFDataService sharedInstance] cacheDataForKey:@"MPushNotificationConfiguration" domain:@"MOBPUSH_FLUTTER_PLUGIN"]; 352 | if (config && [config isKindOfClass:MPushNotificationConfiguration.class]) 353 | { 354 | [MobPush setupNotification:config]; 355 | } 356 | } 357 | 358 | - (void)didReceiveMessage:(NSNotification *)notification 359 | { 360 | // NSLog(@"flutter: ================ didReceiveMessage ========================="); 361 | if ([notification.object isKindOfClass:[MPushMessage class]]) 362 | { 363 | MPushMessage *message = (MPushMessage *)notification.object; 364 | NSMutableDictionary *resultDict = [NSMutableDictionary dictionary]; 365 | NSMutableDictionary *reslut = [NSMutableDictionary dictionary]; 366 | switch (message.messageType) 367 | { 368 | case MPushMessageTypeCustom: 369 | {// 自定义消息 370 | [resultDict setObject:@(0) forKey:@"action"]; 371 | if (message.notification.userInfo) 372 | { 373 | [reslut setObject:message.notification.userInfo forKey:@"extrasMap"]; 374 | } 375 | if (message.notification.body) 376 | { 377 | [reslut setObject:message.notification.body forKey:@"content"]; 378 | } 379 | if (message.messageID) 380 | { 381 | [reslut setObject:message.messageID forKey:@"messageId"]; 382 | } 383 | [reslut addEntriesFromDictionary:message.notification.convertDictionary]; 384 | } 385 | break; 386 | case MPushMessageTypeAPNs: 387 | {// APNs 回调 388 | 389 | if (message.notification.userInfo) 390 | { 391 | [reslut setObject:message.notification.userInfo forKey:@"extrasMap"]; 392 | } 393 | if (message.notification.body) 394 | { 395 | [reslut setObject:message.notification.body forKey:@"content"]; 396 | } 397 | if (message.messageID) 398 | { 399 | [reslut setObject:message.messageID forKey:@"messageId"]; 400 | } 401 | [reslut addEntriesFromDictionary:message.notification.convertDictionary]; 402 | 403 | [resultDict setObject:@(1) forKey:@"action"]; 404 | } 405 | break; 406 | case MPushMessageTypeLocal: 407 | { // 本地通知回调 408 | if (message.notification.userInfo) 409 | { 410 | [reslut setObject:message.notification.userInfo forKey:@"extrasMap"]; 411 | } 412 | if (message.notification.body) 413 | { 414 | [reslut setObject:message.notification.body forKey:@"content"]; 415 | } 416 | if (message.messageID) 417 | { 418 | [reslut setObject:message.messageID forKey:@"messageId"]; 419 | } 420 | [reslut addEntriesFromDictionary:message.notification.convertDictionary]; 421 | 422 | [resultDict setObject:@(1) forKey:@"action"]; 423 | } 424 | break; 425 | 426 | case MPushMessageTypeClicked: 427 | { 428 | 429 | if (message.notification.userInfo) 430 | { 431 | [reslut setObject:message.notification.userInfo forKey:@"extrasMap"]; 432 | } 433 | if (message.notification.body) 434 | { 435 | [reslut setObject:message.notification.body forKey:@"content"]; 436 | } 437 | if (message.messageID) 438 | { 439 | [reslut setObject:message.messageID forKey:@"messageId"]; 440 | } 441 | [reslut addEntriesFromDictionary:message.notification.convertDictionary]; 442 | 443 | [resultDict setObject:@(2) forKey:@"action"]; 444 | 445 | } 446 | break; 447 | 448 | default: 449 | break; 450 | } 451 | if (reslut.count > 0) 452 | { 453 | [resultDict setObject:reslut forKey:@"result"]; 454 | } 455 | // 回调结果 456 | NSString *resultDictStr = [MOBFJson jsonStringFromObject:resultDict]; 457 | 458 | if (self.callBack) 459 | { 460 | self.callBack(resultDictStr); 461 | } 462 | else 463 | { 464 | if(_tmps) 465 | { 466 | [_tmps addObject:resultDictStr]; 467 | } 468 | else 469 | { 470 | _tmps = @[resultDictStr].mutableCopy; 471 | } 472 | } 473 | 474 | } 475 | } 476 | 477 | - (void)setCallBack:(void (^)(id _Nullable))callBack 478 | { 479 | _callBack = callBack; 480 | 481 | if (_callBack && _tmps.count) 482 | { 483 | for (NSString *obj in _tmps) { 484 | _callBack(obj); 485 | } 486 | } 487 | } 488 | 489 | 490 | - (void)dealloc 491 | { 492 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 493 | } 494 | 495 | @end 496 | -------------------------------------------------------------------------------- /mobpush_plugin/ios/mobpush_plugin.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | # 标准: 名字需要和文件名字保持一致,不带后缀 6 | s.name = 'mobpush_plugin' 7 | # 标准: ios目录有改动,需要更新版本号 8 | s.version = '1.3.0' 9 | # 标准: 需要添加内容 10 | s.summary = 'mobpush 是一款推送SDK.' 11 | # 标准: 需要添加内容 12 | s.description = <<-DESC 13 | A new flutter plugin project. 14 | DESC 15 | # 标准: 添加官网对应插件项目的首页 16 | s.homepage = 'http://www.mob.com/mobService/mobpush' 17 | # 标准: 固定为 { :file => '../LICENSE' } 18 | s.license = { :file => '../LICENSE' } 19 | # 标准: 固定为 { 'Mob' => 'mobproducts@mob.com' } 20 | s.author = { 'Mob' => 'mobproducts@mob.com' } 21 | # 标准: 固定为 { :path => '.' } 22 | s.source = { :path => '.' } 23 | # 标准: 固定为 'Classes/**/*' 24 | s.source_files = 'Classes/**/*' 25 | # 标准: 固定为'Classes/**/*.h' 26 | s.public_header_files = 'Classes/**/*.h' 27 | # 标准: 固定为'Flutter' 28 | s.dependency 'Flutter' 29 | # 标准: 根据具体需要引入库,如 'mob_pushsdk' 30 | s.dependency 'mob_pushsdk' 31 | # 标准: 固定为true 32 | s.static_framework = true 33 | 34 | # 标准: 固定为 '8.0' 35 | s.ios.deployment_target = '9.0' 36 | end 37 | 38 | -------------------------------------------------------------------------------- /mobpush_plugin/lib/mobpush_custom_message.dart: -------------------------------------------------------------------------------- 1 | 2 | class MobPushCustomMessage { 3 | String content; 4 | String? messageId; 5 | int? timestamp; 6 | Map? extrasMap; 7 | 8 | MobPushCustomMessage(this.content, this.messageId, this.timestamp, this.extrasMap); 9 | 10 | factory MobPushCustomMessage.fromJson(Map json) { 11 | return MobPushCustomMessage(json['content'], json['messageId'], json['timeStamp'], json['extrasMap']); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /mobpush_plugin/lib/mobpush_local_notification.dart: -------------------------------------------------------------------------------- 1 | import 'mobpush_notify_message.dart'; 2 | 3 | class MobPushLocalNotification extends MobPushNotifyMessage { 4 | int? notificationId; 5 | 6 | MobPushLocalNotification( 7 | {this.notificationId, 8 | title, 9 | content, 10 | timestamp, 11 | subTitle, 12 | sound, 13 | badge, 14 | styleContent, 15 | messageId, 16 | inboxStyleContent, 17 | style, 18 | channel, 19 | extrasMap, 20 | voice, 21 | shake, 22 | light}) 23 | : super( 24 | title: title, 25 | content: content, 26 | timestamp: timestamp, 27 | subTitle: subTitle, 28 | sound: sound, 29 | badge: badge, 30 | styleContent: styleContent, 31 | messageId: messageId, 32 | inboxStyleContent: inboxStyleContent, 33 | style: style, 34 | channel: channel, 35 | extrasMap: extrasMap, 36 | voice: voice, 37 | shake: shake, 38 | light: light); 39 | 40 | Map toJson() => { 41 | 'notificationId': notificationId, 42 | 'title': title, 43 | 'content': content, 44 | 'messageId': messageId, 45 | 'inboxStyleContent': inboxStyleContent, 46 | 'timestamp': timestamp, 47 | 'style': style, 48 | 'channel': channel, 49 | 'extrasMap': extrasMap, 50 | 'voice': voice, 51 | 'shake': shake, 52 | 'styleContent': styleContent, 53 | 'light': light, 54 | 'badge': badge, 55 | 'sound': sound, 56 | 'subTitle': subTitle 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /mobpush_plugin/lib/mobpush_notify_message.dart: -------------------------------------------------------------------------------- 1 | 2 | class MobPushNotifyMessage { 3 | // iOS Properties 4 | String? subTitle; 5 | String? sound; 6 | int? badge; 7 | // Android Properties 8 | String? styleContent; 9 | String? messageId; 10 | List? inboxStyleContent; 11 | int? style; 12 | int? channel; 13 | Map? extrasMap; 14 | bool? voice; 15 | bool? shake; 16 | bool? light; 17 | String? title; 18 | String content; 19 | int? timestamp; 20 | 21 | MobPushNotifyMessage({this.title, required this.content, this.timestamp, this.subTitle, this.sound, this.badge, this.styleContent, required this.messageId, this.inboxStyleContent, this.style, this.channel, this.extrasMap, this.voice, this.shake, this.light}); 22 | 23 | factory MobPushNotifyMessage.fromJson(Map json) { 24 | return MobPushNotifyMessage( 25 | title: json['title'], 26 | content: json['content'], 27 | messageId: json['messageId'], 28 | timestamp: json['timestamp'], 29 | style: json['style'], 30 | channel: json['channel'], 31 | voice: json['voice'], 32 | shake: json['shake'], 33 | extrasMap: json['extrasMap'], 34 | inboxStyleContent: json['inboxStyleContent'], 35 | styleContent: json['styleContent'], 36 | light: json['light'], 37 | badge: json['badge'], 38 | sound: json['sound'], 39 | subTitle: json['subTitle']); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /mobpush_plugin/lib/mobpush_plugin.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'package:flutter/services.dart'; 4 | import 'mobpush_local_notification.dart'; 5 | 6 | typedef void EventHandler(dynamic event); 7 | 8 | class MobpushPlugin { 9 | // 标准: MethodChannel 统一命名:com.mob.项目xx.功能 10 | static const MethodChannel _channel = const MethodChannel('com.mob.mobpush.methodChannel'); 11 | static EventChannel _channelReciever = const EventChannel('com.mob.mobpush.reciever'); 12 | 13 | static Future get getPlatformVersion async { 14 | return await _channel.invokeMethod('getPlatformVersion'); 15 | } 16 | 17 | /* 18 | *上传隐私协议. 19 | */ 20 | static Future updatePrivacyPermissionStatus(bool agree) async { 21 | return await _channel.invokeMethod('updatePrivacyPermissionStatus', {'status': agree}); 22 | } 23 | 24 | /* 25 | *获取SDK版本号. 26 | */ 27 | static Future getSDKVersion() async { 28 | return await _channel.invokeMethod('getSDKVersion'); 29 | } 30 | 31 | /* 32 | *获取regId. 33 | */ 34 | static Future> getRegistrationId() async { 35 | final Map ridMap = await _channel.invokeMethod('getRegistrationId'); 36 | return Map.from(ridMap); 37 | } 38 | 39 | /* 40 | *添加推送回调监听(接收自定义透传消息回调、接收通知消息回调、接收点击通知消息回调、接收别名或标签操作回调). 41 | */ 42 | static Future addPushReceiver(EventHandler onEvent, EventHandler onError) async { 43 | _channelReciever.receiveBroadcastStream().listen(onEvent, onError: onError); 44 | } 45 | 46 | /* 47 | *移除推送回调监听. 48 | */ 49 | static Future removePushReceiver() async { 50 | return await _channel.invokeMethod('removePushReceiver'); 51 | } 52 | 53 | /* 54 | *停止推送. 55 | */ 56 | static Future stopPush() async { 57 | _channel.invokeMethod('stopPush'); 58 | } 59 | 60 | /* 61 | *重新打开推送服务. 62 | */ 63 | static Future restartPush() async { 64 | _channel.invokeMethod('restartPush'); 65 | } 66 | 67 | /* 68 | *是否已停止接收推送. 69 | */ 70 | static Future isPushStopped() async { 71 | return await _channel.invokeMethod('isPushStopped'); 72 | } 73 | 74 | /* 75 | *设置别名. 76 | */ 77 | static Future> setAlias(String alias) async { 78 | final Map resMap = await _channel.invokeMethod('setAlias', {'alias': alias}); 79 | return Map.from(resMap); 80 | } 81 | 82 | /* 83 | *获取别名. 84 | */ 85 | static Future> getAlias() async { 86 | final Map ridMap = await _channel.invokeMethod('getAlias'); 87 | return Map.from(ridMap); 88 | } 89 | 90 | /* 91 | *删除别名. 92 | */ 93 | static Future> deleteAlias() async { 94 | final Map ridMap = await _channel.invokeMethod('deleteAlias'); 95 | return Map.from(ridMap); 96 | } 97 | 98 | /* 99 | *添加标签. 100 | */ 101 | static Future> addTags(List tags) async { 102 | final Map resMap = await _channel.invokeMethod('addTags', {'tags': tags}); 103 | return Map.from(resMap); 104 | } 105 | 106 | /* 107 | *获取标签. 108 | */ 109 | static Future> getTags() async { 110 | final Map ridMap = await _channel.invokeMethod('getTags'); 111 | return Map.from(ridMap); 112 | } 113 | 114 | /* 115 | *删除标签. 116 | */ 117 | static Future> deleteTags(List tags) async { 118 | final Map resMap = await _channel.invokeMethod('deleteTags', {'tags': tags}); 119 | return Map.from(resMap); 120 | } 121 | 122 | /* 123 | *清空标签. 124 | */ 125 | static Future> cleanTags() async { 126 | final Map ridMap = await _channel.invokeMethod('cleanTags'); 127 | return Map.from(ridMap); 128 | } 129 | 130 | /* 131 | *发送本地通知. 132 | */ 133 | static Future addLocalNotification(MobPushLocalNotification localNotification) async { 134 | return await _channel.invokeMethod('addLocalNotification', {'localNotification': json.encode(localNotification.toJson())}); 135 | } 136 | 137 | /* 138 | *绑定手机号. 139 | */ 140 | static Future> bindPhoneNum(String phoneNum) async { 141 | final Map resMap = await _channel.invokeMethod('bindPhoneNum', {'phoneNum': phoneNum}); 142 | return Map.from(resMap); 143 | } 144 | 145 | /* 146 | *测试模拟推送,用于测试. 147 | */ 148 | static Future> send(int type, String content, int space, String extras) async { 149 | final Map resMap = await _channel.invokeMethod('send', { 150 | 'type': type, 151 | 'content': content, 152 | 'space': space, 153 | 'extrasMap': extras 154 | }); 155 | return Map.from(resMap); 156 | } 157 | 158 | // IOS API 159 | /* 160 | *设置远程推送,向用户授权(仅 iOS). 161 | */ 162 | static Future setCustomNotification() async { 163 | _channel.invokeMethod('setCustomNotification'); 164 | } 165 | 166 | /* 167 | *设置远程推送环境 (仅 iOS). 168 | */ 169 | static Future setAPNsForProduction(bool isPro) async { 170 | _channel.invokeMethod('setAPNsForProduction', {'isPro': isPro}); 171 | } 172 | 173 | /* 174 | *设置角标 (仅 iOS). 175 | */ 176 | static Future setBadge(int badge) async { 177 | _channel.invokeMethod('setBadge', {'badge': badge}); 178 | } 179 | 180 | /* 181 | *清空角标,不清除通知栏消息记录 (仅 iOS). 182 | */ 183 | static Future clearBadge() async { 184 | _channel.invokeMethod('clearBadge'); 185 | } 186 | 187 | /* 188 | *设置应用在前台有 Badge、Sound、Alert 三种类型 189 | *默认3个选项都有 190 | *iOS 10以上设置生效.(仅 iOS). 191 | */ 192 | static Future setAPNsShowForegroundType(int type) async { 193 | _channel.invokeMethod('setAPNsShowForegroundType', {'type': type}); 194 | } 195 | 196 | /* 197 | *设置地区:regionId 默认0(国内),1:海外 (仅 iOS). 198 | */ 199 | static Future setRegionId(int regionId) async { 200 | _channel.invokeMethod('setRegionId', {'regionId': regionId}); 201 | } 202 | 203 | /* 204 | *注册appkey和appsecret 205 | * (仅 iOS). 206 | */ 207 | static Future registerApp(String appKey, String appSecret) async { 208 | _channel.invokeMethod('registerApp', {'appKey': appKey, 'appSecret': appSecret}); 209 | } 210 | 211 | // Android API 212 | /* 213 | *设置点击通知是否跳转默认页(仅andorid). 214 | */ 215 | static Future setClickNotificationToLaunchMainActivity(bool enable) async { 216 | return await _channel.invokeMethod('setClickNotificationToLaunchMainActivity', {'enable': enable}); 217 | } 218 | 219 | /* 220 | *移除本地通知(仅andorid). 221 | */ 222 | static Future removeLocalNotification(int notificationId) async { 223 | return await _channel.invokeMethod('removeLocalNotification', {"notificationId": notificationId}); 224 | } 225 | 226 | /* 227 | *清空本地通知(仅andorid). 228 | */ 229 | static Future clearLocalNotifications() async { 230 | return await _channel.invokeMethod('clearLocalNotifications'); 231 | } 232 | 233 | /* 234 | *设置通知栏icon,不设置默认取应用icon(仅andorid). 235 | */ 236 | static Future setNotifyIcon(String resId) async { 237 | return await _channel.invokeMethod('setNotifyIcon', {'iconRes': resId}); 238 | } 239 | 240 | /* 241 | *设置应用在前台时是否隐藏通知不进行显示,不设置默认不隐藏通知(仅andorid). 242 | */ 243 | static Future setAppForegroundHiddenNotification(bool hidden) async { 244 | return await _channel.invokeMethod('setAppForegroundHiddenNotification', {'hidden': hidden}); 245 | } 246 | 247 | /* 248 | *设置是否显示角标(仅andorid). 249 | */ 250 | static Future setShowBadge(bool show) async { 251 | return await _channel.invokeMethod('setShowBadge', {'show': show}); 252 | } 253 | 254 | /* 255 | *设置通知静音时段(推送选项)(仅andorid). 256 | */ 257 | static Future setSilenceTime(int startHour, int startMinute, int endHour, int endMinute) async { 258 | return await _channel.invokeMethod('setSilenceTime', { 259 | 'startHour': startHour, 260 | 'startMinute': startMinute, 261 | 'endHour': endHour, 262 | 'endMinute': endMinute 263 | }); 264 | } 265 | 266 | } -------------------------------------------------------------------------------- /mobpush_plugin/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.8.2" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "1.2.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.15.0" 46 | fake_async: 47 | dependency: transitive 48 | description: 49 | name: fake_async 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "1.2.0" 53 | flutter: 54 | dependency: "direct main" 55 | description: flutter 56 | source: sdk 57 | version: "0.0.0" 58 | flutter_test: 59 | dependency: "direct dev" 60 | description: flutter 61 | source: sdk 62 | version: "0.0.0" 63 | matcher: 64 | dependency: transitive 65 | description: 66 | name: matcher 67 | url: "https://pub.flutter-io.cn" 68 | source: hosted 69 | version: "0.12.11" 70 | material_color_utilities: 71 | dependency: transitive 72 | description: 73 | name: material_color_utilities 74 | url: "https://pub.flutter-io.cn" 75 | source: hosted 76 | version: "0.1.3" 77 | meta: 78 | dependency: transitive 79 | description: 80 | name: meta 81 | url: "https://pub.flutter-io.cn" 82 | source: hosted 83 | version: "1.7.0" 84 | path: 85 | dependency: transitive 86 | description: 87 | name: path 88 | url: "https://pub.flutter-io.cn" 89 | source: hosted 90 | version: "1.8.0" 91 | sky_engine: 92 | dependency: transitive 93 | description: flutter 94 | source: sdk 95 | version: "0.0.99" 96 | source_span: 97 | dependency: transitive 98 | description: 99 | name: source_span 100 | url: "https://pub.flutter-io.cn" 101 | source: hosted 102 | version: "1.8.1" 103 | stack_trace: 104 | dependency: transitive 105 | description: 106 | name: stack_trace 107 | url: "https://pub.flutter-io.cn" 108 | source: hosted 109 | version: "1.10.0" 110 | stream_channel: 111 | dependency: transitive 112 | description: 113 | name: stream_channel 114 | url: "https://pub.flutter-io.cn" 115 | source: hosted 116 | version: "2.1.0" 117 | string_scanner: 118 | dependency: transitive 119 | description: 120 | name: string_scanner 121 | url: "https://pub.flutter-io.cn" 122 | source: hosted 123 | version: "1.1.0" 124 | term_glyph: 125 | dependency: transitive 126 | description: 127 | name: term_glyph 128 | url: "https://pub.flutter-io.cn" 129 | source: hosted 130 | version: "1.2.0" 131 | test_api: 132 | dependency: transitive 133 | description: 134 | name: test_api 135 | url: "https://pub.flutter-io.cn" 136 | source: hosted 137 | version: "0.4.8" 138 | typed_data: 139 | dependency: transitive 140 | description: 141 | name: typed_data 142 | url: "https://pub.flutter-io.cn" 143 | source: hosted 144 | version: "1.3.0" 145 | vector_math: 146 | dependency: transitive 147 | description: 148 | name: vector_math 149 | url: "https://pub.flutter-io.cn" 150 | source: hosted 151 | version: "2.1.1" 152 | sdks: 153 | dart: ">=2.14.0 <3.0.0" 154 | flutter: ">=1.12.0" 155 | -------------------------------------------------------------------------------- /mobpush_plugin/pubspec.yaml: -------------------------------------------------------------------------------- 1 | # 标准: 符合插件命名规范 xx_plugin. 2 | name: mobpush_plugin 3 | 4 | # 标准: 必须添加产品说明信息,需要修改时变更. 5 | description: 这是一个基于 MobPush 功能的扩展的 Flutter 插件。使用此插件能够帮助您在使用 Flutter 开发应用时,快速地实现推送功能。 6 | 7 | # 标准: 每次发布新版本,都需要更新版本号. 8 | version: 1.3.0 9 | 10 | # 标准: 添加官网对应插件项目的首页. 11 | homepage: http://www.mob.com/mobService/mobpush 12 | 13 | environment: 14 | # 标准: 最低版本 2.1.0 , 最高版本 x.x.x 15 | sdk: ">=2.12.0 <3.0.0" 16 | 17 | # 标准: 最低版本 1.12.0. 18 | flutter: ">=1.12.0" 19 | 20 | dependencies: 21 | # 标准: 依赖插件,只能是官方的,对于第三方的,需要自己实现,避免冲突 22 | flutter: 23 | sdk: flutter 24 | #json_annotation: ^4.0.1. 第三方,不能用 25 | 26 | dev_dependencies: 27 | # 标准: 依赖插件,只能是官方的,对于第三方的,需要自己实现,避免冲突 28 | flutter_test: 29 | sdk: flutter 30 | #json_annotation: ^4.0.1. 第三方,不能用 31 | 32 | flutter: 33 | 34 | # 标准: 现在需要区分安卓/iOS的包,否则会报错.pluginClass保持统一. 35 | plugin: 36 | platforms: 37 | android: 38 | package: com.mob.flutter.mobpush 39 | pluginClass: MobpushPlugin 40 | ios: 41 | pluginClass: MobpushPlugin 42 | 43 | # 标准: 需要检查部分项目的明文配置信息(通过try命令可以检查是否报错),push的google-services, share的MobSDK.gradle 44 | false_secrets: 45 | - example/android/app/google-services.json 46 | -------------------------------------------------------------------------------- /mobpush_plugin/test/mobpush_plugin_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:mobpush_plugin/mobpush_plugin.dart'; 4 | 5 | void main() { 6 | const MethodChannel channel = MethodChannel('mobpush_plugin'); 7 | 8 | setUp(() { 9 | channel.setMockMethodCallHandler((MethodCall methodCall) async { 10 | return '42'; 11 | }); 12 | }); 13 | 14 | tearDown(() { 15 | channel.setMockMethodCallHandler(null); 16 | }); 17 | 18 | test('getPlatformVersion', () async { 19 | expect(await MobpushPlugin.getPlatformVersion, '42'); 20 | }); 21 | } 22 | --------------------------------------------------------------------------------