├── .gitignore ├── .gitmodules ├── .idea ├── encodings.xml ├── misc.xml ├── modules.xml ├── public_docs.iml ├── scopes │ └── scope_settings.xml └── vcs.xml ├── README.md ├── android_demo_quick_start.md ├── android_faq.md ├── android_kb_android_push.md ├── android_kb_multiple_package.md ├── android_sdk_api_manual.md ├── android_sdk_quick_start.md ├── android_sdk_third_part_push.md ├── android_sdk_troubleshooting.md ├── android_sdk_tutorial.md ├── c_demo_quick_start.md ├── c_sdk_api_manual.md ├── c_sdk_quick_start.md ├── csharp_demo_quick_start.md ├── embeddedc_sdk_api_manual.md ├── image ├── androidpng_demo_api.png ├── androidpng_demo_app_message.png ├── androidpng_demo_import_project.png ├── androidpng_demo_notification.png ├── androidpng_demo_select_project.png ├── androidpng_demo_xiaomi_push.png ├── androidpng_kb_multi_package_add.png ├── androidpng_kb_multi_package_info.png ├── androidpng_kb_push_message.png ├── androidpng_sdk_as_mainfest_package.png ├── androidpng_sdk_genr.png ├── androidpng_sdk_include_lib.png ├── androidpng_sdk_main_window.png ├── androidpng_sdk_package_and_appkey.png ├── androidpng_sdk_rfi.png ├── androidpng_sdk_rfile.png ├── androidpng_thirdpart_jar_path.png ├── cpng_demo_console.png ├── cpng_demo_directory.png ├── cpng_demo_open_sln.png ├── cpng_demo_vs.png ├── csharppng_demo_connected.png ├── csharppng_demo_enter_commonId.png ├── csharppng_demo_mqtt_dot_net.png ├── csharppng_demo_publish_message.png ├── csharppng_demo_run_project.png ├── csharppng_demo_select_project.png ├── csharppng_demo_subscribe.png ├── iospng_cert_before_create_certificate.png ├── iospng_cert_choose_appid.png ├── iospng_cert_choose_type.png ├── iospng_cert_creat_certificate.png ├── iospng_cert_creat_csr.png ├── iospng_cert_download_certifcate.png ├── iospng_cert_enable_push_service.png ├── iospng_cert_enter_name.png ├── iospng_cert_export_certificate.png ├── iospng_cert_new_appId.png ├── iospng_cert_open_key_chain.png ├── iospng_cert_p12_password.png ├── iospng_cert_provision_all.png ├── iospng_cert_provision_appId.png ├── iospng_cert_provision_certificate.png ├── iospng_cert_provision_device.png ├── iospng_cert_provision_done.png ├── iospng_cert_provision_name.png ├── iospng_cert_provision_type.png ├── iospng_cert_save_csr.png ├── iospng_cert_upload_csr.png ├── iospng_demo_bar_message.png ├── iospng_demo_bundle_identity.png ├── iospng_demo_code_sign.png ├── iospng_demo_enable_apns.png ├── iospng_demo_file_list.png ├── iospng_demo_new_message.png ├── iospng_demo_receive_message.png ├── iospng_demo_receive_notification.png ├── iospng_kb_push_apns_message.png ├── iospng_portal_add_certificate.png ├── iospng_portal_upload_certtificate.png ├── iospng_portal_upload_certtificate_success.png ├── iospng_protal_multi_certificate.png ├── iospng_sdk_add_in_xcode.png ├── iospng_troubleshooting_ios_9_registration.png ├── iospng_troubleshooting_keychain_certificate.png ├── iospng_xcode_capabilities_enable_push.png ├── jspng_demo_publish.png ├── jspng_demo_receive_message.png ├── jspng_demo_set_alias.png ├── jspng_demo_subscribe_presence.png ├── jspng_faq_browser_debug.png ├── jspng_troubleshooting_browser_debug.png ├── jspng_troubleshooting_portal_offline1.png ├── jspng_troubleshooting_portal_offline2.png ├── phppng_demo_curl.png ├── phppng_demo_extention_dir.png ├── phppng_demo_extention_openssl.png ├── phppng_demo_include_lib.png ├── phppng_demo_publish_masked.png ├── phppng_demo_publish_success.png ├── phppng_demo_received_message.png ├── phppng_demo_subscribe_masked.png ├── phppng_demo_subscribe_success.png ├── productpng_access_manager_process.png ├── productpng_demo_iot_lamp.gif ├── productpng_demo_push_message.gif ├── productpng_demo_quote_stock.gif ├── productpng_demo_web_drawing.gif ├── productpng_kb_apns.png ├── productpng_kb_connect_step.png ├── productpng_kb_foreign_server.png ├── productpng_kb_identification.png ├── productpng_kb_packet_capture_wireshark.png ├── productpng_kb_packet_capture_wireshark_connect_command.png ├── productpng_kb_packet_capture_wireshark_mqtt.png ├── productpng_kb_packet_capture_wireshark_publish_message.png ├── productpng_kb_presence0.gif ├── productpng_kb_presence_a1.gif ├── productpng_kb_presence_a2.gif ├── productpng_kb_presence_a3.gif ├── productpng_kb_presence_b1.gif ├── productpng_kb_presence_b2.gif ├── productpng_kb_presence_join_and_leave.png ├── productpng_kb_presence_on_offline.png ├── productpng_kb_pub_sub_1.png ├── productpng_kb_pub_sub_2.png ├── productpng_kb_pub_sub_3.png ├── productpng_kb_publish2alias.png ├── productpng_kb_publish2topic.png ├── productpng_kb_quick_start_flow.png ├── productpng_portal_alias_state.png ├── productpng_portal_apps.png ├── productpng_portal_bills.png ├── productpng_portal_copy_app_key.png ├── productpng_portal_creat_app.png ├── productpng_portal_creat_new_app.png ├── productpng_portal_info.png ├── productpng_portal_online_statistic.png ├── productpng_portal_payment.png ├── productpng_portal_portal_publish_history.png ├── productpng_portal_publish.png ├── productpng_portal_publish2_to_alias.png ├── productpng_portal_publish2_to_topic.png ├── productpng_portal_publish2_usage.png ├── productpng_portal_publish_history.png ├── productpng_portal_publish_statistic.png ├── productpng_portal_publish_to_alias.png ├── productpng_portal_publish_to_topic.png ├── productpng_portal_register_account.png ├── productpng_portal_restful_demo.png ├── productpng_portal_third_push_applist.png ├── productpng_portal_third_push_appsource.png ├── productpng_portal_third_push_huawei_setup.png ├── productpng_portal_third_push_xiaomi_setup.png ├── productpng_ss_choose_pso_model.png ├── productpng_ss_enter_pso_setup.png ├── productpng_ss_install_pso.png ├── productpng_ss_mac_socks_set.png ├── productpng_ss_pso_save_change.png ├── productpng_ss_pso_setup.png ├── productpng_ss_running.png ├── productpng_ss_shimo_add_account.png ├── productpng_ss_shimo_creat_ssh.png ├── productpng_ss_shimo_edit_account.png ├── productpng_ss_shimo_meunbar.png ├── productpng_ss_shimo_set_socks5.png ├── productpng_ss_shimo_ssh_info.png ├── productpng_ss_shimo_switch_in_bar.png ├── productpng_ss_shimo_turn_on.png ├── productpng_ss_worked.png ├── socketiopng_demo_client_receive.png ├── socketiopng_demo_publish2_alias.png ├── socketiopng_demo_publish2_topic.png ├── socketiopng_demo_python_on_message.png ├── socketiopng_demo_setting.png └── socketiopng_demo_term_receive.png ├── ios_demo_quick_start.md ├── ios_faq.md ├── ios_kb_apns_implementation.md ├── ios_kb_cfg_remote_notification.md ├── ios_kb_create_apns_certificate.md ├── ios_kb_create_app_id.md ├── ios_kb_create_csr_file.md ├── ios_kb_create_provisioning_profile.md ├── ios_kb_ios_10_impact.md ├── ios_kb_ios_push.md ├── ios_kb_multiple_certificates.md ├── ios_kb_payload.md ├── ios_kb_provider_api.md ├── ios_sdk_api_manual.md ├── ios_sdk_quick_start.md ├── java_demo_quick_start.md ├── java_sdk_api_manual.md ├── js_demo_quick_start.md ├── js_faq.md ├── js_sdk_api_manual.md ├── js_sdk_quick_start.md ├── php_demo_quick_start.md ├── product_best_practice.md ├── product_demo_bullet.md ├── product_faq.md ├── product_kb_access_manager.md ├── product_kb_app_key.md ├── product_kb_identification.md ├── product_kb_message_id.md ├── product_kb_mqtt_porting.md ├── product_kb_offline_message.md ├── product_kb_packet_capture.md ├── product_kb_param.md ├── product_kb_portal.md ├── product_kb_presence.md ├── product_kb_pricing_details.md ├── product_kb_pub_sub.md ├── product_kb_qos.md ├── product_kb_topic_and_alias.md ├── product_kb_topic_filter.md ├── product_kb_whats_yunba.md ├── product_kb_yunba_charitic.md ├── product_kb_yunba_quick_start.md ├── product_kb_yunba_unfixed_ip.md ├── restful_api_api_manual.md ├── restful_faq.md ├── setting ├── README.md ├── newDoc.json └── newDownloads.json ├── socketio_api_api_manual.md ├── socketio_faq.md ├── socketio_java_demo_quick_start.md ├── socketio_python_demo_quick_start.md ├── socketio_wxapp_usage.md ├── white_paper.pdf └── yunba_doc.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/.name 2 | .idea/workspace.xml 3 | report_usage.md 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/.gitmodules -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/public_docs.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yunba Documentation 2 | 3 | ## 资源列表 4 | 5 | - 快速入门 6 | - [云巴是什么](product_kb_whats_yunba.md) 7 | - [常见问题解答(FAQ)](product_faq.md) 8 | - [云巴快速入门教程](product_kb_yunba_quick_start.md) 9 | 10 | - 案例 11 | - [云巴视频直播弹幕](https://github.com/yunbademo/yunba-live-video) 12 | - [云巴智能小屋](https://github.com/yunbademo/yunba-smarthome) 13 | - [云巴智能办公室](https://github.com/yunbademo/yunba-smartoffice) 14 | - [云巴多屏互动](https://github.com/yunbademo/yunba-multi-screen) 15 | - [云巴聊天室](https://github.com/yunbademo/yunba-chatroom) 16 | - [云巴 Yo](https://github.com/yunbademo/YunBa-Yo) 17 | - [更多案例](https://github.com/yunbademo) 18 | 19 | - 功能介绍 20 | - [频道和别名](product_kb_topic_and_alias.md) 21 | - [AppKey](product_kb_app_key.md) 22 | - [Portal](product_kb_portal.md) 23 | - [云巴的实时在线](product_kb_presence.md) 24 | - [云巴的离线消息](product_kb_offline_message.md) 25 | - [QoS](product_kb_qos.md) 26 | - [云巴服务的 IP 是不固定的](product_kb_yunba_unfixed_ip.md) 27 | 28 | - Android 29 | - [云巴 Android 消息推送](android_kb_android_push.md) 30 | - [Android SDK 快速入门](android_sdk_quick_start.md) 31 | - [Android SDK API 手册](android_sdk_api_manual.md) 32 | - [Android SDK 使用指南](android_sdk_tutorial.md) 33 | - [运行 Yunba Android Demo](android_demo_quick_start.md) 34 | 35 | - iOS 36 | - [云巴 iOS 消息推送](ios_kb_ios_push.md) 37 | - [iOS SDK 快速入门](ios_sdk_quick_start.md) 38 | - [iOS SDK API 手册](ios_sdk_api_manual.md) 39 | - [运行 Yunba iOS Demo](ios_demo_quick_start.md) 40 | - [如何通过云巴实现 APNs 推送](ios_kb_apns_implementation.md) 41 | - [生成 APNs 证书的步骤](ios_kb_create_apns_certificate.md) 42 | - [新建 App ID 的步骤](ios_kb_create_app_id.md) 43 | - [新建 CSR 文件的步骤](ios_kb_create_csr_file.md) 44 | - [生成 Provisioning Profile](ios_kb_create_provisioning_profile.md) 45 | - [APNs 推送的 Payload 介绍](ios_kb_payload.md) 46 | - [多证书](ios_kb_multiple_certificates.md) 47 | 48 | - JavaScript 49 | - [JavaScript SDK 快速入门](js_sdk_quick_start.md) 50 | - [JavaScript SDK API 手册](js_sdk_api_manual.md) 51 | - [运行 Yunba JavaScript Demo](js_demo_quick_start.md) 52 | 53 | - C 和 Embedded C 54 | - [快速入门](c_sdk_quick_start.md) 55 | - [C SDK API 手册](c_sdk_api_manual.md) 56 | - [Embedded C API 手册](embeddedc_sdk_api_manual.md) 57 | - [运行 Yunba C Demo](c_demo_quick_start.md) 58 | 59 | - RESTful 60 | - [API 手册](restful_api_api_manual.md) 61 | 62 | - Socket.IO 63 | - [API 手册](socketio_api_api_manual.md) 64 | - [运行 Yunba Socket.IO Python Demo](socketiopython_demo_quick_start.md) 65 | - [运行 Yunba Socket.IO Java Demo](SocketIOjava_demo_quick_start.md) 66 | 67 | - C Sharp 68 | - [运行 Yunba C Sharp Demo](csharp_demo_quick_start.md) 69 | 70 | - Java 71 | - [API 手册](java_sdk_api_manual.md) 72 | - [Yunba Java Demo](java_demo_quick_start.md) 73 | 74 | - PHP(Cli) 75 | - [运行 Yunba PHP Demo](php_demo_quick_start.md) 76 | 77 | ## 文档风格 78 | 79 | - 文档采用 Github 兼容 Markdown 格式编写,后渲染到官网上。 80 | - 中文文档中如果出现英文、数字、超链接或某些特殊字符的文本时,需要在文本两侧加上空格进行分隔。遇到标点符号时可省略空格。如果必须对文本使用引号,需要使用中文的引号。例如:在 WampServer 解压后的 “...\wamp\bin\php” 路径下搜索 php.init 文件;Yunba 的 Android/iOS 消息推送;保留 50 条。 81 | - Github Markdown 的中文引号始终显示为半角引号,在使用引号后,引号外侧需再加个空格。同样地,遇到标点符号时可空格省略。(参考上面的例子) 82 | - 中文文档,一律使用中文标点符号。夹杂英文或其他非中文字符时,尽量只在字符外侧使用空格进行分隔,不使用引号。 83 | - 专用名词统一。特别是中英文翻译,使用统一的对照表。 84 | - API 输入参数使用表格描述。 85 | - 文档的图片使用 Github URL:https://raw.githubusercontent.com/yunba/docs/master/image/xxx.png 86 | - 提到某个函数时,用:`函数名`。例如,`subscribe()`。 87 | - 代码示例中涉及到 AppKey、SecKey、Message ID、Session ID 时,使用统一的示例(代码示例较长,ID 必须变化的情况除外): 88 | - AppKey:567a4a754407a3cd028aaf6b 89 | - SecKey:sec-mj64xlu0ob1Xs1wWuZzmGZOYZqrpFmFxp5jHULr13eUZCVpS 90 | - Message ID:11833652203486491112 91 | - Session ID:567a4a754407a3cd028aaf6b-f02bf150-c653-4557-973f-8526b078d736 92 | - 注意事项另起一行,并用引用的方式写:**注**:……。 93 | - 文档标题为 # 级别,以此类推。 94 | - 需要用到序号时,使用:1. 1.1 1.2 样式。 95 | - 添加代码的首行统一顶格,其余行则遵守代码格式。 96 | 97 | - Anchor: 98 | - 一律为小写字母; 99 | - 空格用短横杠代替; 100 | - 小数点直接忽略掉; 101 | - 例如:小标题“自定义 Receiver 在 AndroidManifest.xml 的配置”对应的是:#自定义-receiver-在-androidmanifestxml-的配置 102 | 103 | 104 | ## 渲染后效果问题 105 | - 换行:Github Markdown(简称 GM)支持 br 换行,但云巴网页(简称 YB)渲染后不支持。(GM 一次换行无效果,两次换行最终效果是一次换行。) 106 | - 标题字号:GM 上 #### 级的字,在 YB 上比普通正文字体还要小。因此,约定 GM 上最多使用 ### 级,再往下,采用双星号加粗表示标题。还可以使用 1. 1.1 样式。 107 | - GM 上使用单个大于号所引导的内容,在 GM 上显示为灰色背景的深灰色字,而在 YB 上渲染后为红色字、有缩进且带大边框,不建议使用。 108 | 109 | ## 文件命名规则 110 | 111 | - 文档的文件名由模块名、文档类型和文档的名称三个部分组成,各个部分用 "_" 连接,全部规定为小写英文字母,除专有英文缩写外不允许缩写。 112 | - 第一部分的名字是平台名,如 ios、android 等,通用的则命名为 product; 113 | - 第二部分的名字是类型,现有 sdk、demo、kb 和 faq 四种; 114 | - 第三部分的名字是文档的名称,没有具体限制,要足够直观,为了简洁性,最好在五个英文单词内,并用"_"连接。 115 | 116 | `例如:android_sdk_quick_start.md` 117 | 118 | - 图片的命名规则同文档类似,也是三个部分。 119 | - 第一部分是平台名后加"png"; 120 | - 第二部分是所用在的类型,如:cert、demo、troubleshooting、sdk 和 portal; 121 | - 第三部分是描述这个图片所进行的行为,要简洁、直观,限定在五个英文单词内,并用"_"连接。 122 | 123 | `例如:productpng_demo_quote_stock` 124 | 125 | ## 图片标注规则 126 | 127 | - 截图 128 | - 约定使用 Paintbrush; 129 | - 选中:用方框第三行首个红色(Maraschino, sRGB: 237.70.47)3号粗; 130 | - 覆盖:用直线首行倒数第四个(Magnesium, sRGB:192.192.192)9号粗。 131 | 132 | - 线框图 133 | - 目前使用 processOn; 134 | - 文字:#323232;英文:Tahoma 12px bold; 135 | - 箭头:#b8b8b8; 136 | - 透明度:100%; 137 | - 彩色块采用最浅色的一组; 138 | - 彩色块加白色 10px 边框,可使得箭头首尾与边框分离,更美观; 139 | 140 | -------------------------------------------------------------------------------- /android_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba Android Demo 2 | 3 | 4 | 本文介绍如何在 Android Studio 中运行 Yunba Android SDK 中的 Demo 示例程序。 5 | 6 | 另,云巴 Android SDK 自 v1.8.0-beta 版本起,开始支持小米、华为推送,通过在这两类机型上的小米、华为推送进程来拉起云巴进程,从而实现应用被杀掉也收到推送的效果。本文将以小米推送为例,对这一功能作出演示。 7 | 8 | 本文涉及的运行环境如下: 9 | 10 | * Mac OS X 10.11.6 11 | * Android Studio 2.2 12 | * Android SDK 4.0.3 (API 15) 13 | * YunBa Android SDK 1.8.0-beta 14 | * 小米手机:MI MAX - Android 6.0.1 15 | 16 | ## 详细步骤 17 | 18 | ### 1. 在云巴 Portal 上创建新应用 19 | 20 | 打开云巴官方网站,注册并登录。 21 | 22 | 点击界面右上角“创建应用”。 23 | 24 | 对于 Android 应用来说,只需填写应用名称、应用包名两项即可。 25 | 26 | 假设我们创建了一个应用包名(PackageName)为:io.yunba.test 的应用。 27 | 28 | 创建完成后,即可得到对应的 AppKey。如图所示: 29 | 30 | ![productpng_portal_info.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_info.png) 31 | 32 | ### 2. 引入 Android Demo 工程 33 | 34 | 云巴官网提供的 Android Demo 是 Eclipse 下的工程,引入 Android Studio 时,需在其 Welcome 界面选择 Import project (Eclipse ADT, Gradle, etc.) 选项。 35 | 36 | 如图所示。 37 | 38 | ![androidpng_demo_import_project.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_demo_import_project.png) 39 | 40 | 在弹出的文件树中,找到下载的 SDK 的 yunba-demo 文件夹,点击 OK 确认,并输入目标工程的路径 (Import Destination Directory),点击 Next、Finish 即可成功导入。 41 | 42 | ![androidpng_demo_select_project.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_demo_select_project.png) 43 | 44 | 45 | 引入后,如遇到错误提示:"failed to find target with hash string android-15", 46 | 则说明您没有安装 Android 4.0.3 (API 15) 的 SDK,打开 Tools --> Android --> SDK Manager,按需要进行安装即可。 47 | 48 | 49 | ### 3. 替换包名 50 | 51 | 由于 Android SDK Demo 使用的应用包名是 io.yunba.example,而本文创建的是 io.yunba.test。因此,需要把工程中所有的 example 重命名为 test。注意,这里不可以仅仅使用文本查找和替换的方式,具体的重命名方法可以参考下文。(在修改过程中,如出现 sync now 的黄色横幅提示,请点击确认) 52 | 53 | - 打开 app - manifests - AndroidManifest.xml,将该文件中的 example 字符批量重命名为 test(笔者的测试环境下,批量重命名的快捷键是 Fn + Shift + F6),并保存; 54 | 55 | - 打开 Gradle Scripts 下的 build.gradle (Module.app),将 `applicationId "io.yunba.example"` 改为 `applicationId "io.yunba.test"`; 56 | 57 | - 右击 app - java - io.yunba.example,选择 Refactor,将 example 改为 test,点击 Do refactor 按钮确认修改; 58 | 59 | - 打开菜单栏的 Edit - Find - Replace in Path,将其他出现 example 的地方替换为 test; 60 | 61 | 至此,包名修改完成。 62 | 63 | ### 4. 替换 AppKey 64 | 65 | 使用第一步中从 Portal 获取到的 AppKey 替换 AndroidManifest.xml 中的 AppKey。 66 | 67 | ### 5. 小米推送相关内容 68 | 69 | 有关小米、华为推送集成的详细内容,可查看 [第三方推送集成指南](android_sdk_third_part_push.md)。这里以小米推送为例,进行简要的说明。 70 | 71 | #### 5.1 创建小米应用 72 | 73 | ![productpng_portal_third_push_appsource.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_third_push_appsource.png) 74 | 75 | 如图所示,用户可以借助云巴提供的“自动创建应用”的功能,委托云巴进行小米或华为应用的申请。申请成功后,获取到的 AppID、AppKey 等应用信息将显示在当前页面上。 76 | 77 | 对于希望自己创建应用的开发者们,可前往小米、华为 Portal 创建应用: 78 | 79 | - 登录小米开发者账号,在 Portal 上新建应用,填写在本例中的应用包名:io.yunba.test; 80 | - 进入小米开放平台下的消息推送模块; 81 | - 点击创建应用 - 创建手机/平板应用; 82 | - 填写应用名称、应用包名后,点击创建,创建成功后,可以查看应用的 AppID、AppKey、AppSecret; 83 | - 点击同意条款后,应用会成功启用; 84 | 85 | #### 5.2 修改 Demo 工程 86 | 87 | 在 Demo 的 YunBaApplication.java 文件中添加 `YunBaManager.setXMRegister(String appid,String appkey)`。 88 | 使用上一步中创建小米应用时获得的 AppID、AppKey 作为参数。添加后如下: 89 | 90 | ```java 91 | YunBaManager.setThirdPartyEnable(getApplicationContext(), true); 92 | YunBaManager.setXMRegister(, ); 93 | YunBaManager.start(getApplicationContext()); 94 | ``` 95 | 96 | ### 6. 在云巴 Portal 填写第三方推送信息 97 | 98 | 登录云巴 Portal,进入应用列表,找到之前创建的应用,并点击其右侧的第三方推送选项。选择小米标签页后,在启用一栏选择“是”,并填上小米应用的包名(io.yunba.test)和 AppSecret 即可。 99 | 100 | ### 7. 编译运行 101 | 102 | 这里以小米 Max 手机为例,连接小米手机并打开开发者模式。在 Android Studio 中,点击 Run 按钮,选择小米设备即可。 103 | 104 | 成功运行后,在小米手机上选择允许安装,**并在 设置 - 授权管理 - 自启动管理 中将 YunBaDemo 的自启动打开**。 105 | 106 | 打开应用,订阅一个名为 news 的 Topic。订阅成功后,将该应用杀死。然后在云巴 Portal 上向 news 发送一条内容为 good news 的消息: 107 | 108 | ![productpng_portal_publish_to_topic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_to_topic.png) 109 | 110 | 发送后,可在小米手机端收到两条通知: 111 | 112 | - 来自小米通知:标题为 yunba_push,内容为 good news; 113 | - 来自云巴通道:标题为 news,内容为 good news; 114 | 115 | ![androidpng_demo_xiaomi_push.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_demo_xiaomi_push.png) 116 | 117 | -------------------------------------------------------------------------------- /android_faq.md: -------------------------------------------------------------------------------- 1 | # Android SDK 常见问题解答 2 | 3 | 4 | 1. **当 App 退出,进程被杀死时,能接收到 Message 吗?** 5 | 6 | 答: Android 端需要在后台保留进程才能接收消息;iOS 端的 APNs 在 App 退出后仍可接收消息。 7 | 8 | Android 端的解决方法:增加相互拉起功能和后台守护进程,使 App 退出后仍能接收到推送消息。可下载并参考 [特殊版本的 SDK](https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.6.3.zip)(该版本仅供测试)。 9 | 10 | 对于 Android 5.0 以上版本的系统,请使用 Android 最新的 SDK,参考我们的[第三方集成指南](android_sdk_third_part_push.md),集成小米、华为推送。 11 | 12 | --- 13 | 2. **Android 端如何设置 qos 等级?** 14 | 15 | 答:`publish2()`、`publish2ToAlias()`的 opts(JSONObject) 参数可以设置 qos。 16 | 17 | 附:qos 为服务质量等级。有三种取值:0 表示最多送达一次;1 表示最少送达一次;2 表示保证送达且仅送达一次。默认为 1。详见 [QoS](product_kb_qos.md) 的说明。 18 | 19 | --- 20 | 3. **Android 端怎么设置离线消息时间?** 21 | 22 | 答: 设置`publish2()`、`publish2ToAlias()`的 opts(JSONObject) 参数; 23 | qos 设置为 1 或 2,就能够保证离线消息的送达;设置 time_to_live,可以控制离线消息在云巴服务器上保留的时间(以秒为单位)。详见:[云巴的离线消息](product_kb_offline_message.md) 。 24 | 25 | --- 26 | 4. **YunBa Android SDK 有没有设置通知栏的 API?** 27 | 28 | 答: 关于设置消息通知栏,YunBa Android SDK 没提供相关的 API。设置方法可参考 [Android 官方文档](http://developer.android.com/guide/topics/ui/notifiers/notifications.html)。 29 | 30 | 31 | --- 32 | 5. **怎么获取 Message 的 Message ID?** 33 | 34 | 答: YunBa Android SDK 暂时没有提供获取接收消息的 Message ID 的API。 35 | 如果需要 Message ID 等自定义内容,可以封装自定义内容到 Message 进行发送,在接收时进行解析。 36 | 37 | --- 38 | 6. **Android 端如何断开连接,不接收消息?** 39 | 40 | 答: 可以调用[`stop()`](android_sdk_api_manual.md#stop)停止推送服务,使所有的 API 都失效(包括 start API);当需要重新使用推送服务时,必须要调用[`resume ()`](android_sdk_api_manual.md#resume)。 41 | 42 | --- 43 | 7. **云巴的第三方推送,小米可以和华为一样只有透传没有通知栏么?** 44 | 45 | 答:(2016.12 更新)该问题已经失效。按照我们目前的做法:如果用户发送第三方推送,华为、小米应用无论是否活着,都会收到一条第三方通道推送的通知;这个通知不会拉起应用,目的是引导用户点击通知栏,打开应用。详见 [第三方推送集成指南](android_sdk_third_part_push.md)。 46 | 47 | --- 48 | 8. **我集成了云巴推送,需要设置混淆吗?** 49 | 50 | 答:Android SDK 已经混淆过了。 51 | 52 | --- 53 | 9. **集成云巴的第三方推送后,为什么手机会有收到两条通知栏的情况?如何应对?** 54 | 55 | 答:按照目前的做法,如果用户发送第三方推送,华为、小米应用无论是否活着,都会收到一条第三方通道推送的通知;另外,在应用活着的状态下,会通过云巴长链接直接收消息,如果应用在收到消息时选择弹出通知(取决于应用开发者),那么此时就会出现两条通知栏的情况。详见 [第三方推送集成指南](android_sdk_third_part_push.md)。 56 | 57 | 由于云巴第三方通道的通知是一定会有的(小米应用在前台时除外),用户可以在收到云巴通道消息时,不弹出通知。 58 | 59 | 例如,可以在`msg`字段中加一个标签,客户端收到消息时,解析``里面的内容,如果带有这个标签,就不弹出通知栏。但由于第三方通道的稳定性不佳,这个方法不适用于依赖我们通道的实时性的场景。 60 | -------------------------------------------------------------------------------- /android_kb_android_push.md: -------------------------------------------------------------------------------- 1 | # 云巴 Android 消息推送 2 | 3 | 如下图所示,客户端集成了云巴的 Android SDK,服务端可通过云巴的 SDK 或使用 RESTful API,向 Android 客户端发消息。 4 | 5 | ![androidpng_kb_push_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_kb_push_message.png) 6 | 7 | * 后台保持长连接 8 | 9 | Android SDK 会启动一个后台的 Service,创建并保持到云巴服务器的长连接,从而保证了消息推送的实时性。 10 | 11 | * 确保消息的送达 12 | 13 | 云巴 SDK 支持 [离线消息](product_kb_offline_message.md) 的功能,可保证消息送达客户端。 14 | 15 | 在推送消息时,如果客户端当前不在线,消息将暂存在云巴服务器上(多达 50 条,长达 15 天)。 16 | 当客户端上线并成功连接到云巴的服务器后,服务器会把离线消息推送给该客户端。客户端成功接收后,服务器才会删除保存的离线消息。 17 | -------------------------------------------------------------------------------- /android_kb_multiple_package.md: -------------------------------------------------------------------------------- 1 | # 多包名 2 | 3 | ## 场景 4 | 5 | 很多 Android 应用在开发时,会为了渠道运营等目的使用多个包名。 6 | 7 | 在这种场景下,可以使用云巴提供的 “多包名” 功能。 8 | 9 | ## 使用对象 10 | 11 | **“多包名” 针对的对象是:同一个 [AppKey](product_kb_app_key.md)、不同包名的 Android 应用。** 12 | 13 | ## 如何使用 14 | 15 | “多包名” 的使用很简单,只需在 [Portal](product_kb_portal.md) 创建应用时添加多个包名即可。也可以在应用创建后,根据需要添加新的包名。 16 | 如下图所示。 17 | 18 | 19 | ![androidpng_kb_multi_package_add.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_kb_multi_package_add.png) 20 | 21 | ![androidpng_kb_multi_package_info.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_kb_multi_package_info.png) 22 | 23 | -------------------------------------------------------------------------------- /android_sdk_quick_start.md: -------------------------------------------------------------------------------- 1 | # Yunba Android SDK 快速入门 2 | ## 注册开发者账号 3 | 4 | 打开 [云巴官方网站](https://yunba.io),点击注册创建账号。 5 | 6 | 7 | ![create_accout.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_register_account.png) 8 | 9 | 10 | ## 创建应用 11 | 12 | 注册账号成功跳转到我的应用界面,点击“创建应用”,输入应用名称和包名(包名为 Java 标准包名规范)。 13 | 14 | 15 | ![productpng_portal_creat_application.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_creat_app.png) 16 | 17 | 18 | ## 下载 Android SDK 19 | 20 | 打开 [云巴开发者页面](https://yunba.io/downloads/) 下载 Android SDK, Android SDK 包含 DEMO 程序和开发者所需嵌入的 jar 包。 21 | 22 | 23 | ## 导入 Android SDK 24 | 25 | 下载的 yunba-sdk-release.jar 包放到项目的 libs 目录下。 26 | 27 | 28 | ![androidpng_sdk_include_lib.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_sdk_include_lib.png) 29 | 30 | 31 | 开发工具为 Android Studio 的 Android SDK 导入步骤可参考 [Demo 运行文档](android_demo_quick_start.md)。 32 | 33 | 34 | ## 配置 AndroidManifest.xml 35 | ### 添加权限 36 | 37 | ```xml 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ``` 55 | 56 | 57 | ### 配置应用的 AppKey(AppKey 来自 Portal,与包名对应) 58 | [AppKey](product_kb_app_key.md) 来自 YunBa 注册的应用,与包名对应。 59 | 60 | 61 | ![appkey-pkg.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_copy_app_key.png) 62 | 63 | 64 | **添加 Appkey** 65 | 66 | 在`......`中加入 67 | ```xml 68 | 69 | 70 | ``` 71 | 72 | 73 | ### 修改应用包名称 74 | 75 | 在 AndroidManifest.xml 中根据 YunBa Portal 注册应用的包名替换 “Your PackageName”, 友情提示:一共有两处需要修改。 76 | 77 | 78 | ### 添加 Service 79 | 80 | 添加 YunBaService,YunBa SDK 会启动一个后台的 service。 81 | 82 | 83 | **添加 YunBaService** 84 | 85 | 在` ... `标签内加入以下Service 86 | ```xml 87 | 88 | ``` 89 | 90 | 91 | ### 添加 Receiver 92 | 93 | 同样地,在` ... `内添加 YunBaReceiver, 用来监听网络变化等事件,确保网络切换时能重新建立长连接。 94 | 95 | ```xml 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | ``` 104 | 105 | 106 | ## 添加使用代码 107 | 108 | 初始化 SDK 并订阅 [Topic](product_kb_topic_and_alias.md),请在您的 Application 子类的 OnCreate 方法中加入如下代码: 109 | 110 | ```java 111 | 112 | public class YourApp extends Application { 113 | 114 | public void onCreate() { 115 | 116 | super.onCreate(); 117 | YunBaManager.start(getApplicationContext()); 118 | 119 | YunBaManager.subscribe(getApplicationContext(), new String[]{"t1"}, new IMqttActionListener() { 120 | 121 | @Override 122 | public void onSuccess(IMqttToken arg0) { 123 | Log.d(TAG, "Subscribe topic succeed"); 124 | } 125 | 126 | @Override 127 | public void onFailure(IMqttToken arg0, Throwable arg1) { 128 | Log.d(TAG, "Subscribe topic failed" ; 129 | } 130 | }); 131 | 132 | } 133 | } 134 | ``` 135 | 136 | 137 | ## 自定义 Receiver 接收 Publish 消息 138 | 139 | YunBa 系统 Publish 的消息会通过广播的形式传递给 App, App 通过监听相关的 Action 接收消息并处理。 140 | 141 | 142 | ### 自定义 Receiver 在 AndroidManifest.xml 的配置 143 | 144 | 自定义 Receiver 接收 Publish 消息, Package Name 为当前应用程序的包名。 145 | 146 | ```xml 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | ``` 155 | 156 | 157 | ### 自定义 Receiver 处理 Publish 消息代码示例 158 | 159 | 自定义 Receiver 处理 Publish 消息 160 | 161 | ```java 162 | 163 | if (YunBaManager.MESSAGE_RECEIVED_ACTION.equals(intent.getAction())) { 164 | 165 | String topic = intent.getStringExtra(YunBaManager.MQTT_TOPIC); 166 | String msg = intent.getStringExtra(YunBaManager.MQTT_MSG); 167 | 168 | //在这里处理从服务器发布下来的消息, 比如显示通知栏, 打开 Activity 等等 169 | StringBuilder showMsg = new StringBuilder(); 170 | showMsg.append("Received message from server: ") 171 | .append(YunBaManager.MQTT_TOPIC) 172 | .append(" = ") 173 | .append(topic) 174 | .append(" ") 175 | .append(YunBaManager.MQTT_MSG) 176 | .append(" = ")\ 177 | 178 | .append(msg); 179 | DemoUtil.showNotifation(context, topic, msg); 180 | } 181 | ``` 182 | 183 | 184 | ## 重新编译文件 185 | 186 | 在 Eclipse 中重新编译项目生成新的 R 文件,在MainActivity,DemoUtil,APIActivity,YunBaTabActivity 重新导入 R 文件。 187 | 188 | 189 | ![此处输入图片的描述](https://github.com/yunba/docs/blob/master/image/androidpng_sdk_genr.png?raw=true) 190 | 191 | 192 | ![此处输入图片的描述](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_sdk_rfi.png) 193 | 194 | 195 | ## 运行程序 196 | 197 | 运行 yunba-demo 程序(Run as Android application), 如果 yunba-demo 程序出现 Connected 的日志表示连接成功。 198 | 199 | 200 | 可能遇到的问题: 201 | 运行程序的过程中可能会出现 **requires API level 10 (current min is 8)** 的问题。只需要修改 AndroidManifest.xml 中的标签 `` 如下: 202 | 203 | ``` 204 | 207 | ``` 208 | 209 | 210 | ### 程序运行主界面 211 | 212 | 213 | ![此处输入图片的描述](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_sdk_main_window.png) 214 | 215 | 216 | ### API 接口界面展示 217 | 218 | 219 | ![此处输入图片的描述](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_demo_api.png) 220 | 221 | 222 | ## 在 Portal 上发布消息 223 | 224 | 客户端集成 YunBa SDK 后,打开 Portal 上的应用详情页面,输入频道名称和消息内容,点击 “发送”,订阅该频道的客户端即可收到消息,如图所示: 225 | 226 | 227 | ![productpng_portal_publish_to_topic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_to_topic.png) 228 | 229 | 230 | ## 在 Portal 查看消息发布实时报表 231 | 232 | 打开应用详情页面,点击 “发布上报统计” 可以查看消息发布 **实时送达比**,如图所示: 233 | 234 | 235 | ![report.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_statistic.png) 236 | 237 | 238 | ## 在 Portal 查看用户在线信息实时报表 239 | 240 | 打开应用详情页面,点击 “在线用户统计” 可以查看当前在线用户数,用户活跃数等信息,如图所示: 241 | 242 | 243 | ![online.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_online_statistic.png) 244 | 245 | 246 | >**注**: 247 | 248 | Portal 的详细使用可参考 [Portal 文档](product_kb_portal.md)。 249 | 250 | 251 | -------------------------------------------------------------------------------- /android_sdk_troubleshooting.md: -------------------------------------------------------------------------------- 1 | # 故障排除 2 | ## 按照步骤操作但接收不到消息 3 | 1. 如果从未成功接收消息,一般为代码集成错误,请参考 [Yunba Android SDK 快速入门](android_sdk_quick_start.md),检查集成步骤。 4 | **提示:**确保完成了 AndroidManifest.xml 的添加权限、配置 AppKey、修改应用包名、添加 Service 、添加 Receiver 和初始化 SDK 几个步骤;检查自定义 Receiver (接收消息)部分的代码,可参考 YunBa Android Demo 的 AndroidManifest.xml 和 DemoReceiver.java。 5 | 2. 检查网络问题,在网络正常情况下为秒内延迟。网络不稳定可能导致客户端与云巴服务端的长连接断开。支持 2G,3G,4G,Wi-Fi 网络环境。 6 | 3. 检查是否有保留后台进程,详见下文的后台进程部分。 7 | 8 | ## 显示“等待来自服务器的响应时超时” 9 | 如果 `subscribe()` 和 `publish()` 等操作未成功过,显示“等待来自服务器的响应时超时”,则一般为代码集成错误;如果是近期的故障,请检查本地网络环境。 10 | 11 | ## 应用退出后收不到消息 12 | 在后台进程驻留的情况下,应用可以接收到消息。 13 | 14 | 当后台进程被系统杀死,则长连接断开,客户端收不到消息。解决方法:可以通过后台进程守护和进程相互拉起使 App 退出后仍能收到消息。请参考 [特殊版本的 SDK](https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.6.3.zip)(该版本仅供测试)。 15 | -------------------------------------------------------------------------------- /c_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba C Demo 2 | 3 | 本文介绍如何运行 Yunba C SDK 中的其中一个 Demo 示例程序。 4 | 5 | 本文涉及的运行环境如下: 6 | - Windows 7 | * Windows 10 Pro 8 | * Microsoft Visual Studio 2015 9 | * YunBa C SDK 10 | - Linux & OS X 11 | * GNU Make,gcc 12 | * GNU bash 13 | * OpenSSL 14 | 15 | ## 准备工作 16 | 17 | ###1. 下载云巴 C SDK 18 | 这里使用的是云巴 C SDK 的 feature/windows_building 下的工程,这个工程是在 Visual Studio 2015 下 build 的。 19 | 可打开[其 GitHub 页](https://github.com/yunba/yunba-c-sdk/tree/feature/windows_building),下载 Zip 文件。 20 | 21 | ![cpng_demo_directory.png](https://raw.githubusercontent.com/yunba/docs/master/image/cpng_demo_directory.png) 22 | 23 | ###2. 注册云巴开发者账号 24 | 打开 [云巴官方网站](https://yunba.io),点击右上角的“注册”按钮创建账号。 25 | 26 | ## 详细步骤 27 | 28 | ### - Windows 29 | 30 | ###1. 在云巴 Portal 上创建新应用 31 | 请参考 [运行 Yunba Android Demo](android_demo_quick_start.md) 32 | 一文中的该步骤的做法,获得一个 AppKey。 33 | 34 | ###2. 打开工程 35 | 本文以 [stdoutsub](https://github.com/yunba/yunba-c-sdk/tree/feature/windows_building/Windows%20Build/stdoutsub) 工程为例, 36 | 演示 C SDK 的使用。 37 | 解压之前下载的 Zip 文件,在 Visual Studio 2015 中打开“Paho C MQTT APIs.sln”工程。如图: 38 | 39 | ![cpng_demo_open_sln.png](https://raw.githubusercontent.com/yunba/docs/master/image/cpng_demo_open_sln.png) 40 | 41 | 右击 stdoutsub 工程,选择“设为启动项目”。 42 | 43 | ![cpng_demo_vs.png](https://raw.githubusercontent.com/yunba/docs/master/image/cpng_demo_vs.png) 44 | 45 | ###3. 输入参数 46 | 修改 [stdoutsub](https://github.com/yunba/yunba-c-sdk/blob/feature/windows_building/src/samples/stdoutsub.c) 中的 main 函数的参数输入部分。 47 | 48 | 为了便于演示,我们将原程序的部分语句注释掉,对 AppKey 和 Topic 直接赋值。如下所示: 49 | 50 | ```C 51 | int main(int argc, char** argv) 52 | { 53 | //MQTTClient client; 54 | // MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; 55 | char topic[200] = ""; 56 | char* buffer = NULL; 57 | int rc = 0; 58 | char url[100]; 59 | char broker[100]; 60 | 61 | // if (argc < 2) 62 | // usage(); 63 | 64 | // getopts(argc, argv); 65 | 66 | // sprintf(url, "%s:%s", opts.host, opts.port); 67 | // if (opts.verbose) 68 | // printf("URL is %s\n", url); 69 | 70 | char a[200] = "567a4a754407a3cd028aaf6b"; //请替换为你在步骤 1 中申请到的 AppKey。 71 | char b[200] = "news"; //填上 Topic 的名称,如,“news”。 72 | // strcpy(topic, argv[1]); 73 | 74 | opts.appkey = a; //给 opt.appkey 赋值 75 | strcpy(topic,b); //给 topic 赋值 76 | 77 | printf("Using topic %s\n", topic); 78 | 79 | //其他代码略。 80 | 81 | ``` 82 | ###4. 运行程序 83 | **注**:如果遇到 “无法解析的外部符号 _cJSON_” 的错误提示,则表示 cJSON 库没有正确导入,可以右击工程 -> 属性 -> 配置属性 -> VC++ 目录 -> 库目录 -> 编辑,然后添加 cJSON 文件所在的路径即可。 84 | 85 | 修改好后,直接运行。可以看到控制台的打印信息。 86 | 在控制台直接输入需要发送的信息,回车,即可向设定的 Topic 发送信息,如,发送一条“good news”。 87 | 在这个例子中,设定的 Topic 是“news”,且 C 客户端本身也订阅了“news”。因此,发出的消息自己也可以收到。 88 | 如果使用同一个 AppKey 的另一个客户端(如,Portal)向“news”发送消息,C 客户端也会收到,控制台会将收到的消息打印出来。 89 | 90 | ![cpng_demo_console.png](https://raw.githubusercontent.com/yunba/docs/master/image/cpng_demo_console.png) 91 | 92 | ### - Linux & OS X 93 | 94 | ###1. make 95 | 使用 make 来生成可执行文件,本 demo 包含一份 makefile,在 makefile 所在的路径下执行`make`,成功后会在 yunba-c-sdk/build/output/sample/ 下生成 stdouta\_demo 和 stdinpub\_present 两个可执行文件。Linux 用户在`make`后还要进行`make install`,将依赖库文件移动到系统目录中去。 96 | 97 | *注意:由于本demo没有针对OS X做适配,所以 OS X 用户在`make`后需要手动将 yunba-c-sdk/build/output/ 中的所有依赖库移动到 yunba-c-sdk/build/output/samples 中* 98 | 99 | ###2. 执行 100 | 使用 bash 或其它命令行工具进入可执行文件的路径,然后执行该程序。 101 | 102 | ###3. `stdinpub_present`的使用 103 | `stdinpub_present` 的使用方法是 `stdinpub_present --appkey --deviceid --retained --qos --delimiter `。``和``是必须的,其余为可选项,不填的话使用默认值,其中``可以使用已有的,没有的话系统会自动给您分配一个,用以在后台区分用户;`retained`默认关闭,打开后可以收到自己发送的消息;``为分隔符,打出该字符后会发送该字符前的字符,默认为`\n`。 104 | 105 | - 示例:`./stdinpub_present test --appkey 567a4a754407a3cd028aaf6b --retained` 106 | 107 | ###4. 结果 108 | 运行成功后会订阅你填写的频道,并向该频道发送一个消息,获得 Client-ID 和 password。您可以在 Portal 中看到。还会向服务器询问该 topic 的 aliaslist、topic 和 status 的信息,服务器会向你返回一个获取完以后当您按回车之后会把在分割符``之前的字符推送到频道去。 109 | 110 | ###5. `stdouta_demo`的使用 111 | `stdouta_demo` 的使用方法与 stdinpub\_present 类似,只是没有订阅 present。 112 | 113 | - 示例:`./stdouta_demo tttest --appkey 567a4a754407a3cd028aaf6b` 114 | 115 | ###6. 结果 116 | 运行成功后会订阅你填写的频道,并向该频道发送一个推送消息,获得 Client-ID 和 password。之后程序会维持这个链接,在命令行中输入消息的内容并按 Enter 后会把分割符``之前的字符推送到频道去。 117 | 118 | ### 附:demo 的功能 119 | - stdouta\_present 可以订阅一个频道,并向该频道发送一个推送消息,同时会订阅该频道的 present 消息,查询该频道的 aliaslist、topic 和 status。向云巴服务器发送 device ID(如果没有服务器会给您返回一个),并请求 Client-ID 和 password。程序之后会维持这个链接,在命令行中输入消息的内容并按 Enter 后会发送分割符``之前的字符。 120 | 121 | - stdouta\_demo 可以订阅一个频道,并向该频道发送一个推送消息,向云巴服务器发送 device ID(如果没有服务器会给您返回一个),并请求 Client-ID 和 password。发送完毕后会维持这个链接,在命令行中输入消息的内容并按 Enter 后会发送分割符``之前的字符。 -------------------------------------------------------------------------------- /c_sdk_quick_start.md: -------------------------------------------------------------------------------- 1 | # Yunba C 快速入门 2 | 3 | ## 注册开发者账号 4 | 5 | 打开 [云巴官方网站](https://yunba.io), 点击注册创建账号。 6 | 7 | ![create_accout.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_register_account.png) 8 | 9 | ## 创建应用 10 | 注册账号成功跳转到我的应用界面,点击“创建应用”,输入应用名称和包名 11 | 12 | ![productpng_portal_creat_application.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_creat_app.png) 13 | 14 | 15 | ##从哪里获得 SDK 16 | 17 | 你可以使用下面命令去获得 SDK 18 | 19 | 打开 [开发者资源页面](https://yunba.io/downloads/) 下载 C SDK。 20 | 21 | ##怎么开始 22 | ###1.添加 lib 以及 header 到 Makefile: 23 | 24 | ```c 25 | INCLUDEPATH = -I/home/yunba/test/yunba-c-sdk/install/include 26 | LIBPATH = -L/home/yunba/test/yunba-c-sdk/install/lib 27 | ``` 28 | 29 | 其中/home/yunba/test/yunba-c-sdk/install 是你的 yunba SDK 目录。 30 | 31 | ###2.在应用中添加 yunba 服务。 32 | 在你的代码中应用包含: 33 | 34 | ```c 35 | #include "yunba.h" 36 | ``` 37 | 38 | 在入口函数中添加 yunba 服务初始化: 39 | ```c 40 | REG_info my_reg_info; 41 | int res = MQTTClient_setup_with_appkey(appkey, &my_reg_info); 42 | if (res < 0) { 43 | printf("can't get info"); 44 | return -1; 45 | } 46 | ``` 47 | 上面 appkey 为用户注册获得的 appkey。 48 | 49 | 获得url. 50 | ```c 51 | char url[200]; 52 | MQTTClient_get_host(appkey, url); 53 | ``` 54 | url用来保存获得url. 55 | 56 | 57 | 接下来, 58 | ```c 59 | MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; 60 | rc = MQTTClient_create(&client, url, my_reg_info.client_id, MQTTCLIENT_PERSISTENCE_NONE, NULL); 61 | 62 | rc = MQTTClient_setCallbacks(client, NULL, NULL, messageArrived, NULL, extendedCmdArrive); 63 | ``` 64 | 连接到服务器。 65 | 66 | ```c 67 | conn_opts.username = my_reg_info.username; 68 | conn_opts.password = my_reg_info.password; 69 | if (MQTTClient_connect(*client, opts) != 0) { 70 | return -1; 71 | } 72 | ``` 73 | 74 | 订阅你的频道 75 | 76 | ```c 77 | rc = MQTTClient_subscribe(client, "your_channel"); 78 | ``` 79 | 80 | 其中messageArrived, extendedCmdArrive为回调函数。 81 | 82 | 下面函数处理status, get alias get-topic等扩展命令。 83 | 84 | ```c 85 | int extendedCmdArrive(void *context, EXTED_CMD cmd, int status, int ret_string_len, char *ret_string) 86 | { 87 | //处理接收到的扩展命令返回。 88 | } 89 | 90 | int messageArrived(void* context, char* topicName, int topicLen, MQTTClient_message* m) 91 | { 92 | //处理topic以及推送的消息内容。 93 | } 94 | ``` 95 | 96 | 当你的程序退出时,不要忘记使用: 97 | 98 | ```c 99 | MQTTClient_destroy(&client) 100 | ``` 101 | 102 | ## 例子代码 103 | 104 | 在 C SDK 目录下 src/samples/stdinpub_present.c 。 105 | 106 | 107 | -------------------------------------------------------------------------------- /csharp_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba C# Demo 2 | 3 | 本文介绍如何运行 Yunba C# SDK 中的 Sample Demo 示例程序。 4 | 5 | 本文涉及的运行环境如下: 6 | 7 | * Windows 8.1 8 | * Microsoft Visual Studio 2015 9 | * YunBa C# SDK 10 | 11 | ## 准备工作 12 | 13 | ### 1. 下载云巴 C# SDK 14 | 这里使用的是 Yunba C# SDK ,这个工程是在 Visual Studio 2013 下 build 的。 15 | 可打开[其 GitHub 页](https://github.com/yunba/yunba-csharp-sdk),下载 Zip 文件。 16 | 17 | 18 | ### 2. 注册云巴开发者账号 19 | 打开 [云巴官方网站](https://yunba.io),点击右上角的“注册”按钮创建账号。 20 | 21 | ## 详细步骤 22 | 23 | ### 1. 在云巴 Portal 上创建新应用 24 | 请参考 [运行 Yunba Android Demo](android_demo_quick_start.md) 25 | 一文中的该步骤的做法,获得一个 AppKey。 26 | 27 | ### 2. 打开工程 28 | 本文以 [Yunba C# SDK](https://github.com/yunba/yunba-csharp-sdk) 的 Sample 工程为例,演示 C# SDK 的使用。 29 | 30 | 解压下载的 Zip 文件,在 Visual Studio 2013 中打开 "MqttDotNet.sln" 工程。如图: 31 | 32 | 33 | ![csharppng_demo_mqtt_dot_net.png](https://raw.githubusercontent.com/yunba/docs/master/image/csharppng_demo_mqtt_dot_net.png) 34 | 35 | 36 | 右击 Sample 工程,选择“设为启动项目”。 37 | 38 | 39 | ![csharppng_demo_select_project.png](https://github.com/yunba/docs/blob/master/image/csharppng_demo_select_project.png) 40 | 41 | 42 | ### 3. 运行程序 43 | 运行程序,会生成 "\yunba-csharp-sdk-master\Sample\bin\Debug" 路径下的 "Sample.exe"。 44 | 在控制台进入该路径,启动 "Sample.exe" ,同时输入 AppKey,如图: 45 | 46 | ![csharppng_demo_run_project.png](https://raw.githubusercontent.com/yunba/docs/master/image/csharppng_demo_run_project.png) 47 | 48 | 连接成功之后会显示 "Client connected",可以按任意键继续往下执行。如图: 49 | 50 | ![csharppng_demo_connected.png](https://raw.githubusercontent.com/yunba/docs/master/image/csharppng_demo_connected.png) 51 | 52 | 按任意键之后将出现如下提示: 53 | 54 | ![csharppng_demo_enter_commonId.png](https://raw.githubusercontent.com/yunba/docs/master/image/csharppng_demo_enter_commonId.png) 55 | 56 | 可以先订阅话题 `subscribe()` : 57 | 58 | ![csharppng_demo_subscribe.png](https://raw.githubusercontent.com/yunba/docs/master/image/csharppng_demo_subscribe.png) 59 | 60 | 再发布消息 `publish()`。发布成功后,使用同一 AppKey 并且已订阅该 Topic 的其它客户端将收到消息。使用同一个 AppKey 的客户端在该 Topic 下发布的消息,C# 端也将收到。 61 | 62 | ![csharppng_demo_publish_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/csharppng_demo_publish_message.png) 63 | 64 | 65 | 详细的程序逻辑,请参考项目源程序。 66 | 67 | 68 | >**注**: 69 | 70 | 如需清除用户信息,可删除工程 "bin/Debug" 路径下所有以 ".config" 为后缀名的文件。 71 | 72 | -------------------------------------------------------------------------------- /image/androidpng_demo_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_demo_api.png -------------------------------------------------------------------------------- /image/androidpng_demo_app_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_demo_app_message.png -------------------------------------------------------------------------------- /image/androidpng_demo_import_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_demo_import_project.png -------------------------------------------------------------------------------- /image/androidpng_demo_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_demo_notification.png -------------------------------------------------------------------------------- /image/androidpng_demo_select_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_demo_select_project.png -------------------------------------------------------------------------------- /image/androidpng_demo_xiaomi_push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_demo_xiaomi_push.png -------------------------------------------------------------------------------- /image/androidpng_kb_multi_package_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_kb_multi_package_add.png -------------------------------------------------------------------------------- /image/androidpng_kb_multi_package_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_kb_multi_package_info.png -------------------------------------------------------------------------------- /image/androidpng_kb_push_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_kb_push_message.png -------------------------------------------------------------------------------- /image/androidpng_sdk_as_mainfest_package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_sdk_as_mainfest_package.png -------------------------------------------------------------------------------- /image/androidpng_sdk_genr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_sdk_genr.png -------------------------------------------------------------------------------- /image/androidpng_sdk_include_lib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_sdk_include_lib.png -------------------------------------------------------------------------------- /image/androidpng_sdk_main_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_sdk_main_window.png -------------------------------------------------------------------------------- /image/androidpng_sdk_package_and_appkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_sdk_package_and_appkey.png -------------------------------------------------------------------------------- /image/androidpng_sdk_rfi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_sdk_rfi.png -------------------------------------------------------------------------------- /image/androidpng_sdk_rfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_sdk_rfile.png -------------------------------------------------------------------------------- /image/androidpng_thirdpart_jar_path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/androidpng_thirdpart_jar_path.png -------------------------------------------------------------------------------- /image/cpng_demo_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/cpng_demo_console.png -------------------------------------------------------------------------------- /image/cpng_demo_directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/cpng_demo_directory.png -------------------------------------------------------------------------------- /image/cpng_demo_open_sln.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/cpng_demo_open_sln.png -------------------------------------------------------------------------------- /image/cpng_demo_vs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/cpng_demo_vs.png -------------------------------------------------------------------------------- /image/csharppng_demo_connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/csharppng_demo_connected.png -------------------------------------------------------------------------------- /image/csharppng_demo_enter_commonId.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/csharppng_demo_enter_commonId.png -------------------------------------------------------------------------------- /image/csharppng_demo_mqtt_dot_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/csharppng_demo_mqtt_dot_net.png -------------------------------------------------------------------------------- /image/csharppng_demo_publish_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/csharppng_demo_publish_message.png -------------------------------------------------------------------------------- /image/csharppng_demo_run_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/csharppng_demo_run_project.png -------------------------------------------------------------------------------- /image/csharppng_demo_select_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/csharppng_demo_select_project.png -------------------------------------------------------------------------------- /image/csharppng_demo_subscribe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/csharppng_demo_subscribe.png -------------------------------------------------------------------------------- /image/iospng_cert_before_create_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_before_create_certificate.png -------------------------------------------------------------------------------- /image/iospng_cert_choose_appid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_choose_appid.png -------------------------------------------------------------------------------- /image/iospng_cert_choose_type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_choose_type.png -------------------------------------------------------------------------------- /image/iospng_cert_creat_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_creat_certificate.png -------------------------------------------------------------------------------- /image/iospng_cert_creat_csr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_creat_csr.png -------------------------------------------------------------------------------- /image/iospng_cert_download_certifcate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_download_certifcate.png -------------------------------------------------------------------------------- /image/iospng_cert_enable_push_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_enable_push_service.png -------------------------------------------------------------------------------- /image/iospng_cert_enter_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_enter_name.png -------------------------------------------------------------------------------- /image/iospng_cert_export_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_export_certificate.png -------------------------------------------------------------------------------- /image/iospng_cert_new_appId.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_new_appId.png -------------------------------------------------------------------------------- /image/iospng_cert_open_key_chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_open_key_chain.png -------------------------------------------------------------------------------- /image/iospng_cert_p12_password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_p12_password.png -------------------------------------------------------------------------------- /image/iospng_cert_provision_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_provision_all.png -------------------------------------------------------------------------------- /image/iospng_cert_provision_appId.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_provision_appId.png -------------------------------------------------------------------------------- /image/iospng_cert_provision_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_provision_certificate.png -------------------------------------------------------------------------------- /image/iospng_cert_provision_device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_provision_device.png -------------------------------------------------------------------------------- /image/iospng_cert_provision_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_provision_done.png -------------------------------------------------------------------------------- /image/iospng_cert_provision_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_provision_name.png -------------------------------------------------------------------------------- /image/iospng_cert_provision_type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_provision_type.png -------------------------------------------------------------------------------- /image/iospng_cert_save_csr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_save_csr.png -------------------------------------------------------------------------------- /image/iospng_cert_upload_csr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_cert_upload_csr.png -------------------------------------------------------------------------------- /image/iospng_demo_bar_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_demo_bar_message.png -------------------------------------------------------------------------------- /image/iospng_demo_bundle_identity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_demo_bundle_identity.png -------------------------------------------------------------------------------- /image/iospng_demo_code_sign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_demo_code_sign.png -------------------------------------------------------------------------------- /image/iospng_demo_enable_apns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_demo_enable_apns.png -------------------------------------------------------------------------------- /image/iospng_demo_file_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_demo_file_list.png -------------------------------------------------------------------------------- /image/iospng_demo_new_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_demo_new_message.png -------------------------------------------------------------------------------- /image/iospng_demo_receive_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_demo_receive_message.png -------------------------------------------------------------------------------- /image/iospng_demo_receive_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_demo_receive_notification.png -------------------------------------------------------------------------------- /image/iospng_kb_push_apns_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_kb_push_apns_message.png -------------------------------------------------------------------------------- /image/iospng_portal_add_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_portal_add_certificate.png -------------------------------------------------------------------------------- /image/iospng_portal_upload_certtificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_portal_upload_certtificate.png -------------------------------------------------------------------------------- /image/iospng_portal_upload_certtificate_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_portal_upload_certtificate_success.png -------------------------------------------------------------------------------- /image/iospng_protal_multi_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_protal_multi_certificate.png -------------------------------------------------------------------------------- /image/iospng_sdk_add_in_xcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_sdk_add_in_xcode.png -------------------------------------------------------------------------------- /image/iospng_troubleshooting_ios_9_registration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_troubleshooting_ios_9_registration.png -------------------------------------------------------------------------------- /image/iospng_troubleshooting_keychain_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_troubleshooting_keychain_certificate.png -------------------------------------------------------------------------------- /image/iospng_xcode_capabilities_enable_push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/iospng_xcode_capabilities_enable_push.png -------------------------------------------------------------------------------- /image/jspng_demo_publish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/jspng_demo_publish.png -------------------------------------------------------------------------------- /image/jspng_demo_receive_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/jspng_demo_receive_message.png -------------------------------------------------------------------------------- /image/jspng_demo_set_alias.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/jspng_demo_set_alias.png -------------------------------------------------------------------------------- /image/jspng_demo_subscribe_presence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/jspng_demo_subscribe_presence.png -------------------------------------------------------------------------------- /image/jspng_faq_browser_debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/jspng_faq_browser_debug.png -------------------------------------------------------------------------------- /image/jspng_troubleshooting_browser_debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/jspng_troubleshooting_browser_debug.png -------------------------------------------------------------------------------- /image/jspng_troubleshooting_portal_offline1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/jspng_troubleshooting_portal_offline1.png -------------------------------------------------------------------------------- /image/jspng_troubleshooting_portal_offline2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/jspng_troubleshooting_portal_offline2.png -------------------------------------------------------------------------------- /image/phppng_demo_curl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_curl.png -------------------------------------------------------------------------------- /image/phppng_demo_extention_dir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_extention_dir.png -------------------------------------------------------------------------------- /image/phppng_demo_extention_openssl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_extention_openssl.png -------------------------------------------------------------------------------- /image/phppng_demo_include_lib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_include_lib.png -------------------------------------------------------------------------------- /image/phppng_demo_publish_masked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_publish_masked.png -------------------------------------------------------------------------------- /image/phppng_demo_publish_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_publish_success.png -------------------------------------------------------------------------------- /image/phppng_demo_received_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_received_message.png -------------------------------------------------------------------------------- /image/phppng_demo_subscribe_masked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_subscribe_masked.png -------------------------------------------------------------------------------- /image/phppng_demo_subscribe_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/phppng_demo_subscribe_success.png -------------------------------------------------------------------------------- /image/productpng_access_manager_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_access_manager_process.png -------------------------------------------------------------------------------- /image/productpng_demo_iot_lamp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_demo_iot_lamp.gif -------------------------------------------------------------------------------- /image/productpng_demo_push_message.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_demo_push_message.gif -------------------------------------------------------------------------------- /image/productpng_demo_quote_stock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_demo_quote_stock.gif -------------------------------------------------------------------------------- /image/productpng_demo_web_drawing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_demo_web_drawing.gif -------------------------------------------------------------------------------- /image/productpng_kb_apns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_apns.png -------------------------------------------------------------------------------- /image/productpng_kb_connect_step.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_connect_step.png -------------------------------------------------------------------------------- /image/productpng_kb_foreign_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_foreign_server.png -------------------------------------------------------------------------------- /image/productpng_kb_identification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_identification.png -------------------------------------------------------------------------------- /image/productpng_kb_packet_capture_wireshark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_packet_capture_wireshark.png -------------------------------------------------------------------------------- /image/productpng_kb_packet_capture_wireshark_connect_command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_packet_capture_wireshark_connect_command.png -------------------------------------------------------------------------------- /image/productpng_kb_packet_capture_wireshark_mqtt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_packet_capture_wireshark_mqtt.png -------------------------------------------------------------------------------- /image/productpng_kb_packet_capture_wireshark_publish_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_packet_capture_wireshark_publish_message.png -------------------------------------------------------------------------------- /image/productpng_kb_presence0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_presence0.gif -------------------------------------------------------------------------------- /image/productpng_kb_presence_a1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_presence_a1.gif -------------------------------------------------------------------------------- /image/productpng_kb_presence_a2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_presence_a2.gif -------------------------------------------------------------------------------- /image/productpng_kb_presence_a3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_presence_a3.gif -------------------------------------------------------------------------------- /image/productpng_kb_presence_b1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_presence_b1.gif -------------------------------------------------------------------------------- /image/productpng_kb_presence_b2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_presence_b2.gif -------------------------------------------------------------------------------- /image/productpng_kb_presence_join_and_leave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_presence_join_and_leave.png -------------------------------------------------------------------------------- /image/productpng_kb_presence_on_offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_presence_on_offline.png -------------------------------------------------------------------------------- /image/productpng_kb_pub_sub_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_pub_sub_1.png -------------------------------------------------------------------------------- /image/productpng_kb_pub_sub_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_pub_sub_2.png -------------------------------------------------------------------------------- /image/productpng_kb_pub_sub_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_pub_sub_3.png -------------------------------------------------------------------------------- /image/productpng_kb_publish2alias.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_publish2alias.png -------------------------------------------------------------------------------- /image/productpng_kb_publish2topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_publish2topic.png -------------------------------------------------------------------------------- /image/productpng_kb_quick_start_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_kb_quick_start_flow.png -------------------------------------------------------------------------------- /image/productpng_portal_alias_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_alias_state.png -------------------------------------------------------------------------------- /image/productpng_portal_apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_apps.png -------------------------------------------------------------------------------- /image/productpng_portal_bills.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_bills.png -------------------------------------------------------------------------------- /image/productpng_portal_copy_app_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_copy_app_key.png -------------------------------------------------------------------------------- /image/productpng_portal_creat_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_creat_app.png -------------------------------------------------------------------------------- /image/productpng_portal_creat_new_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_creat_new_app.png -------------------------------------------------------------------------------- /image/productpng_portal_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_info.png -------------------------------------------------------------------------------- /image/productpng_portal_online_statistic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_online_statistic.png -------------------------------------------------------------------------------- /image/productpng_portal_payment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_payment.png -------------------------------------------------------------------------------- /image/productpng_portal_portal_publish_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_portal_publish_history.png -------------------------------------------------------------------------------- /image/productpng_portal_publish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_publish.png -------------------------------------------------------------------------------- /image/productpng_portal_publish2_to_alias.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_publish2_to_alias.png -------------------------------------------------------------------------------- /image/productpng_portal_publish2_to_topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_publish2_to_topic.png -------------------------------------------------------------------------------- /image/productpng_portal_publish2_usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_publish2_usage.png -------------------------------------------------------------------------------- /image/productpng_portal_publish_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_publish_history.png -------------------------------------------------------------------------------- /image/productpng_portal_publish_statistic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_publish_statistic.png -------------------------------------------------------------------------------- /image/productpng_portal_publish_to_alias.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_publish_to_alias.png -------------------------------------------------------------------------------- /image/productpng_portal_publish_to_topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_publish_to_topic.png -------------------------------------------------------------------------------- /image/productpng_portal_register_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_register_account.png -------------------------------------------------------------------------------- /image/productpng_portal_restful_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_restful_demo.png -------------------------------------------------------------------------------- /image/productpng_portal_third_push_applist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_third_push_applist.png -------------------------------------------------------------------------------- /image/productpng_portal_third_push_appsource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_third_push_appsource.png -------------------------------------------------------------------------------- /image/productpng_portal_third_push_huawei_setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_third_push_huawei_setup.png -------------------------------------------------------------------------------- /image/productpng_portal_third_push_xiaomi_setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_portal_third_push_xiaomi_setup.png -------------------------------------------------------------------------------- /image/productpng_ss_choose_pso_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_choose_pso_model.png -------------------------------------------------------------------------------- /image/productpng_ss_enter_pso_setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_enter_pso_setup.png -------------------------------------------------------------------------------- /image/productpng_ss_install_pso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_install_pso.png -------------------------------------------------------------------------------- /image/productpng_ss_mac_socks_set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_mac_socks_set.png -------------------------------------------------------------------------------- /image/productpng_ss_pso_save_change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_pso_save_change.png -------------------------------------------------------------------------------- /image/productpng_ss_pso_setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_pso_setup.png -------------------------------------------------------------------------------- /image/productpng_ss_running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_running.png -------------------------------------------------------------------------------- /image/productpng_ss_shimo_add_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_shimo_add_account.png -------------------------------------------------------------------------------- /image/productpng_ss_shimo_creat_ssh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_shimo_creat_ssh.png -------------------------------------------------------------------------------- /image/productpng_ss_shimo_edit_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_shimo_edit_account.png -------------------------------------------------------------------------------- /image/productpng_ss_shimo_meunbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_shimo_meunbar.png -------------------------------------------------------------------------------- /image/productpng_ss_shimo_set_socks5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_shimo_set_socks5.png -------------------------------------------------------------------------------- /image/productpng_ss_shimo_ssh_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_shimo_ssh_info.png -------------------------------------------------------------------------------- /image/productpng_ss_shimo_switch_in_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_shimo_switch_in_bar.png -------------------------------------------------------------------------------- /image/productpng_ss_shimo_turn_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_shimo_turn_on.png -------------------------------------------------------------------------------- /image/productpng_ss_worked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/productpng_ss_worked.png -------------------------------------------------------------------------------- /image/socketiopng_demo_client_receive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/socketiopng_demo_client_receive.png -------------------------------------------------------------------------------- /image/socketiopng_demo_publish2_alias.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/socketiopng_demo_publish2_alias.png -------------------------------------------------------------------------------- /image/socketiopng_demo_publish2_topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/socketiopng_demo_publish2_topic.png -------------------------------------------------------------------------------- /image/socketiopng_demo_python_on_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/socketiopng_demo_python_on_message.png -------------------------------------------------------------------------------- /image/socketiopng_demo_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/socketiopng_demo_setting.png -------------------------------------------------------------------------------- /image/socketiopng_demo_term_receive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/image/socketiopng_demo_term_receive.png -------------------------------------------------------------------------------- /ios_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba iOS Demo 2 | 3 | 本文介绍如何运行 Yunba iOS SDK 中的 Demo 示例程序。 4 | 本文涉及的运行环境如下: 5 | 6 | * Mac OS X 10.11.1 7 | * Xcode 7.0.1 8 | * YunBa iOS SDK 1.6.0 9 | 10 | ## 准备工作 11 | 12 | ###1. 注册云巴开发者账号 13 | 打开 [云巴官方网站](https://yunba.io),点击右上角的“注册”按钮创建账号。 14 | 15 | ###2. 下载云巴 iOS SDK 16 | 打开 [云巴开发者页面](https://yunba.io/downloads/),下载最新版本的 iOS SDK。iOS SDK 包含 Demo 程序和开发者所需嵌入的 lib 库以及头文件。 17 | 18 | ## 详细步骤 19 | 20 | ###1. 生成 APNs 证书 21 | iOS Demo 程序会用到 APNs,因此,在运行之前,请先参考 [生成 APNs 证书的步骤](ios_kb_create_apns_certificate.md) 一文,生成 APNs 证书。 22 | 23 | ###2. 在云巴 Portal 上创建新应用 24 | 25 | 打开 [云巴官方网站](https://yunba.io),登录,点击 “创建应用”。 26 | 27 | ![productpng_portal_creat_app.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_creat_app.png) 28 | 29 | 输入应用的名称及 Bundle ID。 30 | 31 | ![productpng_portal_creat_new_app.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_creat_new_app.png) 32 | 33 | 同时,上传上一个步骤中生成的 iOS 开发或生产证书,并输入导出证书时所设置的证书密码(如证书导出时未设置密码,则留空即可)。如果您的同一个应用分为不同的版本,您也可以添加 “[多个证书](ios_kb_multiple_certificates.md)”。 34 | 35 | ![ios_create_new_app.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_portal_add_certificate.png) 36 | 37 | 应用信息填好以后,点击页面下方的“创建应用”按钮,会来到“应用详情”页面。这里可以看到从 [Portal](product_kb_portal.md) 申请到的 [AppKey](product_kb_app_key.md)、Secret Key 等。 38 | 39 | >**注**:请妥善保管好您的 AppKey、Secret Key 等,不要泄露给他人。 40 | 41 | ![productpng_portal_copy_app_key.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_copy_app_key.png) 42 | 43 | ###3. 生成 Provisioning Profile 44 | 请参考 [生成 Provisioning Profile](ios_kb_create_provisioning_profile.md) 一文,生成 Provisioning Profile,并导入到 Xcode 中。 45 | 46 | ###4. 运行 Yunba iOS Demo 工程 47 | 48 | **4.1. 打开 YunBaDemo 工程** 49 | 50 | 在 Xcode 中打开 Yunba iOS SDK 中的 Demo 工程“YunBaDemo”。 51 | 52 | ![iospng_demo_file_list.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_demo_file_list.png) 53 | 54 | **4.2. 替换代码中的 AppKey** 55 | 56 | iOS SDK Demo 的代码已经实现了订阅、接收等逻辑,您无需添加任何代码,只需使用您从 Portal 获取到的 Appkey 替换代码中的 Appkey 即可。 57 | ```iOS 58 | [YunBaService setupWithAppkey:AppKey]; // 请替换此处的 AppKey。 59 | ``` 60 | 61 | **4.3. 配置 Bundle ID** 62 | 63 | 在 Xcode 的 General --> Identity 页面,修改 Bundle Identifier 的值,如图所示: 64 | 65 | ![iospng_demo_bundle_identity.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_demo_bundle_identity.png) 66 | 67 | **4.4. 配置 Code Signing** 68 | 69 | 在 Xcode 的 Build Setting --> Code Signing 页面,Code Signing Identity 选择 Automatic,Provisioning Profile 选择之前在步骤 3 中双击导入的 Provisioning Profile。 70 | 71 | ![iospng_demo_code_sign.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_demo_code_sign.png) 72 | 73 | **4.5. 编译** 74 | 75 | 至此,编译运行即可。 76 | 77 | **4.6. 运行** 78 | 79 | App 在真机上运行起来后,可以通过左右拨动,切换到不同的功能展示页面。 80 | 81 | **其中,在 Demo App 内,向右拨动至最后一页,打开 Enable APNs 的开关,才能收到 APNs 的消息。** 82 | 83 | ![iospng_demo_enable_apns.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_demo_enable_apns.png) 84 | 85 | 86 | ###5. 订阅和发布 87 | 88 | 在 App 的首页,最上方如果显示 “Connected”,则表示连上了云巴服务器。 89 | 90 | 此时,填写 Topic 的名称,点击 Subscribe 按钮,即可成功订阅。 91 | 92 | 在官网的 Portal 上,选择对应的应用,点击“发布消息”,即可向特定的 Topic 发消息,您的 iOS App 会收到相应的消息。 93 | 94 | 在 Portal 上发送消息: 95 | 96 | ![productpng_portal_publish_to_topic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_to_topic.png) 97 | 98 | 99 | App 在前台运行时会收到内部消息: 100 | 101 | ![iospng_demo_new_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_demo_new_message.png) 102 | 103 | 104 | App 在后台运行时会收到推送通知: 105 | 106 | ![iospng_demo_bar_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_demo_bar_message.png) 107 | -------------------------------------------------------------------------------- /ios_faq.md: -------------------------------------------------------------------------------- 1 | # iOS SDK 常见问题解答 2 | 3 | 1. **如何实现 iOS 应用退出或者处于后台时可以收到推送消息?** 4 | 5 | 答: 6 | * 需要生成 APNs 证书; 7 | * 在 App 注册 remoteNotification 通知,获取 Device Token,并通过[`storeDeviceToken()`](ios_sdk_api_manual.md#storedevicetoken)函数保存 Device Token 到云巴服务端; 8 | * 通过带有 ApnOption 的`publish2()`、`publish2ToAlias()`或者默认的`publish()`、`publishToAlias()`发送 APNs 消息,该参数设置详见云巴知识库的 [Payload](ios_kb_payload.md) 一文,以及 [iOS 官方文档](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1)。 9 | 10 | >**注**:`publish2()`需要带有 ApnOption 参数才能成功发送 APNs 消息;而`publish()`会发送默认的 APNs 消息。 11 | 12 | --- 13 | 2. **接收的消息,除了基本的内容(Topic 和 Message)还可以传递一些参数信息吗?** 14 | 15 | 答: 开发者可以封装多个数据到 data.msg。 16 | 17 | --- 18 | 3. **ApnOption 的 sound 和 badge 有什么作用?** 19 | 20 | 答: 可在`publish2ToAlias()`、`publish2()`的 ApnOption 参数设置消息通知的方式。 21 | alert 设置消息通知栏的内容;badge 设置角标;sound 设置通知的铃声。 22 | 23 | 具体参考云巴知识库的 [Payload](ios_kb_payload.md) 一文,以及 [iOS 官方文档](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1),或参考 iOS demo 中有关 ApnOption 的设置方法。 24 | 25 | --- 26 | 4. **如何自定义 iOS 推送的铃声?** 27 | 28 | 答: 先将自定义的铃声文件加入你的 Xcode 工程里,然后,在推送的时候指定音频的名称即可。注意使用系统支持的音频格式。 29 | 30 | ```json 31 | { 32 | "aps": { 33 | "alert":"yunba", 34 | "badge":3, 35 | "sound":"bingbong.aiff" 36 | } 37 | } 38 | ``` 39 | 40 | 如使用默认铃声,则为: 41 | ```JSON 42 | "sound":"default" 43 | ``` 44 | 45 | --- 46 | 5. **如何处理 badge?** 47 | 48 | 答: 在推送的时候可通过指定 badge 的值来改变当前的 badge(如上例);通过`[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];`可清除 badge 的值。 49 | 50 | --- 51 | 6. **iOS SDK`subscribe()`的 qosLevel 参数,和 YBPublish2Option 的 qos 这两个参数有什么区别?** 52 | 53 | 答:`subscribe()`的 qos Level 限制该话题下接收到 message 的最大 qos 等级。 例如:当设置`subscribe()`的 qosLevel 为 0,则 qos 为 1 的接收消息会降级到 qos 为 0。详见 [MQTT V3.1 Protocol Specification 54 | ](http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html#subscribe) 和 [QoS](product_kb_qos.md) 的说明。 55 | 56 | --- 57 | 7. **iOS 端怎样设置不接收任何消息?** 58 | 59 | 答: 设置别名为空,并`unsubscribe()`所有 Topic。 60 | 61 | --- 62 | 8. **当同时定义了`publish()`的 data 和 ApnOption 参数中 alert 的 message,消息内容将以哪个为准?** 63 | 64 | 答: 以 alert 的 message 为准。未定义 alert 时,则默认显示`publish()`的 data。 65 | 66 | --- 67 | 9. **iOS 端如何设置通知方式?** 68 | 69 | 答: 上传 APNs 证书;通过 YBPublish2Option 参数的 alert 设置通知栏内容、角标和声音等,具体参考 sdk 中关于[`pushlish2()`](ios_sdk_api_manual.md#publish2)的介绍,也可以下载并参考 iOS demo 中 YBPublish2Option 的设置。 70 | 71 | 完整的设置方法请参考 [iOS 官方文档](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1)。 72 | 73 | --- 74 | 10. **使用苹果电脑来生成 APNs 证书,在双击打开证书文件(*.cer)时,遇到“不能修改“System Roots”钥匙串”的提示** 75 | 76 | 答:在钥匙串访问的界面左侧,选择“登录”(login),将证书文件(*.cer)拖进钥匙列表中即可。 77 | 78 | 79 | --- 80 | 11. **使用 iOS SDK,上传了 APNs 证书,但应用在后台时却收不到 APNs 通知?** 81 | 82 | 答: 83 | * 请确认一下是否在云巴 Portal 的该应用页面下正确地上传了 APNs 证书; 84 | * 确保上传到云巴的证书是和你的 App 关联的有效证书,而且需要带上证书的 RSA 密钥; 85 | * 确保 App 的 provisioning profile 包含这个证书和这个设备; 86 | * Xcode 8 及以上的版本需要在项目的 Capabilities 页面中打开 Push Notification 的按钮(如下图所示); 87 | * 请确认应用是否开启了接收 APNs; 88 | * 请通过查看日志打印或 store Device Token 回调的返回值的方式来确认 Device Token 是否上传成功了; 89 | * 集成 SDK 所使用的 AppKey 是否是 Portal 中该应用的 AppKey; 90 | * 请确认 Xcode 里填入的 bundle id 与在 Apple Portal 上的创建的证书的 bundle id 是否一致; 91 | * 另外还需注意:`publish()` 或 `publish_to_alias()` 会发送默认的 APNs 通知, 92 | 而 `publish2()` 或 `publish2_to_alias()`,则**必须在 opts 里填写 apn_json,才会发送 APNs 通知**。 93 | 94 | ![iospng_xcode_capabilities_enable_push.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_xcode_capabilities_enable_push.png) 95 | 96 | 97 | 最后,如果问题依然没有得到解决,请将您的 Appkey 用私聊或邮件(support@yunba.io)的方式发给我们,我们会尽快协助您找出原因。 98 | 99 | 100 | 101 | --- 102 | 12. **为什么升级 iOS 后,收不到 APNs 了?** 103 | 104 | 答:可能是升级后 Device Token 改变造成的。建议按照苹果官方文档的建议,每次启动应用时检查 Device Token 并发送到服务器。 105 | 106 | > **苹果官方文档**:The device token is your key to sending push notifications to your app on a specific device. Device tokens can change, so your app needs to reregister every time it is launched and pass the received token back to your server. If you fail to update the device token, remote notifications might not make their way to the user’s device. Device tokens always change when the user restores backup data to a new device or computer or reinstalls the operating system. When migrating data to a new device or computer, the user must launch your app once before remote notifications can be delivered to that device. 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /ios_kb_apns_implementation.md: -------------------------------------------------------------------------------- 1 | # 如何通过云巴实现 APNs 推送 2 | 3 | ## 概述 4 | 熟悉 iOS 开发的朋友们都知道,实现 APNs 推送的前提是:告诉苹果的 Push 服务器推送消息的去向——即,发往哪个应用(即应用证书)、哪台机器(即 Device Token)。 5 | 6 | 因而,[云巴的 iOS 消息推送](ios_kb_ios_push.md) 也有同样必不可少的前提步骤:上传 APNs 推送证书到云巴 Portal 相应的应用界面、获取 Device Token 并保存到云巴服务器。 7 | 8 | ## 详细步骤 9 | 如果在集成云巴 iOS SDK 同时,希望激活 APNs 推送功能,具体应该怎么做呢? 10 | 11 | - [生成 APNs 证书](ios_kb_create_apns_certificate.md)。 12 | - 打开 [云巴官方网站](https://yunba.io),点击右上角的“注册”按钮创建云巴开发者账号。 13 | - 在 [Portal 上创建新应用](product_kb_portal.md#如何在云巴-portal-上创建新应用),并**上传开通了 Push Notification 功能的 iOS 开发或生产证书**。 14 | - 打开 [云巴开发者页面](https://yunba.io/downloads/),下载最新版本的 iOS SDK,并导入到 App 的 Xcode 工程中。 15 | - [生成 Provisioning Profile](ios_kb_create_provisioning_profile.md),并导入到 Xcode 中。 16 | - 配置 Xcode 中的 Bundle ID 和 Code Signing。 17 | - 代码处理(详见 iOS SDK 中的 YunBaDemo): 18 | - 添加头文件,引入YunBaService.h。 19 | - 通过[`setupWithAppkey`](ios_sdk_api_manual.md#setup)初始化。使用您从 Portal 获取到的 Appkey 替换初始化函数 中的 Appkey。 20 | - 通过[`subscribe`](ios_sdk_api_manual.md#subscribe)订阅 Topic。 21 | - 在默认消息中心添加监听消息及处理代码。 22 | - 通过 registerForRemoteNotificationTypes 注册并获取 Device Token。如果注册成功,再通过 didRegisterForRemoteNotificationsWithDeviceToken **将 Device Token 保存到云巴服务器**;如果注册失败,didFailToRegisterForRemoteNotificationsWithError 会被调用,可根据 NSError 的描述排查出错原因。 23 | - 处理收到消息后的回调。 24 | - 处理好 App 的其他代码逻辑后,便可以通过 [Portal 发送消息](product_kb_portal.md#利用云巴-portal-发布消息),进行测试了。 25 | 26 | 如下图所示,详细步骤可参考 [运行 Yunba iOS Demo](ios_demo_quick_start.md) 一文。 27 | 28 | 29 | ![productpng_kb_apns.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_apns.png) 30 | -------------------------------------------------------------------------------- /ios_kb_cfg_remote_notification.md: -------------------------------------------------------------------------------- 1 | # 配置远程通知服务 2 | 3 | 本文结合云巴 iOS SDK 的使用,翻译了 iOS 官方开发文档的 [Configuring Remote Notification Support](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/HandlingRemoteNotifications.html#//apple_ref/doc/uid/TP40008194-CH6-SW1) 章节的部分内容。 4 | 5 | 由于专业术语的翻译可能会引起理解上的偏差,请以 iOS 官方开发文档为准。文档如有任何谬误不妥之处,欢迎指正。 6 | 7 | 借助远程通知服务,可以向用户即时推送最新的消息,且无需担心用户是否正在使用该应用。远程通知功能的大部分程序都由云巴服务器进行处理,应用方面需要做如下配置: 8 | 9 | - 打开应用的推送通知(Push Notification)功能; 10 | - 在应用的启动代码中注册 APNs; 11 | - 实现远程通知的处理代码; 12 | 13 | ## 打开推送通知功能 14 | 15 | 要处理远程通知,应用必须先取得与 APNs 通讯的权限。在 Xcode 工程的 Capability 面板中添加这一功能权限。 16 | 17 | **流程** 18 | 19 | - 在工程导航中选择你的工程; 20 | - 在编辑器的 TARGETS 中选择你的应用; 21 | - 点击右侧的 Capability 标签页; 22 | - 打开推送通知(Push Notification)功能权限; 23 | 24 | 按上面的做法,Xcode 就会把所需的权限加进你的工程中。 25 | 26 | 如果未添加相应的功能权限,应用会在应用商店审核阶段被驳回。测试期间,如果没有相应的权限,注册 APNs 时会返回错误。 27 | 28 | 29 | ## 通过注册接受远程通知 30 | 31 | App 每次启动的时候,都必须注册 APNs。大致上这分为两步: 32 | 33 | 1. 获取 App 的 Device Token 34 | 2. 将 Device Token 通过 API 发送到云巴的服务器 35 | 36 | 不同设备不同 App 的 Device Token 都是唯一的。云巴的 SDK 通过获得 Device token 来与 App 进行 APNs 通信,每一个 APNs data 都包含了 Device Token 作为识别。 37 | 38 | 永远不要储存 Device Token,需要的时候再将它从系统中获取,通过云巴 SDK 进行上传。虽然 Device Token 对每个设备每个 App 都是唯一的,但是它随时可能改变。它有可能在任何时候发生变化:也许是用户恢复备份时、用户把 App 安装到一个新的设备时、用户重装系统时等等,但是能够保障其唯一性。从系统获取 Device Token(而不是从储存的 Device Token 获取)才能保证 APNs 的正常使用。另外,如果 Device Token 没有变化,获取过程是很快的,并不会导致任何明显的耽误。 39 | 40 | **重要:当 Device Token 发生变化时,用户只有启动一次应用才能再次接收到 APNs 通知。** 41 | 42 | 43 | ## 获取 Device Token 44 | 45 | 你需要通过调用 `UIApplication registerForRemoteNotifications` 函数来获取 Device Token。推荐的做法是将调用这个函数加入你正常启动 App 需要的程序之中。第一次调用这个函数时,App 会向 APNs 请求 Device Token。初始化完成后,App 只在 Device Token 发生变化时才会与 APNs 连接。其他时候,获取 Device Token 都非常快。 46 | 47 | 48 | The app object notifies its delegate asynchronously upon the successful or unsuccessful retrieval of the device token. You use these delegate callbacks to process the device token or to handle any errors that arose. You must implement the following delegate methods to track whether registration was successful: 49 | 50 | 51 | 当 App 获取 Device Token (不管是成功还是失败),app delegate 的对应代理方法都会被同步调用。需使用这些代理方法回调来处理 Device Token 或者处理 Errors。你需要实现下面的代理方法来追溯注册的成败: 52 | 53 | - 使用 `application:didRegisterForRemoteNotificationsWithDeviceToken:` 来获得 Device Token 并上传到云巴服务器。 54 | - 使用 `application:didFailToRegisterForRemoteNotificationsWithError:` 对错误进行回应。 55 | 56 | **注意:如果 Device Token 发生了变化且你的 App 正在运行,App 会再次调用相对应的代理方法来告诉你 Device Token 发生了变化。** 57 | 58 | 下面的代码演示了如何获取 Device Token, App 代理调用 `registerForRemoteNotifications` 方法作为初始化调用。当获取到 Device Token 后,调用 `application:didRegisterForRemoteNotificationsWithDeviceToken:` 方法让你有机会将它上传到云巴的服务器。如果在此期间发生了任何错误,App 会暂时禁用所有远程推送相关的特性,直到收到正确的 Device Token 为止。 59 | 60 | - (void)applicationDidFinishLaunching:(UIApplication *)app { 61 | // Configure the user interactions first. 62 | [self configureUserInteractions]; 63 | 64 | // Register for remote notifications. 65 | [[UIApplication sharedApplication] registerForRemoteNotifications]; 66 | } 67 | 68 | // Handle remote notification registration. 69 | - (void)application:(UIApplication *)app 70 | didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken { 71 | // Forward the token to your server. 72 | [self enableRemoteNotificationFeatures]; 73 | [self forwardTokenToServer:devTokenBytes]; 74 | } 75 | 76 | - (void)application:(UIApplication *)app 77 | didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 78 | // The token is not currently available. 79 | NSLog(@"Remote notification support is unavailable due to error: %@", err); 80 | [self disableRemoteNotificationFeatures]; 81 | } 82 | 83 | func application(_ application: UIApplication, 84 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 85 | // Configure the user interactions first. 86 | self.configureUserInteractions() 87 | 88 | // Register with APNs 89 | UIApplication.shared.registerForRemoteNotifications() 90 | } 91 | 92 | // Handle remote notification registration. 93 | func application(_ application: UIApplication, 94 | didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data){ 95 | // Forward the token to your server. 96 | self.enableRemoteNotificationFeatures() 97 | self.forwardTokenToServer(token: deviceToken) 98 | } 99 | 100 | func application(_ application: UIApplication, 101 | didFailToRegisterForRemoteNotificationsWithError error: Error) { 102 | // The token is not currently available. 103 | print("Remote notification support is unavailable due to error: \(error.localizedDescription)") 104 | self.disableRemoteNotificationFeatures() 105 | } 106 | 107 | 如果蜂窝数据或 Wi-Fi 无法连接,不管是 `application:didRegisterForRemoteNotificationsWithDeviceToken:` 还是 `application:didFailToRegisterForRemoteNotificationsWithError:` 都不会被调用。当 Wi-Fi 连接上时,也经常会发生因端口配置而无法连接到 APNs 的情况。这种情况下,用户可以转移到其他不会阻拦请求端口 Wi-Fi 网络环境下。而蜂窝数据的情况,用户同样可以等到蜂窝数据服务能使用为止。 108 | 109 | 110 | 111 | ## 处理远程通知 112 | 113 | User Notification 框架把所有涉及到本地和远程通知相关的操作代码都集中到了一个地方。 114 | 115 | 具体来说,可以用同样的方法处理下面的事情: 116 | 117 | - 如果应用在前台运行,可以直接收通知,并静默该通知; 118 | - 如果应用在后台,且未运行: 119 | - 可以在用户选择了一个与通知有关的自定义操作时做出响应; 120 | - 可以在用户忽略掉通知,或者登录了应用时做出响应; 121 | 122 | 除了借助 User Notification 框架提供的方法来处理通知以外,应用还可以通过它的 app delegate 接收整个远程通知的负载。当一个远程通知到达时,如果应用在后台,系统会正常处理用户的交互。系统也会把通知的负载发给 iOS 的 app delegate 的 `application:didReceiveRemoteNotification:fetchCompletionHandler:` 方法。你可以用这个方法检测负载,并执行相应的操作。例如,收到一个静默的远程通知后,可以执行应用更新的下载。 123 | 124 | 有关如何使用 User Notifications 框架的方法处理通知,详见 [Responding to the Delivery of Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/SchedulingandHandlingLocalNotifications.html#//apple_ref/doc/uid/TP40008194-CH5-SW14)。 125 | 126 | 有关如何在 app delegate 里处理通知,详见 [UIApplicationDelegate Protocol Reference](https://developer.apple.com/reference/uikit/uiapplicationdelegate) 或 [NSApplicationDelegate Protocol Reference](https://developer.apple.com/reference/appkit/nsapplicationdelegate)。 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /ios_kb_create_apns_certificate.md: -------------------------------------------------------------------------------- 1 | # 生成 APNs 证书的步骤 2 | 3 | 4 | ## 准备工作 5 | 6 | 1. 制作 APNs 证书时,需要一个 CSR(CertificateSigningRequest.certSigningRequest)文件,来使新生成的推送证书与私钥相匹配。CSR 文件的新建步骤请参考 [新建 CSR 文件的步骤](ios_kb_create_csr_file.md)。 7 | 8 | 2. 如果您还没有创建 App ID,请参考 [新建 App ID 的步骤](ios_kb_create_app_id.md) 一文,创建一个 App ID,并为 App 开启 Push Notification 功能。如果已经创建过了,可跳过此步,只需在设置页面中确认该 App 已开启了 Push Notification 功能即可。**注意,这里的 App ID 不可以使用通配符。** 9 | 10 | ## 详细步骤 11 | 12 | 1. 打开 Apple 开发者网站的 [证书管理界面](https://developer.apple.com/account/ios/certificate),并用您的苹果开发者账号登录; 13 | 14 | 2. 点击新建证书的按钮; 15 | 16 | ![iospng_cert_creat_certificate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_creat_certificate.png) 17 | 18 | 3. 选择新建证书的类型(开发或者生产推送环境); 19 | 20 | ![iospng_cert_choose_type.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_choose_type.png) 21 | 22 | >**注**:如果你的系统中没有中间签名证书,则需要下载并安装到你的系统中: 23 | 24 | ![iospng_cert_before_create_certificate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_before_create_certificate.png) 25 | 26 | 4. 为证书选择对应需要推送功能的 App ID,点击继续; 27 | 28 | ![iospng_cert_choose_appid.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_choose_appid.png) 29 | 30 | 5. 在界面上点击 Continue 按钮后,请上传前文提到的 CSR 证书。(CSR 文件的新建步骤请参考 [新建 CSR 文件的步骤](ios_kb_create_csr_file.md))。 31 | 32 | ![iospng_cert_upload_csr.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_upload_csr.png) 33 | 34 | 35 | 6. 点击 Generate 按钮生成 APNs 证书,然后点击 Download 按钮下载即可,点击 Done 按钮完成整个操作。 36 | 37 | ![iospng_cert_download_certifcate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_download_certifcate.png) 38 | 39 | 7. 证书下载后,双击打开证书文件(*.cer)使之加入到钥匙串中。如遇到“不能修改‘System Roots’钥匙串”的警告,请参考 [相关文档](ios_faq.md#10) 解决。 40 | 41 | 42 | 8. 将证书导出为“个人信息交换(.p12)”格式。如遇到“个人信息交换(.p12)”的选项为灰色不可选状态,请您再次确认您的 APNs 证书是否是严格按照上述步骤进行生成的,建议删除重新做一次。 43 | 44 | ![iospng_cert_export_certificate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_export_certificate.png) 45 | 46 | 导出时可以添加自定义密码以提高安全性: 47 | 48 | ![iospng_cert_p12_password.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_p12_password.png) 49 | 50 | 至此,APNs 证书生成完毕。 51 | 52 | 在 Yunba 的 Portal 页面创建新应用时,在 iOS 开发/生产证书处上传这份个人信息交换(.p12)即可。 53 | -------------------------------------------------------------------------------- /ios_kb_create_app_id.md: -------------------------------------------------------------------------------- 1 | # 新建 App ID 的步骤 2 | 3 | 4 | 5 | 1. 打开 Apple 开发者网站的 [Identifer 管理界面](https://developer.apple.com/account/ios/identifiers/bundle/bundleList.action),并用您的苹果开发者账号登录; 6 | 7 | 2. 点击新建 ID 的按钮; 8 | 9 | ![iospng_cert_new_appId.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_new_appId.png) 10 | 11 | 3. 按实际情况填写 App ID 的描述,以及具体的 Bundle ID; 12 | 13 | ![iospng_cert_enter_name.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_enter_name.png) 14 | 15 | 4. 按实际需要,为 App 开启相应的 service。例如,Push Notification 功能。勾选后,点击 Continue 按钮; 16 | 17 | ![iospng_cert_enable_push_service.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_enable_push_service.png) 18 | 19 | 5. 信息确认完毕后,点击 Submit、Done 按钮。
至此,App ID 创建完毕,如需修改 App ID 的描述或服务配置,可在 App IDs 界面的右侧选择相应的 App ID,点击信息页面底部的 Edit 按钮进行修改。 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ios_kb_create_csr_file.md: -------------------------------------------------------------------------------- 1 | # 新建 CSR 文件的步骤 2 | 3 | 4 | 1. 打开钥匙串访问 5 | 6 | ![iospng_cert_open_key_chain.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_open_key_chain.png) 7 | 8 | 2. 申请创建 CSR 文件 9 | 10 | ![iospng_cert_creat_csr.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_creat_csr.png) 11 | 12 | 3. 输入邮箱等信息后保存 CSR 文件(CertificateSigningRequest.certSigningRequest)到本地磁盘即可。 13 | 14 | ![iospng_cert_save_csr.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_save_csr.png) 15 | -------------------------------------------------------------------------------- /ios_kb_create_provisioning_profile.md: -------------------------------------------------------------------------------- 1 | # 生成 Provisioning Profile 2 | 3 | 本节以“开发”类型的 Provisioning Profile 为例,介绍如何生成 Provisioning Profile,并导入 Xcode 中。 4 | 5 | 1. 打开 Apple 开发者网站的 [Provisioning Profiles 管理界面](https://developer.apple.com/account/ios/profile/profileList.action),并用您的苹果开发者账号登录。 6 | 如图所示,界面上列出了现有的 Provisioning Profiles。 7 | 8 | ![iospng_cert_provision_all.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_provision_all.png) 9 | 10 | 2. 点击右上角的新建按钮,选择 Profile 的类型,并点击 Continue 按钮。 11 | 12 | ![iospng_cert_provision_type.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_provision_type.png) 13 | 14 | 3. 选择要创建 Provisioning Profile 的 App ID。 15 | 16 | ![iospng_cert_provision_appId.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_provision_appId.png) 17 | 18 | 4. 选择开发者证书。 19 | 20 | ![iospng_cert_provision_certificate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_provision_certificate.png) 21 | 22 | 5. 选择允许哪些设备使用该 Provisioning Profile。一般情况下,全选即可。 23 | 24 | ![iospng_cert_provision_device.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_provision_device.png) 25 | 26 | 6. 为该 Provisioning Profile 命名,并点击 Generate,即可生成。 27 | 28 | ![iospng_cert_provision_name.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_provision_name.png) 29 | 30 | 7. 点击 Download,下载到本地。 31 | 32 | ![iospng_cert_provision_done.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_provision_done.png) 33 | 34 | 8. 双击 Provisioning Profile 文件,即可将其导入到 Xcode 中。 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ios_kb_ios_10_impact.md: -------------------------------------------------------------------------------- 1 | # iOS 10 更新的影响 2 | 3 | Apple 发布 iOS 10,带来了一系列的 [新特性](https://developer.apple.com/library/content/releasenotes/General/WhatsNewIniOS/Articles/iOS10.html)。 4 | 在消息推送方面,引入了 User Notifications 框架进行本地和远程通知的传送和处理。 5 | 6 | 本文阐述这次更新对云巴 iOS 产品的影响。 7 | 8 | ## 云巴 iOS SDK Demo 出现 Warning 9 | 10 | 由于 iOS 10 舍弃了部分原有的 API,用户在运行云巴 iOS Demo(1.7.3)时,会出现 Warning。 11 | 12 | 例如,授权接收通知的逻辑(authorization API)被舍弃,需要使用 UNUserNotificationCenter。 13 | 14 | 我们针对 iOS 的不同版本对云巴 iOS Demo 中的`registerRemoteNotification`作了修改(详见下方代码)。为了兼容旧的版本,Demo 中的 Warning 暂时无法全部消除。 15 | 16 | 另:经测试,在 iOS 升级为 10 以后,云巴 iOS Demo 不进行任何修改,使用原有 API 也可以正常编译运行、正常接收推送。**部分设备升级后收不到 APNs,可能是 Device Token 改变引起的。请参考 [iOS FAQ 第 12 条](https://yunba.io/docs/ios_faq#12)**。 17 | 18 | ```objective-c 19 | @import UserNotifications; 20 | ``` 21 | 22 | 23 | ```objective-c 24 | - (void)registerRemoteNotification { 25 |    // register for remote notification(APNs)     注册 APNs,申请获取 device token 26 | 27 | if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) 28 | { 29 | UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter]; 30 | [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) { 31 | granted ? NSLog(@"author success!") : NSLog(@"author failed!"); 32 | }]; 33 | [[UIApplication sharedApplication] registerForRemoteNotifications]; 34 | } 35 | else if ([[[UIDevice currentDevice] systemVersion] floatValue] < 10.0 && 36 | [[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) 37 | { 38 | [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings 39 | settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]]; 40 | [[UIApplication sharedApplication] registerForRemoteNotifications]; 41 | } 42 | else 43 | { 44 | [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; 45 | } 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /ios_kb_ios_push.md: -------------------------------------------------------------------------------- 1 | # 云巴 iOS 消息推送 2 | 3 | 如下图所示,客户端集成了云巴的 iOS SDK, 4 | 服务端通过云巴的 SDK 向 iOS 设备发消息。 5 | 6 | 一方面,云巴的服务器会负责向苹果的服务器发送 APNs 的消息; 7 | 另一方面,当应用在前台运行时,云巴会通过与 App 建立的长连接,直接推送内部消息。 8 | 9 | ![iospng_kb_push_apns_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_kb_push_apns_message.png) 10 | 11 | 12 | 通过云巴的 SDK 向 iOS App 推送消息,App 在不同状态下的消息接收情况如下: 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 |
App 状态一直 Online服务端推送了消息后,设备才 Online一直 Offline
运行在前台(1) iOS 系统不会显示 APNs 消息通知,但 App 内会有 APNs 的回调;

26 | (2) 云巴服务器与 App 建立了长连接,App 会收到云巴服务器直接发来的消息。
连网后,情况与左侧一列的描述基本一致。

唯一区别是:
设备不在线时,向 APNs 推送多条通知,在上线后只会收到最后一条。
收不到消息。
运行在后台(1) App 会收到并显示 APNs 消息通知;

36 | (2) 打开 App 时,如前所述,App 会连上云巴服务器,收到服务器直接发来的消息。
39 | 40 | * 集成 APNs 41 | 42 | 云巴 SDK 集成了 APNs,开发者无需开发与 APNs 对接的模块,也不必自己负责 Device Token 的更新,一切交给云巴。 43 | 44 | * 确保消息的送达 45 | 46 | 众所周知,APNs 并不保证消息的送达。 47 | 而云巴 SDK 支持 [离线消息](product_kb_offline_message.md) 的功能,可保证消息送达客户端。 48 | 49 | 在推送消息时,如果客户端当前不在线,消息将暂存在云巴服务器上(多达 50 条,长达 15 天)。 50 | 当客户端上线并成功连接到云巴的服务器后,服务器会把离线消息推送给该客户端。客户端成功接收后,服务器才会删除保存的离线消息。 51 | -------------------------------------------------------------------------------- /ios_kb_multiple_certificates.md: -------------------------------------------------------------------------------- 1 | # 多证书 2 | 3 | ## 场景 4 | 5 | 某些 iOS 应用在发布时可能会分为不同的版本,如打车软件的司机版和乘客版、交易软件的买家版和卖家版。 6 | 开发者往往希望在发推送时,不同版本的应用都能同时收到。 7 | 8 | 在这种场景下,可以使用云巴提供的 “多证书” 功能。 9 | 10 | ## 使用对象 11 | 12 | **“多证书” 针对的对象是:同一个 [AppKey](product_kb_app_key.md)、不同版本的 iOS 应用。** 13 | 14 | ## 如何使用 15 | 16 | “多证书” 的使用很简单,只需在 [Portal](product_kb_portal.md) 创建应用时上传多个证书即可。 17 | 上传的界面如下图所示。 18 | 19 | 20 | 云巴会自动检测哪个证书对应哪个设备,确保消息送达所有的订阅设备。 21 | 22 | 23 | 注意:*如果您使用了生产和开发证书两个证书来进行推送:云巴会根据 SDK 上报的状态自动选择生产或者开发证书,也就是说,消息会推送给使用开发或生产证书的所有设备。如果您只需要发送给某一个证书下的 App,建议使用测试的 Topic,或暂时删除另一个证书。* 24 | ![iospng_protal_multi_certificate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_protal_multi_certificate.png) -------------------------------------------------------------------------------- /ios_kb_payload.md: -------------------------------------------------------------------------------- 1 | # 远程通知的负载部分 2 | 3 | 为了便于大家理解 APNs 的 Payload 的用法,本文翻译了 iOS 官方开发文档的 The Remote Notification Payload 章节的部分内容。 4 | 5 | 然而原文链接已失效,iOS 官方已经将文档更新为 [Payload Key Reference](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1) 6 | 7 | 本文尚未比对哪些内容有更新,仅供参考。请以 iOS 官方最新开发文档为准。文档如有任何谬误不妥之处,欢迎指正。 8 | 9 | 每个远程推送通知都带有一个负载(Payload)。其内容包括系统提醒(alert)用户的方式以及任意的自定义数据。负载大小的上限取决于你使用的 API。如果使用的是 HTTP/2 的服务提供商的 API,最多允许 4096 字节;如使用 Legacy binary interface,则最多 2048 字节。如果内容超出了这个最大值,会被 APNs 服务器拒收。 10 | 11 | ## 负载的键 12 | 13 | 开发者需为每一个通知组一个 JSON 的字典对象(遵循 [RFC 4627](http://www.ietf.org/rfc/rfc4627.txt))。该字典内必须包含另一个键名为 aps 的字典。这个 aps 字典可以包含一个或多个属性,来指定用户通知的类型。如下: 14 | 15 | * 向用户显示的提醒消息 16 | * 用于显示在 App 图标右上角的徽标(badge)数字 17 | * 用来播放的铃声 18 | 19 | 如需实现静默远程通知,需在 Info.plist 文件中,将 remote-notification 值加进 [UIBackgroundModes](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW22) 数组中。 20 | 21 | 收到通知时,如果目标 App 当前未运行,则提醒消息、铃声或 badge 数值就会生效;如果 App 正在运行,系统则会以 [NSDictionary](https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/index.html#//apple_ref/occ/cl/NSDictionary) 对象的形式把通知传给 App Delegate。其字典包含对应的 Cocoa property-list 对象(外加 [NSNull](https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSNull_Class/index.html#//apple_ref/occ/cl/NSNull))。 22 | 23 | 服务商可以在苹果保留的 aps 字典以外指定自定义的负载值。自定义的值必须遵循 JSON 的结构,并使用原始的类型:字典(对象)、数组、字符串、数字和布尔类型。自定义负载的内容中不应包含客户信息(或其他敏感数据)。相反,应该用它来做些诸如(为用户界面)设置上下文或内部量度(Metrics)的事情。例如,自定义负载的值可能是 IM 客户端应用的一个会话标识符,或是服务商发送通知的时间戳。任何与提醒消息有关的操作都不应该具有破坏性——比如不应该删除设备上的数据。 24 | 25 | **重要提醒**:APNs 只会 “尽力” 推送通知,并不保证送达。它只是用来通知用户 App 当前有新的可用内容,而并不应该用来传递数据本身。 26 | 27 | 表格 5-1 列出了 aps 负载的键和预期的值。 28 | 29 | **表格 5-1 aps 字典的键(Key)和值(Value)** 30 | 31 | | Key | Value type | 注解 | 32 | |:----|:----|:----| 33 | | alert | string 或 dictionary | 如果包含这一属性,那么系统会根据用户的设置,显示标准形式或是横幅(banner)形式的通知。alert 的值可以是 string 或 dictionary 类型。
* 如果指定的是 string,那它就是通知消息的内容,通知带有 Close 和 View 两个按钮。用户按下 View,则会启动 App。
* 如果是 dictionary,请参考表格 5-2 查看该字典的键的描述。
JSON 的 \U 不支持。请将实际的 UTF-8 的字符放到 alert 文本内。 | 34 | | badge | number | App 图标的徽标上显示的数字。如果不带该属性,则当前徽标值不变。将该属性的值设为 0 可清除徽标。 | 35 | | sound | string | App bundle 或 App data container 的 Library/Sounds 文件夹内的音频文件的名称。这里的音频会在收到通知时播放。如果音频文件不存在或音频的值为 default,则会播放默认的音频。该音频必须是系统兼容的音频格式,详见 [Preparing Custom Alert Sounds](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/SupportingNotificationsinYourApp.html#//apple_ref/doc/uid/TP40008194-CH4-SW10) 章节。 | 36 | | content-available | number | 将该键设为 1 则表示有新的可用内容。带上这个键值,意味着你的 App 在后台启动了或恢复运行了,[application:didReceiveRemoteNotification:fetchCompletionHandler:](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:fetchCompletionHandler:) 被调用了。 | 37 | | category | string | 为了定义一些自定义的动作,你需要创建 [UIMutableUserNotificationCategory](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIMutableUserNotificationCategory_class/index.html#//apple_ref/occ/cl/UIMutableUserNotificationCategory) 对象。而这个 category 的值即为该对象的 identifier 属性。参考 [Configuring Categories and Actionable Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/SupportingNotificationsinYourApp.html#//apple_ref/doc/uid/TP40008194-CH4-SW26) 章节,了解更多自定义动作的用法。| 38 | 39 | 表格 5-2 列出了 alert 字典的键和预期的值。 40 | 41 | **表格 5-2 alert 属性的子属性** 42 | 43 | | Key | Value type | 注解 | 44 | |:----|:----|:----| 45 | | title | string | 通知的意图。Apple Watch 会将之显示为通知界面的一部分。这个字符串必须简明扼要,易于快速理解。这个键是在 iOS 8.2 中加入的。| 46 | | body | string | 通知消息的内容。| 47 | | title-loc-key | string 或 null | Localizable.strings 文件中的标题字符串的键,用于描述当前的本地化参数。字符串可以以 %@ 或 %n$@ 的格式来指定 title-loc-args 数组中的变量。参见 [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9) 章节。这个键是在 iOS 8.2 中加入的。| 48 | | title-loc-args | array of strings 或 null | 待显示于 title-loc-key 中的格式化字符处的字符串变量的值。参见 [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9) 章节。这个键是在 iOS 8.2 中加入的。 | 49 | | action-loc-key | string 或 null | 如果指定了一个字符串,那么系统会显示一个带有 Close 和 View 按钮的通知。这个字符串是获取本地化字符串的一个索引值,来取代右边按钮上的 View 字眼。参见 [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9) 章节。| 50 | | loc-key | string | 位于 Localizable.strings 文件中的一个通知消息的字符串的键(由用户设置的语言偏好所决定)。字符串可以以 %@ 或 %n$@ 的格式来指定 loc-args 数组中的变量。参见 [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9) 章节。| 51 | | loc-args | array of strings | 待显示于 loc-key 中的格式化字符处的字符串变量的值。参见 [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9) 章节。 | 52 | | launch-image | string | App bundle 中的某张图片的文件名。文件扩展名可有可无。用于用户按下某动作按钮或滑动滑条运行后的启动图片。如未指定,则系统要么使用之前的截图,要么使用 App 的 Info.plist 文件中的 UILaunchImageFile 键指定的图片,亦或是 Default.png。这个属性是在 iOS 4.0 中加入的。| 53 | 54 | >**注**:如果想让设备 “原封不动” 地展现一个带有 Close 和 View 的通知消息,那就直接指定通知的内容。如果只有一个 body 属性,就不要把 alert 指定成字典。 55 | 56 | ## 配置静默通知 57 | 58 | aps 字典也可以包含 content-available 属性。其值为 1 时,远程通知会变为静默通知。收到静默通知时,iOS 会在后台唤醒你的 App。之后,App 便可以从你的服务器获取新数据或进行一些后台的信息处理。 59 | 用户不会立刻察觉到静默通知所做的改动,下次打开 App 时才会发现。 60 | 61 | 使用静默通知时,需确保 aps 字典中不存在通知、声音或徽标的负载。否则,错误配置的通知可能会导致通知无法送达 App 的后台,或者是没有做到静默。 62 | 63 | ## 本地化格式字符串 64 | 略。 65 | 66 | ## JSON 负载的例子 67 | 68 | 下面给出几个负载的例子,来解释表格 5-1 中的属性的实际应用。键名带有 acme 的属性是自定义负载数据的例子。 69 | 70 | >**注**:为了便于阅读,示例中加入了空格和换行。在实际使用时,去掉这些空格和换行符,可以减小负载体积、提高网络性能。 71 | 72 | ### 例 1 73 | 下面的负载是一个 aps 字典,带有一个简单的推荐样式的通知消息,有默认的通知按钮(Close 和 View)。通知的值使用的是字符串,而不是字典。该负载还包含一个自定义的数组的属性。 74 | ```JSON 75 | { 76 | "aps" : { "alert" : "Message received from Bob" }, 77 | "acme2" : [ "bang", "whiz" ] 78 | } 79 | ``` 80 | 81 | ### 例 2 82 | 示例中的负载使用如下的 aps 字典来让设备显示出一个左边是 Close 按钮、右边是一个用本地化语言描述的某个 “动作” 按钮的通知。在本例中,PLAY 作为一个索引,用于从 Localizable.strings 文件中取出当前语言对应的描述词语。该 aps 字典还会将 App 的徽标值设为 5。在 Apple Watch 中,title 键用于通知用户当前有新的请求。 83 | ```JSON 84 | { 85 | "aps" : { 86 | "alert" : { 87 | "title" : "Game Request", 88 | "body" : "Bob wants to play poker", 89 | "action-loc-key" : "PLAY" 90 | }, 91 | "badge" : 5 92 | }, 93 | "acme1" : "bar", 94 | "acme2" : [ "bang", "whiz" ] 95 | } 96 | ``` 97 | 98 | ### 例 3 99 | 本例中的负载描述的通知消息带有 Close 和 View 按钮。App 图标的徽标值会被设为 9。另外,在收到通知时,会播放指定的预置的音频。 100 | ```JSON 101 | { 102 | "aps" : { 103 | "alert" : "You got your emails.", 104 | "badge" : 9, 105 | "sound" : "bingbong.aiff" 106 | }, 107 | "acme1" : "bar", 108 | "acme2" : 42 109 | } 110 | ``` 111 | 112 | ### 例 4 113 | 下面的例子使用 alert 字典的子属性 loc-key 和 loc-args 来从 App bundle 中获取格式化的本地字符串来替代相应位置的变量字符串的值(loc-args)。该负载还指定了一个自定义的音频以及一个自定义的属性。 114 | ```JSON 115 | { 116 | "aps" : { 117 | "alert" : { 118 | "loc-key" : "GAME_PLAY_REQUEST_FORMAT", 119 | "loc-args" : [ "Jenna", "Frank"] 120 | }, 121 | "sound" : "chime.aiff" 122 | }, 123 | "acme" : "foo" 124 | } 125 | ``` 126 | 127 | ### 例 5 128 | 本例的负载使用 category 键来指定一组通知的动作。 129 | ```JSON 130 | { 131 | "aps" : { 132 | "category" : "NEW_MESSAGE_CATEGORY", 133 | "alert" : { 134 | "body" : "Acme message received from Johnny Appleseed", 135 | "action-loc-key" : "VIEW" 136 | }, 137 | "badge" : 3, 138 | "sound" : "chime.aiff" 139 | }, 140 | "acme-account" : "jane.appleseed@apple.com", 141 | "acme-message" : "message123456" 142 | } 143 | ``` 144 | -------------------------------------------------------------------------------- /ios_kb_provider_api.md: -------------------------------------------------------------------------------- 1 | # APNs Provider API 2 | 3 | 这篇翻译对应 Apple 2016-03-21 更新的 APNs Provider API 一文。 4 | 5 | 该文档于 2016-9-20 更新为:[Communicating with APNs](https://developer.apple.com/library/prerelease/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1) 6 | 7 | 请以官方开发文档为准。文档如有任何谬误不妥之处,欢迎指正。 8 | 9 | 借助苹果推送通知服务的 APNs Provider API 可以向你的 iOS、tvOS、OS X、苹果手表(通过 iOS)发送远程通知。这个 API 基于 HTTP/2 网络协议。每次的数据来往都始于一个 POST 请求,带有一个 JSON 负载,由你从你的 Provider 的服务器发往 APNs。之后,APNs 会把通知发给你的某个特定用户机器的 App。 10 | 11 | 在 [App Distribution Guide](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40012582) 里的 [Creating a Universal Push Notification Client SSL Certificate](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html#//apple_ref/doc/uid/TP40012582-CH26-SW11) 章节,介绍过如何获取 APNs 证书。 12 | APNs 证书让你可以连接到 APNs 的生产或开发环境。 13 | 14 | 你可以用你的 APNs 证书向你的主应用发通知,通过 bundle ID 来定位你的应用,也可以向附属的苹果手表应用、或该应用后台的 VoIP 服务发通知。使用证书的(1.2.840.113635.100.6.3.6)扩展来确定你的推送的 topic。 15 | 例如,你的应用的 bundle ID 是 com.yourcompany.yourexampleapp,你可以在证书中指定如下的 topics: 16 | ``` 17 | Extension ( 1.2.840.113635.100.6.3.6 ) 18 | Critical NO 19 | Data com.yourcompany.yourexampleapp 20 | Data app 21 | Data com.yourcompany.yourexampleapp.voip 22 | Data voip 23 | Data com.yourcompany.yourexampleapp.complication 24 | Data complication 25 | ``` 26 | 27 | ## Connections 28 | 29 | 发推送通知的第一步是与相应的 APNs 服务器建立连接: 30 | * 开发服务器:api.development.push.apple.com:443 31 | * 生产服务器:api.push.apple.com:443 32 | 33 | > 34 | 注意:与 APNs 通信时,你也可以选择 2197 端口。例如,如果你希望 APNs 的信息能跨越防火墙进来,而其他 HTTPS 的信息进不来的话,就可以这么用。 35 | 36 | 在与 APNs 服务器建立连接时,服务提供商必须支持 TLS 1.2 或更高的版本。此外,连接必须通过你的服务提供商的客户端证书进行授权,这个证书是你从开发者中心获取到的,在 [Creating a Universal Push Notification Client SSL Certificate](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html#//apple_ref/doc/uid/TP40012582-CH26-SW11) 章节里有介绍。 37 | 38 | 在每个与 APNs 服务器建立的连接上,可以同时有多个“流”(每个多路复用的请求响应称为一个“流”)。“流”的数量取决于服务器的负载能力,所以没有一个确切的数字。 39 | 不要在你的“流”中发送 HTTP/2 PRIORITY,因为会被 APNs 服务器忽略掉。 40 | 41 | ## Best Practices for Managing Connections 42 | 43 | 确保在发送多个推送通知时,始终保持与 APNs 的连接;不要不停地打开、关闭连接。APNs 会把短时间内的频繁断连视为拒绝服务的攻击。除非你能确定一个连接在很长一段时间内都空闲,否则应尽量保持连接的打开状态。假如你每天只发一个通知,那么每天都新建连接也是可以的。 44 | 45 | 你可以与 APNs 服务器建立多个连接,以提升性能。在发送大量的远程通知时,可以把他们分发到若干个服务器终端的连接上。这样一来,你可以更快地发送远程通知,APNs 也会传得更快,比起只用单一的连接,这种做法提高了效能。 46 | 47 | 你可以用 HTTP/2 PING 来检测连接是否畅通。 48 | 49 | 50 | ## Termination 51 | 52 | APNs 通过发送一条 GOAWAY,来终结一个已经建立的 HTTP/2 连接。GOAWAY 帧的负载 JSON 数据中,含有一个原因代码,指明连接终止的原因。表 6-6 列出了原因代码可能的取值。 53 | 正常的请求失败不会导致连接的终止。 54 | 55 | ## Notification API 56 | 57 | APNs Provider API 包含一个请求和一个回应,配置好后通过 HTTP/2 POST 命令发送。通过 Request,向 APNs 服务器发送一个推送通知,用 Response 来判断请求的处理结果。 58 | 59 | ## Request 60 | 61 | 用请求,来向某个特定用户设备发送一条通知。 62 | 63 | **表 6-1 HTTP/2 Request** 64 | 65 | | 名称 | 值 | 66 | | :-------- | :-----| 67 | | :method | POST| 68 | |:path|/3/device/\| 69 | 70 | \参数,是十六进制字节形式的目标设备的 device token。 71 | 72 | 为了避免重复的头部的键和值,APNs 要求使用 HPACK(HTTP/2 头部压缩)。 73 | APNs 维护了一个 HPACK 的小型动态表。为了避免出现 HPACK 表填满了必须丢弃数据的情况,头部的编码请采用下述方式。在发送大量的“流”时更要这么做: 74 | 75 | 1. `:path ` 头部应为 literal header field without indexing 类型的; 76 | 77 | 2. `apns-id`、`apns-expiration`头部必须根据初始或后续的 POST 操作编码为不同的值。如下: 78 | 79 | * 当你首次发送这些头部时,用 incremental indexing 来编码,从而让头部名称可以加进动态表里。 80 | 81 | * 后续当你发送这些头部时,用 literal header fields without indexing 形式的头部区域来编码。 82 | 83 | 其他所有的头部都用 literal header fields without indexing 形式来编码。详见 https://tools.ietf.org/html/rfc7541#section-6.2.1 及 https://tools.ietf.org/html/rfc7541#section-6.2.2。 84 | 85 | APNs 会忽略掉不在表格 6-2 中的头部。 86 | 87 | **表 6-2 Request header** 88 | 89 | | Header | 描述 | 90 | | :--------: | :-----| 91 | |apns-id| 通知的全球唯一标识符。如果发送通知时出错了,APNs 会通过这个值来查找发往你服务器的这条通知。
形式是 32 位小写的十六进制数值,分五组显示,每组之间用中杠隔开,形式为 8-4-4-4-12。例如,下面是一个 UUID 的例子:
123e4567-e89b-12d3-a456-42665544000
如果你没写这个头信息的话,APNs 会创建一个新的 UUID 并在回应中返回该值。| 92 | |apns-expiration|UNIX 时代的日期,以秒计算(UTC)。这条头部信息是通知失效可被删除的日期。
如果这个值是非零的,APNs 会保存通知,尝试至少发送一次;如果无法第一次无法发送的话,会重复进行尝试。如果值为 0,APNs 会当做这条通知瞬间过期,并且不会保存或重传这条通知。| 93 | |apns-priority|通知的优先级。指定下列其中一个值:
10:立刻发送推送通知。这种优先级的通知会触发目标设备上的通知、声音或角标。如果一个通知只有 content-available 键的话,用这个优先级就错了。
5:在考虑到设备电量的情况下发送推送通知。这种优先级的通知可能会被分组到一起,然后连续发出。他们会被掐掉,某些情况下甚至会不发。
如果没有指定,APNs 会默认设置优先级为 10。| 94 | |apns-topic|远程通知的 topic,通常是你应用的 bundle ID。在开发者中心创建的证书必须包含了能够容纳这个 topic 的能力。
如果你的证书包含多个 topics,你必须为这个头部指定一个值。
如果没有指定这个头部,并且你的 APNs 证书没有指定多个 topics 的话,APNs 服务器会使用证书的 Subject 作为默认 topic。| 95 | 96 | 你的消息的 body 内容是 JSON 字典对象,包含有通知的数据。body 数据不可以被压缩,最大 4KB(4096 字节)。body 内容中所包含的键值的信息,详见《The Remote Notification Payload》。 97 | 98 | ## Response 99 | 100 | 格式如表 6-3 所示。 101 | 102 | **表 6-3 Response headers** 103 | 104 | | 名称 | 值 | 105 | | :-------- | :----- | 106 | |apns-id|Request 里的 apns-id。如果 Request 里没有这项,服务器会创建一个新的 UUID 并该值。| 107 | |:status|HTTP 状态码。可能的状态码,见表 6-4。| 108 | 109 | 表 6-4 列出了 Request 可能的状态码。这些值都包含在 Response 的 `:status` 头部里。 110 | 111 | **表 6-4 Response 的状态码** 112 | 113 | | 状态码 | 描述 | 114 | | :-------- | :----- | 115 | |200|Success| 116 | |400|Bad Request| 117 | |403|There was an error with the certificate.| 118 | |405|The Request used a bad :method value. Only POST Requests are supported.| 119 | |410|The device token is no longer active for the topic.| 120 | |413|The notification payload was too large.| 121 | |429|The server received too many Requests for the same device token.| 122 | |500|Internal server error| 123 | |503|The server is shutting down and unavailable.| 124 | 125 | 126 | 请求成功时,回应的 body 为空。失败时,回应的 body 包含一个 JSON 的字典,键值如表 6-5 所示。连接终止时的 GOAWAY 帧里,也可能出现该 JSON 数据。 127 | 128 | **表 6-5 JSON 数据键** 129 | 130 | | 键 | 描述 | 131 | | :-------- | :----- | 132 | |reason|表明失败原因的错误代码。string 类型的错误代码。表 6-6 列出了可能的错误值。| 133 | |timestamp|如果 :status 头部的值为 410,则该键对应的值表示最近一次 APNs 确认该 topic 的 device token 无效的时间。在设备向你的 provider 注册一个新一点的 timestamp 的 token 之前,都不要进行推送。| 134 | 135 | 表 6-6 列出了 Response 的 JSON 负载的`reason`键的可能的错误码。 136 | 137 | **表 6-6 `reason`键的值** 138 | 139 | | 原因 | 描述 | 140 | | :-------- | :----- | 141 | |PayloadEmpty|The message payload was empty.
Expected HTTP/2 status code is 400; see Table 6-4.| 142 | |PayloadTooLarge|The message payload was too large. The maximum payload size is 4096 bytes.| 143 | |BadTopic|The apns-topic was invalid.| 144 | |TopicDisallowed|Pushing to this topic is not allowed.| 145 | |BadMessageId|The apns-id value is bad.| 146 | |BadExpirationDate|The apns-expiration value is bad.| 147 | |BadPriority|The apns-priority value is bad.| 148 | |MissingDeviceToken|The device token is not specified in the Request :path. Verify that the :path header contains the device token.| 149 | |BadDeviceToken|The specified device token was bad. Verify that the Request contains a valid token and that the token matches the environment.| 150 | |DeviceTokenNotForTopic|The device token does not match the specified topic.| 151 | |Unregistered|The device token is inactive for the specified topic.
Expected HTTP/2 status code is 410; see Table 6-4.| 152 | |DuplicateHeaders|One or more headers were repeated.| 153 | |BadCertificateEnvironment|The client certificate was for the wrong environment.| 154 | |BadCertificate|The certificate was bad.| 155 | |Forbidden|The specified action is not allowed.| 156 | |BadPath|The Request contained a bad :path value.| 157 | |MethodNotAllowed|The specified :method was not POST.| 158 | |TooManyRequests|Too many Requests were made consecutively to the same device token.| 159 | |IdleTimeout|Idle time out.| 160 | |Shutdown|The server is shutting down.| 161 | |InternalServerError|An internal server error occurred.| 162 | |ServiceUnavailable|The service is unavailable.| 163 | |MissingTopic|The apns-topic header of the Request was not specified and was required. The apns-topic header is mandatory when the client is connected using a certificate that supports multiple topics.| 164 | 165 | ## Examples 166 | 167 | **表单 6-1 单一 topic 的证书的 Request 示例** 168 | ``` 169 | HEADERS 170 | - END_STREAM 171 | + END_HEADERS 172 | :method = POST 173 | :scheme = https 174 | :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0 175 | host = api.development.push.apple.com 176 | apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b 177 | apns-expiration = 0 178 | apns-priority = 10 179 | DATA 180 | + END_STREAM 181 | { "aps" : { "alert" : "Hello" } } 182 | ``` 183 | 184 | **表单 6-2 多 topic 的证书的 Request 示例** 185 | ``` 186 | HEADERS 187 | - END_STREAM 188 | + END_HEADERS 189 | :method = POST 190 | :scheme = https 191 | :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0 192 | host = api.development.push.apple.com 193 | apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b 194 | apns-expiration = 0 195 | apns-priority = 10 196 | apns-topic = 197 | DATA 198 | + END_STREAM 199 | { "aps" : { "alert" : "Hello" } } 200 | ``` 201 | 202 | **表单 6-3 推送 Request 成功时的 Response 示例** 203 | ``` 204 | HEADERS 205 | + END_STREAM 206 | + END_HEADERS 207 | :status = 200 208 | ``` 209 | 210 | **表单 6-4 Request 出错时的 Response 示例** 211 | ``` 212 | HEADERS 213 | - END_STREAM 214 | + END_HEADERS 215 | :status = 400 216 | content-type = application/json 217 | apns-id: 218 | DATA 219 | + END_STREAM 220 | { "reason" : "BadDeviceToken" } 221 | ``` 222 | -------------------------------------------------------------------------------- /ios_sdk_quick_start.md: -------------------------------------------------------------------------------- 1 | # Yunba iOS SDK 快速入门 2 | 3 | ## 注册开发者账号 4 | 打开 [云巴官方网站](https://yunba.io), 点击注册创建账号。 5 | 6 | ![productpng_portal_register_account.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_register_account.png) 7 | 8 | ## 创建应用 9 | 注册账号成功跳转到我的应用界面,点击“创建应用”,输入应用名称 10 | 11 | ![productpng_portal_creat_app.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_creat_app.png) 12 | 13 | ## 下载 iOS SDK 14 | 15 | 打开 [开发者资源页面](https://yunba.io/downloads/>) 下载 iOS SDK, iOS SDK 包含 DEMO 程序和开发者所需嵌入的 lib 库以及头文件。 16 | 17 | ## 导入 iOS SDK 18 | 19 | 下载的 YunBa-iOS-sdk 包并添加到项目中,并且添加依赖库SystemConfiguration.framework。 20 | 21 | ![iospng_sdk_add_in_xcode.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_sdk_add_in_xcode.png) 22 | 23 | ## 添加使用代码 24 | 25 | 添加头文件,引入`YunBaService.h`: 26 | 27 | ```objective_c 28 | #import "YunBaService.h" 29 | ``` 30 | 31 | 从portal获取AppKey: 32 | 33 | ![productpng_portal_copy_app_key.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_copy_app_key.png) 34 | 35 | >**注**: 请使用从 Portal 获取到的 AppKey 替换代码中的 AppKey。 36 | 37 | 初始化 SDK 并订阅 Topic,在`- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` 中添加初始化和订阅代码: 38 | 39 | ```objective_c 40 | [YunBaService setupWithAppkey:AppKey]; 41 | 42 | [YunBaService subscribe:topic resultBlock:^(BOOL succ, NSError *error){ 43 | if (succ) { 44 | NSLog(@"[result] subscribe to topic(%@) succeed", topic); 45 | } else { 46 | NSLog(@"[result] subscribe to topic(%@) failed: %@, recovery suggestion: %@", topic, error, [error localizedRecoverySuggestion]); 47 | } 48 | }]; 49 | ``` 50 | 51 | ## 添加 监听消息及处理代码 52 | 在默认消息中心添加的监听代码: 53 | 54 | ```objective_c 55 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMessageReceived:) name:kYBDidReceiveMessageNotification object:nil]; 56 | ``` 57 | 58 | 消息处理代码: 59 | 60 | ```objective_c 61 | - (void)onMessageReceived:(NSNotification *)notification { 62 | YBMessage *message = [notification object]; 63 | NSString *payloadString = [[NSString alloc] initWithData:[message data] encoding:NSUTF8StringEncoding]; 64 | NSLog(@"[Message] %@ => %@", [message topic], payloadString); 65 | } 66 | ``` 67 | 68 | ## 在 Portal 上发布消息 69 | 70 | 打开应用详情页面,点击发布消息,如图所示: 71 | 72 | ![productpng_portal_publish_to_topic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_to_topic.png) 73 | 74 | ## 在 Portal 查看消息发布实时报表 75 | 76 | 打开应用详情页面,点击发布上报统计可以查看消息发布实时送达比,如图所示: 77 | 78 | ![productpng_portal_publish_statistic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_statistic.png) 79 | 80 | ## 在 Portal 查看用户在线信息实时报表 81 | 82 | 打开应用详情页面,点击在线用户统计可以查看当前在线用户数,用户活跃数等信息,如图所示: 83 | 84 | ![productpng_portal_online_statistic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_online_statistic.png) 85 | 86 | ## 在 Portal 上传APNs证书以激活APN推送功能 87 | 88 | 打开编辑应用页面,点击 “选择文件” 按钮,上传证书文件(*.p12)。如果证书导出时设置了密码,则需将密码填写在 “证书密码” 一栏。 89 | 90 | 此外,iOS SDK 还支持 “[多证书](ios_kb_multiple_certificates.md)” 功能。用户可以点击左侧的 “添加更多证书” 的按钮,上传多个证书(暂无数量限制),从而实现对同一应用的不同版本进行推送。 91 | 92 | 证书添加完成后,请点击 “提交” 按钮,保存设置。 93 | 94 | ![ios_create_new_app.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_portal_add_certificate.png) 95 | 96 | ### 生成APNs证书的步骤如下: 97 | 1. 打开 Apple 开发者网站的 [证书管理界面](https://developer.apple.com/account/ios/certificate/) 98 | 99 | 2. 点击新建证书 100 | 101 | ![iospng_cert_creat_certificate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_creat_certificate.png) 102 | 103 | 3. 选择新建证书的类型(开发或者生产推送环境) 104 | 105 | ![iospng_cert_choose_type.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_choose_type.png) 106 | 107 | 注:如果你的系统中没有中间签名证书,则需要下载并安装到你的系统中: 108 | 109 | ![iospng_cert_before_create_certificate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_before_create_certificate.png) 110 | 111 | 4. 为证书选择对应需要推送功能的APP ID: 112 | 113 | ![iospng_cert_choose_appid.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_choose_appid.png) 114 | 115 | 5. 为制作推送证书,需要有一个CSR文件用以使新生成的推送证书与私钥相匹配: 116 | 117 | ![iospng_cert_upload_csr.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_upload_csr.png) 118 | 119 | 注:如果你没有CSR文件,则需要新建一个,步骤如下: 120 | 121 | a. 打开钥匙串访问 122 | 123 | ![iospng_cert_open_key_chain.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_open_key_chain.png) 124 | 125 | b. 申请创建CSR文件 126 | 127 | ![iospng_cert_creat_csr.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_creat_csr.png) 128 | 129 | c. 输入你的邮件等信息后保存CSR文件到本地磁盘 130 | 131 | ![iospng_cert_save_csr.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_save_csr.png) 132 | 133 | 6. 点击继续之后生成APNs证书成功,然后点击下载即可 134 | 135 | ![iospng_cert_download_certifcate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_download_certifcate.png) 136 | 7. 导出证书为p12文件 137 | 138 | ![iospng_cert_export_certificate.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_export_certificate.png) 139 | 140 | 导出时可以添加自定义密码以提高安全性: 141 | 142 | ![iospng_cert_p12_password.png](https://raw.githubusercontent.com/yunba/docs/master/image/iospng_cert_p12_password.png) 143 | 144 | 8. 制作完成后,在 Portal 上传APNs证书以激活APN推送功能 145 | 146 | 9. 注意:*如果你使用生产和开发证书两个证书来进行推送:云巴会在使用的过程中根据 SDK 上报的状态自动选择生产或者开发证书,也就是说消息会推送给使用开发或生产证书的所有设备。如果需要仅发送给一个证书下的app的话建议在推送前删除另一个证书。* 147 | -------------------------------------------------------------------------------- /java_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba Java Demo 2 | 3 | 本文介绍如何运行 [yunba-java-sdk](https://github.com/yunba/yunba-java-sdk) 中的 Demo。 4 | 5 | 本文涉及的运行环境如下: 6 | 7 | * Mac OS X 10.11.2 8 | * bash 3.2.57 9 | * Eclipse 4.5.1 10 | 11 | ## 准备工作 12 | 13 | ###1. 注册云巴开发者账号 14 | 打开 [云巴官方网站](https://yunba.io),点击右上角的 “注册” 按钮创建账号。 15 | 16 | ###2. 下载云巴 Java SDK 17 | 下载 [yunba-java-sdk](https://github.com/yunba/yunba-java-sdk),并解压。 18 | 19 | ###3. 导入工程和 jar 20 | 打开 Eclipse,新建一个空白的 Java 工程,拖入 YunBaDemo.java 文件。此时会出现大量报错,只需导入下载的 SDK 包里的 yunba-java-sdk.jar 文件即可解决。步骤如下。 21 | 22 | 右击工程名称,选择 Properties --> Java Build Path,在 Libraries 标签页下选择 Add External JARs,然后在弹出的窗口中,指定 yunba-java-sdk.jar 文件。 23 | 24 | ## 详细步骤 25 | 26 | ###1. 在云巴 Portal 上创建新应用 27 | 在云巴 [Portal](product_kb_portal.md) 上创建新应用,并获得一个 [AppKey](product_kb_app_key.md)。 28 | 29 | ###2. 修改 APPKEY 30 | 将 src/YunBaDemo.java 里的 APPKEY 改为上一步骤中自己创建的 AppKey。 31 | ```java 32 | final MqttAsyncClient mqttAsyncClient = MqttAsyncClient.createMqttClient("567a4a754407a3cd028aaf6b"); 33 | ``` 34 | **注**:上文给出的 AppKey 功能受限,仅供文档举例使用。 35 | 36 | ###3. 运行 37 | 38 | 在 [YunBaDemo.java](https://github.com/yunba/yunba-java-sdk/blob/master/src/YunBaDemo.java) 中,给出了 [初始化](java_sdk_api_manual.md#createmqttclient)、[连接云巴服务器](java_sdk_api_manual.md#connect),以及成功连接后的 [订阅 Topic](java_sdk_api_manual.md#subscribe)、 39 | [向 Topic 发布消息](java_sdk_api_manual.md#publish)、[设置 Alias](java_sdk_api_manual.md#setalias)、[向 Alias 发布消息](java_sdk_api_manual.md#publishtoalias)的示例。 40 | 41 | 可直接运行 Demo 客户端,进行消息收发的测试。客户端运行后,可以通过 [Portal](product_kb_portal.md) 向该客户端发布消息,或通过集成其他的云巴 SDK 来与之通信。 42 | 43 | 更多说明,请参考 [Java API 文档](java_sdk_api_manual.md)。 44 | -------------------------------------------------------------------------------- /js_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba JavaScript Demo 2 | 3 | 本文介绍如何运行 Yunba JavaScript SDK 中的 Demo 示例程序。 4 | 5 | 本文涉及的运行环境如下: 6 | 7 | * Mac OS X 10.11.1 8 | * YunBa JavaScript SDK 2.0.3 9 | 10 | ## 准备工作 11 | 12 | ###1. 下载云巴 JavaScript SDK 13 | 打开 [云巴开发者页面](https://yunba.io/downloads/),下载最新版本的 JavaScript SDK。 14 | 15 | ###2. 注册云巴开发者账号 16 | 打开 [云巴官方网站](https://yunba.io),点击右上角的“注册”按钮创建账号。 17 | 18 | ## 详细步骤 19 | 20 | ###1. 在云巴 Portal 上创建新应用 21 | 请参考 [运行 Yunba Android Demo](android_demo_quick_start.md) 22 | 一文中的该步骤的做法,获得一个 AppKey。 23 | 24 | ###2. 修改 AppKey 25 | 请打开需要用到的 yunba_javascript_demo_customid.html 文件,在开头处找到 AppKey 所在的位置,替换为步骤 1 中在 Portal 创建新应用时获取到的 AppKey。 26 | ``` 27 | var yunba = new Yunba({appkey: 'xxxxxxxxxxxxxxxxx'}); 28 | ``` 29 | ###3. 运行 Demo 30 | 31 | examples 目录下有两个html文件:yunba_javascript_demo.html 和 yunba_javascript_demo_customid.html,差别在于连接消息服务器时,使用的是“connect”,还是“connect_by_customid”。推荐使用后者,使用同样的会话ID进行连接,可确保登录信息与上次连接一致(包括离线消息、之前已订阅的频道和别名)。 32 | 33 | 双击打开 yunba_javascript_demo_customid.html 后,浏览器会先弹出一个消息框,提示输入自定义 ID。如下图所示,在界面右上方输入 ID,点击“Connect”即可。订阅“news”后,即可收到“news”频道下的消息。见下图标记处的第一行内容。 34 | 35 | ![jspng_demo_receive_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/jspng_demo_receive_message.png) 36 | 37 | 可通过 Set Alias 设置自己的别名。例如,设置别名为“Jack”,见下图。设置成功后,即可收到发给该别名的消息。 38 | 39 | 40 | 图中靠下方的位置展示的是查询某个用户的订阅列表和在线状态,以及某个频道下所有的用户别名。其返回的结果可参考上图中标记处的后三行。 41 | 42 | 43 | ![jspng_demo_set_alias.png](https://raw.githubusercontent.com/yunba/docs/master/image/jspng_demo_set_alias.png) 44 | 45 | 此外,还可以通过 subscribe_presence 来监听收听了“news”的所有用户的别名状态的变化。见下图。 46 | ![jspng_demo_subscribe_presence.png](https://raw.githubusercontent.com/yunba/docs/master/image/jspng_demo_subscribe_presence.png) 47 | 48 | 49 | 发布消息的界面如下,可按频道发布,或按别名发布: 50 | 51 | ![jspng_demo_publish.png](https://raw.githubusercontent.com/yunba/docs/master/image/jspng_demo_publish.png) 52 | -------------------------------------------------------------------------------- /js_faq.md: -------------------------------------------------------------------------------- 1 | # JavaScript SDK 常见问题解答 2 | 3 | 4 | 1. **如何获取`publish2()`的 opts 设置参数?** 5 | 6 | 答: 可以把 opts 参数封装到 Message,在接收时进行解析。 7 | 8 | --- 9 | 2. **如何接收离线消息?** 10 | 11 | 答: 用[`connect_by_customid()`](https://yunba.io/docs2/Javascript_SDK/#connect_by_customid 12 | ) 进行连接,连接后的会话状态与上次连接一致(包括离线消息、已订阅的频道和别名)。`connect()`仅用于测试,无法接收离线消息。 13 | 14 | --- 15 | 3. **如何判断消息来自频道还是用户?** 16 | 17 | 答: 开发者可传递 Message ID,接收时通过 Message ID 进行判断。设置 Message ID 的方法可以参考 demo 的 [mqtt_publish2 方法](https://github.com/yunba/yunba-javascript-sdk/blob/master/examples/yunba_javascript_demo.html)。 18 | 19 | --- 20 | 4. **用户订阅的 Topic 和设置的别名 Alias 保存在哪里?** 21 | 22 | 答: 保存在云巴服务端,与 CustomID 对应。 23 | 24 | --- 25 | 5. **JavaScript SDK 兼容哪些浏览器?** 26 | 27 | 答: 支持浏览器的版本如下: 28 | 29 | | IE | Safari | Chrome | Opera | Firefox | 30 | |:-----:|:-----:|:-----:|:-----:|:-----:| 31 | | 10+ | ✓ | ✓ | ✓ | ✓ | 32 | 33 | IE7 以下版本需 [配置](https://github.com/yunba/yunba-javascript-sdk) 即可。 34 | 35 | 36 | --- 37 | 6. **如何批量订阅频道?** 38 | 39 | 答: 可以将订阅频道放到数组里,循环订阅。 40 | 41 | 42 | --- 43 | 7. **JS SDK 连接失败怎么办?官网后台的管理页面(Portal)显示连接断开了怎么办?** 44 | 45 | 答: 46 | * 请 Ping 一下 sock.yunba.io,如果网络异常,请自行排查网络故障; 47 | * 如果网络正常,可能是浏览器兼容性的问题,可以换其他的浏览器试试(如,Chrome,Firefox); 48 | * 如果问题还没得到解决,可以打开浏览器的 Debug 窗口(如,Chrome 可以按 F12 打开 Debug 窗口),看看错误信息是什么,并反馈给我们。 49 | 例如,下图是出错时的 Debug 窗口截图,可以看出错误原因是:reg failed 50 | 51 | ![jspng_faq_browser_debug.png](https://raw.githubusercontent.com/yunba/docs/master/image/jspng_faq_browser_debug.png) 52 | 53 | * 最后,还有一种可能是您当前使用的 [AppKey](product_kb_app_key.md) 被我们的系统限制了,请将您的 Appkey 用私聊或邮件(support@yunba.io)的方式发给我们,我们会及时处理。 54 | 55 | --- 56 | 8. **使用 JS SDK,为什么同一个页面用多台电脑打开,只有最后打开的页面可以收到推送?** 57 | 58 | 答:应该是这些页面使用了同一个 Custom ID 造成的。**同时使用多个相同 Custom ID 进行连接时只有一个连接是有效的。**请在调用 [connect_by_customid](https://yunba.io/docs/js_sdk_api_manual#connect_by_customid) 时改为使用不同的 Custom ID。 59 | -------------------------------------------------------------------------------- /js_sdk_quick_start.md: -------------------------------------------------------------------------------- 1 | # Yunba JavaScript SDK 快速入门 2 | 3 | 通过利用 Yunba Javascript SDK 提供的接口 API,你可以很方便地在智能手机、平板电脑、网站等终端应用上使用 Yunba 的各种消息服务。 4 | 5 | 6 | ## 获取 SDK 7 | 8 | [下载最新SDK](https://github.com/yunba/yunba-javascript-sdk) 9 | 10 | 11 | ## 新手上路 12 | 13 | 调试工具可以用 Chrome 本身自带 JavaScript Console,其它浏览器可能需要安装相应插件。例如 FireFox 需要安装 FireBug。 14 | 15 | 16 | ### 第一步:引入 SDK 17 | 18 | Yunba JavaScript SDK 依赖于 Socket.IO,所以要先引入 Socket.IO。 19 | 请参考(SDK 中的)Demo 分别引入 Socket.IO 和 yunba-js-sdk。 20 | 21 | 22 | ### 第二步:创建 Yunba 实例 23 | 24 | 这里,需要在云巴 [Portal](product_kb_portal.md) 上创建新应用,用获取到的 [AppKey](product_kb_app_key.md) 创建 Yunba 实例。 25 | 26 | ```javascript 27 | var yunba = new Yunba({server: 'sock.yunba.io', port: 3000, appkey: appkey}); 28 | ``` 29 | 30 | 31 | ### 第三步:初始化并连接消息服务器 32 | 33 | ***注意:如果不使用 [connect_by_customid](https://yunba.io/docs/js_sdk_api_manual#connect_by_customid) 而使用不带 customid 的 [connect](https://yunba.io/docs/js_sdk_api_manual#connect),那对云巴来说每次连接的都是新用户,也就是客户端每次连接都会创建一个新的日活,*** 34 | 35 | ```javascript 36 | yunba.init(function (success) { 37 | if (success) { 38 | yunba.connect_by_customid('your_app_user_id', function (success, msg, sessionid) { 39 | if (success) { 40 | console.log('你已成功连接到消息服务器,会话ID:' + sessionid); 41 | } else { 42 | console.log(msg); 43 | } 44 | }); 45 | } 46 | }); 47 | ``` 48 | 49 | 50 | ### 第四步:订阅频道(Subscribe) 51 | 52 | 如果你想接收一个频道的消息,你得先使用`subscribe()`方法订阅该 [频道](product_kb_topic_and_alias.md), 53 | 然后用`set_message_cb()`方法设置收到消息时调用的回调函数来接收消息。 54 | 55 | >**注**:`subscribe()`的前提是客户端已经成功连上服务器。为了确保在连接成功以后再进行订阅,可以将`subscribe()`写到`connect_by_customid()`的回调函数中,在 success 时才执行。 56 | 57 | ```javascript 58 | yunba.subscribe({'topic': 'my_topic'}, 59 | function (success, msg) { 60 | if (success) { 61 | console.log('你已成功订阅频道:my_topic'); 62 | } else { 63 | console.log(msg); 64 | } 65 | } 66 | ); 67 | 68 | yunba.set_message_cb(function (data) { 69 | console.log('Topic:' + data.topic + ',Msg:' + data.msg); 70 | }); 71 | ``` 72 | 73 | 74 | ### 第五步:发布消息(Publish) 75 | 76 | 你可以使用`publish()`方法向所有订阅 my_topic 频道的终端发布一条 “你好!Yunba。” 消息。 77 | 78 | ```javascript 79 | yunba.publish({'topic': 'my_topic', 'msg': '你好!Yunba。'}, 80 | function (success, msg) { 81 | if (success) { 82 | console.log('消息发布成功'); 83 | } else { 84 | console.log(msg); 85 | } 86 | } 87 | ); 88 | ``` 89 | 90 | 将上面的例子扩展一下,我们就可以利用 Yunba 实现在 JavaScript 和其他平台之间的实时通讯。 91 | 92 | -------------------------------------------------------------------------------- /php_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba PHP Demo 2 | 3 | 本文介绍如何运行 Yunba PHP SDK 中的 examples 示例程序。 4 | 5 | **提示:**此 SDK 只能在 [CLI](http://php.net/manual/zh/features.commandline.php) 模式下以阻塞方式运行,如果只用于发布消息,推荐使用更简单的 [RESTful API](restful_api_api_manual.md)。 6 | 7 | 本文涉及的运行环境如下: 8 | 9 | Windows 平台: 10 | * Windows 8.1 11 | * WampServer 1.6.1.33 12 | * YunBa PHP SDK 13 | 14 | Mac 平台: 15 | * OS X 10.11.2 16 | * bash 3.2.57 17 | * PHP 5.5.30 18 | * libcurl 19 | * YunBa PHP SDK 20 | 21 | ## 准备工作 22 | 23 | ###1. 注册云巴开发者账号 24 | 打开 [云巴官方网站](https://yunba.io),点击右上角的 “注册” 按钮创建账号。 25 | 26 | ###2. 下载云巴 PHP SDK 27 | 这里使用的是 Yunba PHP SDK,可打开 [其 GitHub 页](https://github.com/yunba/yunba-php-sdk),下载 Zip 文件。 28 | 29 | ###3. 配置环境 30 | 31 | **Windows 平台** 32 | 33 | 在 WampServer 解压后的 “...\wamp\bin\php” 路径下搜索 php.init 文件并打开该文件,确保 ```extension=php_openssl.dll``` 、```extension=php_curl.dll``` 和 ```extension_dir = ".../ext/"``` 语句**取消注释**(删去代码语句前的";")。如下图: 34 | 35 | 36 | ![phppng_demo_extention_openssl.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_extention_openssl.png) 37 | 38 | 39 | ![phppng_demo_curl.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_curl.png) 40 | 41 | 42 | ![phppng_demo_extention_dir.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_extention_dir.png) 43 | 44 | **Mac 平台** 45 | 46 | 安装 PHP 及 PHP 的 cURL 依赖。 47 | 48 | 注意,从 PHP 4.0.2 起,只需安装 libcurl,即可在 PHP 中使用 cURL 的函数。详细说明请参考:[PHP 手册](http://php.net/manual/en/curl.requirements.php)。 49 | 50 | 51 | ## 详细步骤 52 | 本文以 [Yunba PHP SDK](https://github.com/yunba/yunba-php-sdk) 的 subscribe.php 和 publish.php 为例,演示 PHP SDK 的使用。 53 | 54 | ###1. 在云巴 Portal 上创建新应用 55 | 请参考 [运行 Yunba Android Demo](android_demo_quick_start.md) 一文中的该步骤的做法,获得一个 AppKey。 56 | 57 | ###2. 引入 API 库 58 | 59 | 在工程文件中**包含** yunba.php 文件: 60 | 解压下载的 Zip 文件,在 “...\yunba-php-sdk-master\examples” 路径下的 subscribe.php 和 publish.php 文件的第三行添加 yunba.php 文件所在路径。如下图: 61 | 62 | ![phppng_demo_include_lib.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_include_lib.png) 63 | 64 | ###3. 运行 examples 65 | 66 | **Windows 平台** 67 | 68 | **1. 修改 AppKey** 69 | 70 | 打开 subscribe.php,必须修改 appkey,替换为自己的 AppKey。 71 | 72 | ``` 73 | //构造实例 74 | $yunba = new Yunba(array( 75 | "appkey" => "Your AppKey", //替换为自己的 AppKey 76 | "sessionFilePath" => "session1.dat" 77 | )); 78 | ``` 79 | **2. 订阅** 80 | 81 | 可定义 [topic](product_kb_topic_and_alias.md)、[qos](product_kb_qos.md) 等参数。代码示例如下: 82 | 83 | ``` 84 | //订阅topic1 85 | $yunba->subscribe(array( 86 | "topic" => "news", 87 | "qos" =>2 88 | ), function ($success) { 89 | echo "[Yunba]subscribe topic1\n"; 90 | }, function ($data) { 91 | echo "[YunBa]received topic1 " . var_export($data, true) . "\n"; 92 | }); 93 | ``` 94 | 95 | 找到 php.exe 文件所在的路径(从 WampServer 下搜索),把这个路径添加到**环境变量**中,运行 subscribe.php 文件进行该话题的**订阅**,如下图: 96 | 97 | ![php_subscribe.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_subscribe_masked.png) 98 | 99 | 订阅成功如下图: 100 | 101 | ![phppng_demo_subscribe_success.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_subscribe_success.png) 102 | 103 | 104 | **3. 发布消息** 105 | 106 | 打开 publish.php 文件,替换 appkey,可定义 topic、qos、msg 参数。 107 | 108 | 重启 CMD,运行 publish.php 进行该话题下的**消息发布**,如下图: 109 | 110 | ![php_publish.php.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_publish_masked.png) 111 | 112 | 消息成功发布如下图: 113 | 114 | ![phppng_demo_publish_success.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_publish_success.png) 115 | 116 | 117 | 同一个 AppKey 下并且订阅了该 Topic 的 Android 端将收到消息,如下图: 118 | 119 | ![phppng_demo_received_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/phppng_demo_received_message.png) 120 | 121 | 122 | **Mac 平台** 123 | 124 | 同样地,修改代码中的 AppKey 后,在 bash 中运行 subscribe.php 和 publish.php。如下所示。也可根据需要,修改代码中的 Topic 等参数。 125 | 126 | ```bash 127 | $ php subscribe.php 128 | ``` 129 | 130 | ```bash 131 | [YunBa]init success 132 | [YunBa]connect success 133 | [Yunba]subscribe topic1 134 | [Yunba]subscribe topic2 135 | ``` 136 | 137 | ```bash 138 | $ php publish.php 139 | ``` 140 | 141 | ```bash 142 | [YunBa]init success 143 | [YunBa]connect success 144 | [YunBa]publish1 success 145 | [YunBa]publish2 success 146 | ``` 147 | 148 | 详细的程序逻辑,请参考项目源程序。 149 | 150 | 完整的 API 文档可以参考 [yunba-php-sdk](https://github.com/yunba/yunba-php-sdk) 。 151 | -------------------------------------------------------------------------------- /product_best_practice.md: -------------------------------------------------------------------------------- 1 | # 云巴实时通信最佳实践 2 | 3 | 为了让云巴服务发挥其最佳性能、更好地为你所用,我们总结了非常实用的「云巴实时通信[最佳实践](https://en.wikipedia.org/wiki/Best_practice)」,并将持续更新。如果你在使用云巴服务时发现了其他提升性能的技巧,也欢迎随时分享给我们(support@yunba.io)。 4 | 5 | 1. **不要频繁进行订阅、取消订阅的操作** 6 | 7 | 为了充分利用云巴服务器的性能、提升通信质量,我们建议用户不要频繁进行订阅/取消订阅(subscribe / unsubscribe)的操作。 8 | 用户在进行系统架构时,如果能合理地设计 Topic 数量和订阅关系,云巴服务器就能够有效地缓存客户端的路由信息,从而加快通信时的寻址速度,提高通信质量。相反地,如果用户把 频道(Topic)当作临时资源来使用(尽管目前暂无限制),则会加重服务器负载,导致通信质量的下降。 9 | 10 | --- 11 | 2. **建议消息内容不超过 4 KB** 12 | 13 | 云巴适合传输长度不超过 4 KB 的信息,比如物联网设备的控制信令、普通文字聊天信息等。如果需要传递超过 4 KB 的信息(比如图片、视频等),建议先使用第三方存储,然后在云巴系统通道中传递超链接。频繁地传递超过 4 KB 大小的信息可能会受到云巴系统的限制,降低通信质量。 14 | 15 | --- 16 | 3. **建议使用 QoS 1** 17 | 18 | 近期,云巴 QoS 2 的逻辑正在优化中,建议使用 QoS 1,可以考虑在客户端层面进行去重处理。如果对消息的不重复要求很高,可以在 publish2 中自定义 messageId,具体使用的方法为在 publish2 的 opts 字段中加入 `messageId` 字段,该字段为64位整型数转为 `String` 型。接收端可以判断此 message 是否重复来判断是否是重复的消息。 19 | -------------------------------------------------------------------------------- /product_demo_bullet.md: -------------------------------------------------------------------------------- 1 | # 如何用云巴实现弹幕功能 2 | 3 | 在云巴官网的[《视频直播弹幕互动》][1]案例中,介绍了为什么云巴非常适合应用于视频直播的弹幕、点赞等场景。 4 | 5 | 本文主要介绍如何使用云巴的 JavaScript SDK 来实现弹幕功能(可参考案例的 [GitHub][5] 页)。 6 | 7 | 如果你想实现 iOS 系统的视频直播 App,可参考云巴 iOS 视频直播弹幕案例的 [GitHub][9] 页。 8 | 9 | ## 第一步 注册账号 10 | 11 | 打开 [云巴官方网站][8],注册并登录。 12 | 13 | ## 第二步 创建新应用 14 | 15 | 登录后,点击界面右上角 “我的应用 --> 创建新应用”,填写您的视频直播应用的名称、应用包名等内容。详见 [Portal 的说明文档][4]。 16 | 17 | 创建后,您会在应用详情页面看到该应用的 [AppKey][3]。 18 | 19 | ## 第三步 下载 SDK 20 | 21 | 在云巴官网的 [开发者页面][2] 或云巴的 [Github][7] 上找到所需平台的 SDK,并下载。 22 | 23 | 每种 SDK 的文件包内都包含一个 Demo,用来演示主要 API 的用法和功能。 24 | 建议您从运行 Demo 开始熟悉云巴的 SDK,详见各个 SDK 的 Demo 运行的文档。 25 | 26 | ## 第四步 集成 SDK 27 | 28 | 将云巴 SDK 集成到您的应用中(此时会用到第二步中的 [AppKey][3])。 29 | 30 | 我们以 [云巴视频直播案例][5] 所使用的 [JavaScript SDK][6] 为例,介绍一下集成 SDK 的步骤: 31 | 32 | ### 1. 引入 SDK 33 | 34 | Yunba JavaScript SDK 依赖于 Socket.IO,所以要先引入 Socket.IO。 35 | 请参考(SDK 中的)Demo 分别引入 Socket.IO 和 yunba-js-sdk。 36 | 37 | ### 2. 创建 Yunba 实例 38 | 39 | 用 “第二步” 中获取到的 [AppKey][3] 创建 Yunba 实例。 40 | 41 | ```javascript 42 | window.yunba = new Yunba({ 43 | server: 'sock.yunba.io', 44 | port: 3000, 45 | appkey: APPKEY // 这里是您在 “第二步” 中获取到的 AppKey。 46 | }); 47 | ``` 48 | 49 | ### 3. 初始化、连接消息服务器、订阅 “弹幕” 频道 50 | 51 | 假设弹幕的频道名称为 `TOPIC_BULLET`: 52 | 53 | ```javascript 54 | 55 | yunba.init(function(success) { 56 | if (success) { 57 | var cid = Math.random().toString().substr(2); 58 | 59 | // 连接云巴服务器 60 | yunba.connect_by_customid(cid, 61 | function(success, msg, sessionid) { 62 | if (success) { 63 | console.log('sessionid:' + sessionid); 64 | 65 | // 设置收到信息回调函数 66 | yunba.set_message_cb(yunba_msg_cb); 67 | 68 | // 订阅弹幕 TOPIC 69 | yunba.subscribe({ 70 | 'topic': TOPIC_BULLET 71 | }, 72 | function(success, msg) { 73 | if (success) { 74 | console.log('subscribed'); 75 | } else { 76 | console.log(msg); 77 | } 78 | }); 79 | } else { 80 | console.log(msg); 81 | } 82 | }); 83 | } else { 84 | console.log('yunba init failed'); 85 | } 86 | }); 87 | ``` 88 | 89 | ### 4. 发布 “弹幕” 90 | 91 | 用下面的几行代码就可以发布弹幕: 92 | 93 | ```javascript 94 | 95 | var bullet = { 96 | "mode": mode, 97 | "text": text, 98 | "color": color, 99 | "dur": dur 100 | }; 101 | 102 | yunba.publish({ 103 | topic: TOPIC_BULLET, 104 | msg: JSON.stringify(bullet) 105 | }, 106 | function(success, msg) { 107 | if (!success) { 108 | console.log(msg); 109 | } 110 | } 111 | ); 112 | 113 | ``` 114 | 115 | 更详细的代码示例,请参考该案例的 [GitHub][5] 页,以及 iOS 视频直播 App Demo 的 [GitHub][9] 页。 116 | 117 | [1]: http://yunba.io/usercases/livevideo/ 118 | [2]: http://yunba.io/developers/ 119 | [3]: product_kb_app_key.md 120 | [4]: product_kb_portal.md 121 | [5]: https://github.com/yunbademo/yunba-live-video 122 | [6]: https://github.com/yunba/yunba-javascript-sdk 123 | [7]: https://github.com/yunba 124 | [8]: http://yunba.io 125 | [9]: https://github.com/yunbademo/yunba-live-ios-demo 126 | -------------------------------------------------------------------------------- /product_faq.md: -------------------------------------------------------------------------------- 1 | # 产品常见问题解答 2 | 3 | ## 商务合作 4 | 5 | 6 | 1. **云巴是如何收费的?** 7 | 8 | 答: 请参考 [价格页面](https://yunba.io/pricing/)、[定价规则](product_kb_pricing_details.md),以及相关 [Blog](http://blog.yunba.io/yun-ba-yunba-io-xin-jie-ge-fang-an-ji-jiang-shang-xian/)。 9 | 10 | --- 11 | 2. . **免费版每秒 20 条信息,超出后会怎样?** 12 | 13 | 答: 如果用户的使用量超出了免费版的限额,我们会提醒用户升级为付费服务。如果用户拒不接受,我们会在后台做出相应的使用限制。 14 | 15 | --- 16 | 17 | ## 业务范围 18 | 19 | 20 | 3. **在那些地区可以使用云巴的服务?** 21 | 22 | 答: 目前,云巴提供中国大陆、中国香港、东南亚及北美地区的接入服务,如需开通其他地区的接入服务,请联系我们的商务人员。 23 | 24 | --- 25 | 4. **云巴是做推送的吗?** 26 | 27 | 答: 云巴,即云消息总线,是一个跨平台实时消息系统。消息推送只是云巴其中一个产品。 28 | 29 | --- 30 | 5. **云巴可以用于智能家居、物联网吗?** 31 | 32 | 答: 云巴兼容标准的 MQTT 3.1 协议,即物联网协议,因而天然支持智能家居、物联网。 33 | 34 | --- 35 | 6. **云巴对 MQTT 协议做了哪些扩展?** 36 | 37 | 答: 请参考我们的 [Porting 文档](product_kb_mqtt_porting.md)。 38 | 39 | --- 40 | 7. **云巴有哪些产品?** 41 | 42 | 答: Android、iOS 消息推送(集成 APNs),跨平台双向实时通信,实时查看统计信息,实时获取在线状态。 43 | 44 | --- 45 | 8. **云巴能用在 Web 上吗?** 46 | 47 | 答: 可以。云巴支持 Socket.IO 协议。请参考官网上的 [Socket.IO API](socketio_api_api_manual.md)、[RESTful API](restful_api_api_manual.md) 及 [JavaScript SDK](js_sdk_quick_start.md) 文档。 48 | 49 | --- 50 | 9. **云巴系统可以用来发短信吗?** 51 | 52 | 答: 不可以。 53 | 54 | --- 55 | 10. **云巴可以根据地域进行推送吗?** 56 | 57 | 答: 暂不支持。 58 | 59 | --- 60 | 11. **请问从国外访问云巴的服务会有问题吗?** 61 | 62 | 答: 没问题。 63 | 64 | --- 65 | 12. **云巴有完整的聊天系统可直接用吗?** 66 | 67 | 答: 云巴只做最底层的消息系统,发送的具体内容不做处理。 68 | 69 | --- 70 | 13. **怎么获取发送者的信息** 71 | 72 | 答: 云巴不会对用户推送的消息进行任何操作,所以也不会加上诸如发送者信息这样的信息。如果用户想在获得消息的同时获得发送者信息这样的信息,可以把消息体打包成一个 json 格式的字符串来进行发送。在消息体内加入发送者别名这样的信息。然后在收消息的时候对 json 做一定的解析。例如在下面的 JavaScript 例子代码中,我们把消息、自定义的用户名和数据类型进行了打包,然后发送出去。 73 | 74 | ```JavaScript 75 | var data = JSON.stringify({ 76 | dataType: 'MESSAGE', 77 | dataContent: $('#chatroom-input').val(), 78 | username: this.model.get('username') 79 | }); 80 | this.publish(app.chatroomTopic, data); 81 | ``` 82 | --- 83 | 84 | ## 基础问题 85 | 86 | 87 | 14. **[什么是云巴 Portal?如何在云巴 Portal 上创建新应用?](product_kb_portal.md)** 88 | 89 | --- 90 | 15. **[什么是 AppKey?](product_kb_app_key.md)** 91 | 92 | --- 93 | 94 | ## 消息推送、实时消息 95 | 96 | 97 | 16. **[云巴 iOS 消息推送是怎样的?](ios_kb_ios_push.md)** 98 | 99 | --- 100 | 17. **[如何通过云巴实现 APNs 推送?](ios_kb_apns_implementation.md)** 101 | 102 | --- 103 | 18. **[云巴 Android 消息推送是怎样的?](android_kb_android_push.md)** 104 | 105 | --- 106 | 19. **和其他公司相比,云巴的消息推送有什么不同?** 107 | 108 | 答: 云巴支持双向推送,一个客户端既可以 Publish 也可以 Subscribe。而其他家的单向推送只能执行 Subscribe,在执行 Publish 时,还需要提供新的接口。 109 | 110 | --- 111 | 20. **[云巴支持的 频道 和 别名 两种发布方式,具体是怎样的?](product_kb_topic_and_alias.md)** 112 | 113 | --- 114 | 21. **[如何实时获取用户(设备)的在线状态?](product_kb_presence.md)** 115 | 116 | --- 117 | 22. **[云巴的离线消息是怎样的?](product_kb_offline_message.md)** 118 | 119 | --- 120 | 23. **云巴的消息送达率是多少?** 121 | 122 | 答: 排除网络链路层的因素,理论上送达率是百分之百。 123 | 124 | --- 125 | 24. **云巴的实时消息系统依赖什么网络环境?** 126 | 127 | 答: 2G,3G,4G,Wi-Fi 均可。 128 | 129 | --- 130 | 25. **发送消息出现超时是什么原因?** 131 | 132 | 答: 请先检查网络连接是否正常。 133 | 134 | --- 135 | 26. **发送的消息大小有什么限制吗?** 136 | 137 | 答: 建议不要超过 4 KB。 138 | 139 | --- 140 | 27. **支持发送语音、图片、视频吗?** 141 | 142 | 答: 大数据建议使用第三方存储。可先将资源保存到服务器,然后推送地址。 143 | 144 | >**最佳实践**:云巴适合传输长度不超过 4 KB 的信息,比如物联网设备的控制信令、普通文字聊天信息等。如果需要传递超过 4 KB 的信息(比如图片,视频等),建议先使用第三方存储,然后在云巴系统通道中传递超链接。频繁地传递超过 4 KB 大小的信息可能会受到云巴系统的限制,降低通信质量。 145 | 146 | --- 147 | 28. **发出的消息有历史记录吗?** 148 | 149 | 答: 自 2016 年 9 月起,用户可以在 Portal 的应用管理界面查看应用的**所有客户端的消息历史**。(此功能目前处于 Beta 阶段,暂时只提供 5 天的消息历史记录。) 150 | 151 | 152 | --- 153 | 29. **订阅一个频道后,可以收到在订阅之前频道内推送的消息吗?** 154 | 155 | 答: 不可以。 156 | 157 | --- 158 | 30. **发送方怎样知道接收方收到了?** 159 | 160 | 答: 服务器收到第一条 PUBACK 时,会给发送方发一个 [RECVACK](socketio_api_api_manual.md#recvack)。 161 | 162 | --- 163 | 31. **发布的消息可以撤回吗?** 164 | 165 | 答: 目前不支持撤回。 166 | 167 | --- 168 | 33. **发布消息前必须先订阅频道吗?** 169 | 170 | 答: 发布端可以不用订阅,但接收端必须订阅了频道,才能收到该频道发布的消息。 171 | 172 | --- 173 | 34. **为什么我可以收到自己发布的消息?** 174 | 175 | 答: 只要订阅了就会收到。 176 | 177 | --- 178 | 35. **App 重新安装以后,之前的别名、订阅等信息都还在吗?** 179 | 180 | 答: 在。别名、订阅关系都存储在云巴服务器上。 181 | 182 | --- 183 | 36. **是不是订阅一次就可以永久有效?** 184 | 185 | 答: 是。 186 | 187 | --- 188 | 37. **频道的数量有限制吗?** 189 | 190 | 答: 没有。 191 | 192 | --- 193 | 38. **离线消息的数量有限制吗?** 194 | 195 | 答: 每个 Topic 最多保留 50 条。如有需要,可以联系我们提高限制数量。 196 | 197 | --- 198 | 39. **可以同时给多个频道推送消息吗?** 199 | 200 | 答: 不可以。一次只能向一个频道发布消息。 201 | 202 | --- 203 | 40. **云巴可以定点推送给某个设备吗?** 204 | 205 | 答: 可以,请参考 [别名](product_kb_topic_and_alias.md)(alias)的相关文档。 206 | 207 | --- 208 | 41. **推送的消息出现乱码是什么原因?** 209 | 210 | 答: 云巴采用二进制透传,不对消息做任何处理。如果出现乱码,请自行检查应用的编码解码程序,确保发送端的 encode 和接收端的 decode 编码一致。 211 | 212 | --- 213 | 42. **使用云巴 SDK,怎样实现不同平台之间的通讯呢?** 214 | 215 | 答: 在云巴官网 Portal 创建新应用,创建后得到一个 AppKey,在不同平台上使用同一个 216 | AppKey,即可互相通讯。 217 | 218 | --- 219 | 43. **不同 AppKey 之间可以互相通信吗?** 220 | 221 | 答: 不可以。一个应用包名对应一个 AppKey,使用同一个 AppKey 的客户端才可以相互通信。 222 | 223 | --- 224 | 44. **Android SDK 不同包名可以互相通信吗?** 225 | 226 | 答: 使用云巴 Android SDK,如果需要同一个 Appkey 不同包名的客户端之间能够互相通信,请把 Appkey 227 | 对应的包名发到 support@yunba.io,我们会在内部做些处理来支持。 228 | 229 | --- 230 | 45. **用 Portal 和一个设备做测试时,“活跃用户” 显示 2 个用户?** 231 | 232 | 答: 因为 Portal 本身也相当于一个 JavaScript 客户端,所以会被统计在内。 233 | 234 | -------------------------------------------------------------------------------- /product_kb_app_key.md: -------------------------------------------------------------------------------- 1 | # AppKey 2 | 3 | ## 功能 4 | 云巴以 AppKey 来标示应用。每个应用有不同的标识符。**使用同一个 AppKey 的客户端,才可以互相通信。** 5 | 6 | ## 如何获取 7 | AppKey 是云巴的注册用户在云巴 [Portal](product_kb_portal.md) 上创建应用后得到的一串标识符,可以在每个应用的 “应用详情” 页面中查看到。 8 | **用户应妥善保管好自己的 AppKey,不在群聊等公众场合下泄露。** 9 | 10 | ## 举例 11 | 12 | 下面通过一个实际的应用场景来解释 AppKey、UID、[频道](product_kb_topic_and_alias.md)(Topic)、[别名](product_kb_topic_and_alias.md)(Alias)的概念: 13 | 14 | 用户登录云巴 [Portal](product_kb_portal.md) 创建了一个应用,获得了一个 AppKey。 15 | 在开发应用的过程中,使用这个申请到的 AppKey 集成 SDK(集成过程中需要使用 AppKey,详见官网的开发文档)。 16 | 用户将这个应用装到了 3 台机器上,那么这 3 个客户端将会共享同一个 AppKey。 17 | 18 | 在连接到云巴的消息系统时,这 3 台机器会获取到不同的 UID。**云巴以 UID 来标识 AppKey 下的不同客户端。** 19 | 于是,这个 AppKey 下就有了 3 个 UID。**客户端可以通过设置 [别名](product_kb_topic_and_alias.md) 为 UID 命名,或设置 [别名](product_kb_topic_and_alias.md) 为空字符串来删除绑定。** 20 | 21 | 假设这 3 个客户端都订阅了一个名为 Topic_1 的 [频道](product_kb_topic_and_alias.md),那么这个 AppKey 的 Topic_1 下,就有了 3 个 UID。 22 | 这时,如果在 [Portal](product_kb_portal.md) 中选择这个应用,对 Topic_1 发布消息的话,这 3 个客户端都可以收到。 23 | 用户也可以开发其他的服务端程序,向这几个客户端发布消息。只需注意,在集成云巴的 SDK 时,使用同一个 AppKey。 24 | 25 | -------------------------------------------------------------------------------- /product_kb_identification.md: -------------------------------------------------------------------------------- 1 | # device ID, Customid, 以及 MQTT Identification 2 | 3 | 在 MQTT 协议中,设备根据身份信息连接上服务器(Broker),身份信息包括 ClientIdentifier(下简称 Client ID)、Username 以及 Password。在云巴的 sdk 中,我们也是基于此来定义我们的 Device ID 以及 Customid 的:Device ID 即云巴系统中对于此 MQTT 身份信息的内部映射,Customid 即对于此 socket.io 连接的 session id的用户自定义标识;具体关系可以从下面的示意图中看到。 4 | 5 | ![productpng_kb_identification](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_identification.png) 6 | 7 | 这些 ID 和 MQTT 身份信息我们称为`注册信息`。下面我们来看看 `注册信息` 具体代表的含义。 8 | 9 | ## 注册信息代表着什么 10 | 11 | 一般来说,注册信息(特指 Username、device ID 以及 Customid)是唯一的,用来在云巴系统中唯一代表该设备或socket io 中的 session id。在云巴中,订阅关系、别名和离线消息都是与注册信息对应的。 12 | 13 | 另外,在云巴系统中,同一连接信息是互斥的,也就是说*使用相同的注册信息,只有一个设备会保留连接,后连接的会把前一个连接挤下线* 14 | 15 | **注:日活的统计即以此为依据** 16 | 17 | ## 注册信息是怎么生成的 18 | 19 | 经典的注册流程: 20 | 1. 用户在调用了 SDK 中的初始化方法(比如 iOS sdk 中的 setupWithAppkey)后,一般来说,SDK 会检查本地是否有注册信息的缓存,如果有的话就不会申请新的用户; 21 | 2. 如果没有,SDK 就会去向我们的注册服务申请; 22 | 3. 此时服务器会生成包含 Client ID、Username、Password、Device ID 的注册信息,并返回给 SDK; 23 | 4. 如果可能,SDK 会把注册信息保存下来。 24 | 25 | 在某些 SDK,比如 `C` 和 `JavaScript` 中,用户可以通过 Device ID 或 Customid 来进行初始化。使用这些信息来进行初始化(注册)的流程略有不同。 26 | 27 | 即:对于 C sdk,它并不会尝试把 Device ID 存储下来。使用 Device ID 来进行初始化的时候,它会以此为依据向服务器请求与此 Device ID 对应的注册信息; 28 | 29 | 对于 JavaScript 使用的 socket.io 来说,由于 socket.io 使用 session id 来区别每次连接,也就是说 session id 就相当于注册信息,我们使用 Customid 来代表 session id。 30 | 31 | ## 我怎么找到这些注册信息 32 | 33 | 对于用户来说,注册信息是透明的,并不会在日常使用中接触到,但是它们在 debug 的时候往往非常有用。 34 | 35 | 在不同的 sdk 中,存储的方法也会不同,下面我们来具体看看。 36 | 37 | ### Android 38 | Android sdk 中,注册信息存储在缓存文件`mqpush.serverconfig`中,文件路径一般在应用文件路径中。 39 | 40 | ### iOS 41 | iOS sdk 中,注册信息存储在 KeyChain 中,用户一般不允许访问此数据。 42 | 43 | ### JavaScript 44 | 如果允许使用 Cookie,注册信息会存在 Cookie 中,在用户下次使用,且未指定新的 Customid 时会使用此连接信息。 45 | 46 | ### C sharp 47 | C# sdk 中,注册信息存储在文件`MqttLib.dll.config`中。 48 | -------------------------------------------------------------------------------- /product_kb_message_id.md: -------------------------------------------------------------------------------- 1 | # Message ID 2 | 3 | 在 MQTT 协议中,QoS > 0 的情况下,下面这些消息中都会带有 Message ID。 4 | 5 | * PUBLISH 6 | * PUBACK 7 | * PUBREC 8 | * PUBREL 9 | * PUBCOMP 10 | * SUBSCRIBE 11 | * SUBACK 12 | * UNSUBSCRIBE 13 | * UNSUBACK 14 | 15 | 在一个特定方向(服务器发往客户端为一个方向,客户端发送到服务器端为另一个方向)的通信消息中,Message ID 是唯一的。 16 | 17 | 在云巴 SDK 中,Message ID 是自动生成的。 18 | 19 | MQTT 协议规定的 Message ID 是 16 bit,云巴将 Message ID 扩展为 64 bit,以防止 Message ID 重复带来的系统设计和数据统计方面的麻烦。 20 | 21 | -------------------------------------------------------------------------------- /product_kb_mqtt_porting.md: -------------------------------------------------------------------------------- 1 | # 云巴对 MQTT 协议的调整 2 | 3 | ## 扩展 Message ID 4 | 5 | MQTT 目前定义的 Message ID 为 16 bit,对于一个设计容量极大的系统,很快会面临 Message ID 重复的问题,对系统设计、数据统计带来很多麻烦。 因而我们把 Message ID 扩展为 64 bit。 6 | 7 | ## 0x13 协议定义 8 | 9 | * 协议版本为 0x13 时,Message ID 为 8 Bytes 10 | 11 | * 协议版本为 0x13 时,CONNECT/CONNACK/DISCONNECT 包格式不变,PUBLISH/PUBACK/PUBREL/PUBCOMP/SUBSCRIBE/SUBACK/UNSUBSCRIBE/UNSUBACK 包格式需相应变化 12 | 13 | ## 对 MQTT 命令的扩展 14 | 15 | 当前有很多业务需要进行查询内容,返回结果的流程,MQTT 当前协议的 PUBACK 并没有 Payload。通过扩展 MQTT 协议,可以解决这类问题。MQTT 协议的 Message Type 有两个保留值 0 和 15,我们对 15 做了扩展。 16 | 17 | ### 包的结构 18 | 19 | ``` 20 | fix header 21 | Byte 1: 22 | Message Type: 15 23 | Dup: x 24 | Qos: x 25 | Retain: x 26 | Byte 2: 27 | remaining length 28 | Variable header 29 | 8字节:MessageId 30 | ``` 31 | 32 | ### Payload 33 | 34 | ``` 35 | 1字节: 1~254表示命令字 (0,255保留) 36 | 2字节: 表示后面的长度 37 | 最后部分: 参数 或者 返回结果 38 | ``` 39 | 40 | ### Payload ACK 41 | 42 | ``` 43 | 1字节: 1~254表示命令字 (0,255保留) 44 | 1字节: 表示状态 45 | 2字节: 表示后面的长度 46 | 最后部分 (string): 参数 或者 返回结果 47 | ``` 48 | 49 | ### cmd 列表 50 | 51 | 1: get_alias 52 | 53 | 2: get_alias_ack 54 | 返回值 55 | 56 | ```json 57 | {command:2, status:0, data:"aliasname"} 58 | {command:2, status:1, data:"server internal error"} 59 | {command:2, status:2, data:"alias not find"} 60 | ``` 61 | 62 | 3: get_topic 63 | 64 | 4: get_topic_ack 65 | 返回值 66 | 67 | ```json 68 | {command:4, status:0, data: "{'topic':[topic1,topic2,...]}"} 69 | {command:4, status:1, data: "server internal error"} 70 | {command:4, status:2, data: "no operation permission"} 71 | {command:4, status:3, data: "alias not find"} 72 | ``` 73 | 74 | 5: get_aliaslist 75 | 76 | 6: get_aliaslist_ack 77 | 返回值 78 | 79 | ```json 80 | {command:6, status:0, data: "{'alias':[alias1,alias2,alias3], 'occupancy': alias_length}"} 81 | {command:6, status:1, data: "server internal error"} 82 | {command:6, status:2, data: "no operation permission"} 83 | ``` 84 | 85 | 7: new_publish 至少需要两个参数叠加:topic/payload (platform/apn_json/...) 86 | 87 | 8: new_puback 88 | 返回值 89 | 90 | ```json 91 | {command:8, status:0, data: NULL} 92 | ``` 93 | 94 | 9: get_status 95 | 参数: alias 96 | 97 | 10: get_status_ack 98 | 返回值 99 | 100 | ```json 101 | {command:10, status:0, data: "online/offline"} 102 | {command:10, status:1, data: "server internal error"} 103 | {command:10, status:2, data: "no operation permission"} 104 | {command:10, status:3, data: "alias not find"} 105 | {command:10, status:4, data: "no status"} 106 | {command:10, status:5, data: "alias is empty"} 107 | ``` 108 | 109 | 11: puback. 通知推送者谁是第一个收到该消息的。 110 | 111 | ```json 112 | {"sub_uid": , 'mid':, "timestamp": , "alias":} 113 | ``` 114 | 115 | `uid`: 第一个收到该消息的uid. 116 | `message_Id`: 该消息的ID. 117 | `timestamp`:第一个收到该休息client的timestamp. 118 | `alias`: 第一个收到该消息client的别名. 119 | 120 | ### 对 new publish tlv 的参数说明 121 | 122 | ``` 123 | 1字节: 1~254表示 type 类型 (0,255保留) 124 | 2字节: 参数value的长度 125 | 后面的字节: 参数的值 126 | ``` 127 | 128 | type 类型列表 129 | 130 | * 0: topics 131 | 132 | * 1: payload 133 | 134 | * 2: platform 参数为 int 135 | 目标用户终端手机的平台类型,如: android, ios, winphone 多个请使用逗号分隔(默认全部推送) 136 | 137 | * 3: time_to_live 参数为 int 从消息推送时起,保存离线的时长。秒为单位。最多支持15天 (默认永久保留) 138 | 139 | * 4: time_delay 定时发送 140 | 141 | * 5: location 位置 142 | 143 | * 6: qos 144 | 145 | * 7: apn_json,包含以下键: 146 | 147 | ``` 148 | expiration: number (maybe NULL) 149 | priority: number (maybe NULL) 150 | alert: string or dictionary (maybe NULL) 151 | dictionary: (暂时不做检查) 152 | badge: number (maybe NULL) 153 | sound: string (maybe NULL) 154 | content-available: number (maybe NULL) 155 | extra: dictionary (自定义参数, maybe NULL) 156 | ``` 157 | 158 | ## 特殊 topic 的定义 159 | 160 | * topic 为 ”,yta/alias“,表示发送该消息到一个别名为 alias 的用户。 161 | 162 | * topic 为 ”,yali“,表示设置别名。消息内容为别名。 163 | 164 | * topic为 ”,yaliget“,表示获取别名。 165 | 166 | -------------------------------------------------------------------------------- /product_kb_offline_message.md: -------------------------------------------------------------------------------- 1 | # 云巴的离线消息 2 | 3 | ## 功能介绍 4 | 5 | 云巴的消息通道目前基于 IP 连接,由于网络的不完全可靠性及用户自身的使用习惯,通过云巴发消息时,常常会遇到客户端不在线的情形。 6 | 7 | 云巴提供了离线消息机制:只要在发消息时,将 [QoS](product_kb_qos.md) 参数设置为 1 或 2,就能够保证消息的送达。(建议设置为 QoS 1) 8 | 9 | > **最佳实践:近期,云巴 QoS 2 的逻辑正在优化中,建议使用 QoS 1,可以考虑在客户端层面进行去重处理。** 10 | 11 | 这意味着,如果接收方的客户端当前不在线的话,消息会暂存在云巴的服务器(多达 50 条,长达 15 天),等到客户端连网时会收到云巴服务器发来的离线消息,客户端收到后,服务器才会删除之前保存的消息。 12 | 13 | >**注**:云巴的离线消息不保证消息的顺序送达。 14 | 15 | 通过设置 `time_to_live` 参数,可以控制离线消息在云巴的服务器上保留多久。 16 | 另外,每个 Topic 的离线消息数量最多不超过 50 条。 17 | 18 | ## 参数说明 19 | 20 | * `qos`:用来设置服务质量等级。有三种取值:0 表示最多送达一次;1 表示最少送达一次;2 表示保证送达且仅送达一次。默认为 1。 21 | 详见 [官方文档](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718099)。 22 | 23 | * `time_to_live`:用来设置离线消息保留多久。单位为秒(例如,3600 代表 1 小时),默认值为 3 天,最大不超过 15 天。 24 | -------------------------------------------------------------------------------- /product_kb_packet_capture.md: -------------------------------------------------------------------------------- 1 | # 使用 Wireshark 对移动设备进行抓包 2 | ***运行环境需求:*** 3 | 4 | * Wireshark 2.2.1 5 | * 一台可以 Wi-Fi 共享的 Mac (macOS Sierra 10.12.1) 6 | 7 | ## 准备步骤 8 | 1. 在[官网](https://www.wireshark.org/)下载 Wireshark,然后安装。 9 | 2. 开启 Wi-Fi 共享,如需帮助可以参考[这里](http://jingyan.baidu.com/article/17bd8e52e344cf85ab2bb8f0.html)。 10 | 3. 按照 [这个插件](https://github.com/johnzeng/Wireshark-MQTT) 的usage段安装mqtt插件,然后即可解析云巴mqtt协议。 11 | 12 | ## 开始进行 13 | 首先,打开 Wireshark,选择捕获的接口,本教程是通过 Wi-Fi 来进行抓包的,所以选择 Wi-Fi:en0。***注意:多个无线网卡可能会有多个选项,选择你用来进行共享的接口即可*** 14 | 15 | ![productpng_kb_packet_capture_wireshark.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_packet_capture_wireshark.png) 16 | 17 | 把要进行抓包的设备连接到你分享出去的 Wi-Fi,就可以看到设备上的网络包接收和发送的情况,在`显示过滤器`中输入`mqtt`,就可以只观察 mqtt 的包。 18 | 19 | ![productpng_kb_packet_capture_wireshark_mqtt.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_packet_capture_wireshark_mqtt.png) 20 | 21 | ## 观察云巴服务 22 | 保持云巴的服务在前台,就可以观察云巴的服务运行状况,帮助定位问题。下面简单说明一下常见的云巴 MQTT 包的含义。 23 | 24 | 1. Connect Command 连接到云巴服务的信息,包含 client ID,username,password 等连接信息。 25 | ![productpng_kb_packet_capture_wireshark_connect_command.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_packet_capture_wireshark_connect_command.png) 26 | 2. Publish Message 包含推送的消息和频道等信息。 27 | ![productpng_kb_packet_capture_wireshark_publish_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_packet_capture_wireshark_publish_message.png) 28 | 3. Ping Request 心跳包,可用来观察设备是否和云巴服务正常连接。 29 | 30 | ## 补充 31 | * 使用 Wireshark 同时也可以进行其它设备的抓包,原理是类似的,只要把监听的接口设置成设备所在的网络即可,不赘述。 32 | 33 | * 可以在[这个网站](http://whatismyipaddress.com/)获取自己的 IP 地址。 34 | -------------------------------------------------------------------------------- /product_kb_param.md: -------------------------------------------------------------------------------- 1 | # 参数说明 2 | 3 | 本文用来对 SDK 中的部分常见参数进行综合的解释说明。 4 | 5 | ## topic 6 | 7 | `topic` 用来表示 [频道名称](product_kb_topic_and_alias.md#%E9%A2%91%E9%81%93%E5%90%8D%E7%A7%B0) 或 [频道过滤器](product_kb_topic_filter.md#%E9%A2%91%E9%81%93%E8%BF%87%E6%BB%A4%E5%99%A8)。 8 | 9 | - `topic`作为频道名称时,允许的字符包括:英文大小写字母、数字、下划线`_`和正斜杠`/`。 10 | - `topic`作为频道过滤器时,允许的字符包括:英文大小写字母、数字、下划线`_`、正斜杠`/`,以及表示通配符的`#`和`+`。 11 | 12 | ### 取值范围 13 | 14 | - 下列 API 中的`topic`可以作为 [频道名称](product_kb_topic_and_alias.md#%E9%A2%91%E9%81%93%E5%90%8D%E7%A7%B0) 或 [频道过滤器](product_kb_topic_filter.md#%E9%A2%91%E9%81%93%E8%BF%87%E6%BB%A4%E5%99%A8)。**取值范围为:英文大小写字母、数字、`_`、`/`、`#`和`+`,长度不超过 128 个字符。** 15 | 16 | - `subscribe()`(或`MQTTClient_subscribe`) 17 | - `unsubscribe()`(或`MQTTClient_unsubscribe`) 18 | - `get_alias_list()`(或`getAliasList()`、`MQTTGetAliasList()`等类似名称) 19 | 20 | - 下列 API 中的`topic`只能是 [频道名称](product_kb_topic_and_alias.md#%E9%A2%91%E9%81%93%E5%90%8D%E7%A7%B0)。**取值范围为:英文大小写字母、数字、`_`和`/`,长度不超过 128 个字符。** 21 | 22 | - `publish()`(或`MQTTClient_publish`) 23 | - `publish2()`(或`MQTTClient_publish2`) 24 | - `subscribe_presence()`(或`MQTTClient_presence`) 25 | - `unsubscribe_presence()`(或`MQTTClient_unpresence`) 26 | 27 | - `topics`数组的元素个数不超过 100。 28 | 29 | - `/p`是 [Presence](product_kb_presence.md) 的保留字(例如,`subscribe("t/p")`相当于`subscribe_presence("t")`)。为了避免混淆,建议避免在`topic`参数中使用`/p`字符,如需订阅某频道的 Presence,可直接调用 Presence 相关的 API。 30 | 31 | ## alias 32 | 33 | `alias` 用来表示 [别名](product_kb_topic_and_alias.md)。 34 | 35 | **注意** 36 | 37 | - 同一个 AppKey 下,alias 是唯一的,不能有重复。假设 Client 1 别名为 A;此时如果设置 Client 2 的别名为 A 则 Client 1 的别名将会失效。 38 | 39 | - 设置别名为空字符串,可以取消别名。 40 | 41 | ### 取值范围 42 | 43 | - `alias`的取值范围为:英文(大小写)、数字、下划线`_`,长度不超过 128 个字符。 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /product_kb_portal.md: -------------------------------------------------------------------------------- 1 | # Portal 2 | 3 | ## 功能 4 | Portal,即 “门户”。云巴的 Portal 是用户应用的管理入口,后端连接着云巴的实时消息系统。 5 | 6 | 用户在云巴官网注册并登录后,可以通过点击页面右上方的用户名进入 Portal 页面。 7 | 通过云巴的 Portal 页面,可以创建和管理应用、发布消息、查看统计信息,还可以查看通过 Portal 发布过的消息的历史记录。 8 | 9 | 常有客户疑惑,为什么只有一个设备在线时,Portal 的活跃用户统计数量却是 2 ?原因很简单,Portal 也同时是一个 [JavaScript](https://github.com/yunba/yunba-javascript-sdk) 客户端,可以向指定应用([AppKey](product_kb_app_key.md))的指定 Topic/Alias 发布消息,因此会算在统计内。 10 | 11 | ## 如何在云巴 Portal 上创建新应用 12 | 13 | 如图所示: 14 | 15 | ![productpng_portal_creat_new_app.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_creat_new_app.png) 16 | 17 | - 打开[云巴官方网站](https://yunba.io),注册并登录。 18 | - 登录后,点击网页右上角的用户名,会进入 Yunba Portal 主界面,点击右上角 “创建应用”。 19 | - 逐一填写应用信息。其中,“应用名称” 和 “应用包名” 是必填项。对于 Android 应用来说,“应用包名” 一项需要填写 “Android” 应用包名。见下图。 20 | - 对于 iOS 应用,在 “iOS 开发/生产证书” 处上传 iOS 开发/生产证书(*.p12)。如果证书导出时有设置密码,需要在 “开发/生产证书密码” 项填上证书的密码。 21 | - 应用信息填写完成后,点击 “确定”,会调转到 “应用列表” 界面。点击应用的 “应用名” 或右侧的 “管理” 按钮,可以打开该应用的管理页面。 22 | - 在 “应用详情” - “基本信息” 页,可以看到应用的 AppKey、Secret Key 等。**请妥善保管好您的 AppKey、Secret Key 等应用信息,不要在群聊等公众场合下泄露。** 23 | - 在 “应用详情” - “RESTful API Quick Demo” 页,我们给出了通过 RESTful API 的 `Publish` 和 `Publish_to_alias` 向 Portal 发消息的示例。为了方便演示,我们将 Portal 客户端订阅了 `yunba_curl_demo` [频道](product_kb_topic_and_alias.md),并将其 [别名](product_kb_topic_and_alias.md) 设置为 `yunba_curl_demo_alias` 用户只需要复制并发送页面上给出的 [cURL](https://curl.haxx.se/docs/manpage.html) 命令,就可以看到消息收发的效果。如下图所示: 24 | 25 | ![productpng_portal_restful_demo.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_restful_demo.png) 26 | 27 | 28 | ## 利用云巴 Portal 发布消息 29 | 30 | ### 通过 Publish 向频道发布消息 31 | 32 | 可以向客户端 `subscribe` 的 [频道](product_kb_topic_and_alias.md)(Topic)发布消息,客户端即可收到消息,如图所示: 33 | 34 | ![productpng_portal_publish_to_topic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_to_topic.png) 35 | 36 | 在客户端(以 Android 客户端为例)订阅频道: 37 | 38 | ![androidpng_demo_app_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_demo_app_message.png) 39 | 40 | 客户端收到 Portal 发布的消息: 41 | 42 | ![androidpng_demo_notification.png](https://raw.githubusercontent.com/yunba/docs/master/image/androidpng_demo_notification.png) 43 | 44 | ### 通过 Publish2 向频道发布消息 45 | 46 | 此外,Portal 还提供了通过 Publish2 发布消息的功能。 47 | 48 | - 点击 **更多选项** 可设置 [离线消息](product_kb_offline_message.md) 保留时间(Time To Live)、[QoS](product_kb_qos.md) 值 和 Message ID(如果不填则由系统自动生成) 49 | - 可设置 **APN JSON** 发送 APNs 消息,发送 APNs 消息的方法具体可参考 [如何通过云巴实现 APNs 推送](ios_kb_apns_implementation.md) 和 [APNs 参数设置](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1)。 50 | 51 | ![productpng_portal_publish2_to_topic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish2_to_topic.png) 52 | 53 | 54 | 55 | ### 通过 Publish 向别名发布消息 56 | 57 | 58 | 如果客户端通过 `SetAlias` 设置了[别名](product_kb_topic_and_alias.md),用户还可以通过 Portal 向客户端的别名发布消息: 59 | 60 | ![productpng_portal_publish_to_alias.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_to_alias.png) 61 | 62 | 此时,同一 AppKey 下,别名为 Jack 的客户端就会收到该条消息。 63 | 64 | ### 通过 Publish2 向别名发布消息 65 | 66 | 类似地,也可以通过 Publish2 发布消息,带更多的参数,如下图。设置了该别名的客户端会收到消息。 67 | 68 | - 点击 **更多选项** 可设置 [离线消息](product_kb_offline_message.md) 保留时间(Time To Live)、[QoS](product_kb_qos.md) 值 和 Message ID(如果不填则由系统自动生成) 69 | - 可设置 **APN JSON** 发送 APNs 消息,发送 APNs 消息的方法具体可参考 [如何通过云巴实现 APNs 推送](ios_kb_apns_implementation.md) 和 [APNs 参数设置](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1)。 70 | 71 | ![productpng_portal_publish2_to_alias.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish2_to_alias.png) 72 | 73 | 74 | ### 在 Portal 上查看消息历史 75 | 76 | 点击 **消息历史** 可查看使用此 appkey 发送的所有消息(包括你在 Portal 上发送的消息)。 77 | 78 | 点击 **Portal 发送的消息** 可以查看在 Portal 上发送的消息。 79 | 80 | ![productpng_portal_portal_publish_history](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_portal_publish_history.png) 81 | 82 | 点击 **所有消息** 可以查看使用此 appkey 发送的所有消息。支持按时间、频道或别名过滤消息。 83 | 84 | ![productpng_portal_publish_history](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_history.png) 85 | 86 | 87 | ## 云巴 Portal 的发布上报统计 88 | productpng_portal_publish_statistic.png 89 | ![report.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_publish_statistic.png) 90 | 91 | 如图所示,可查看该应用([AppKey](product_kb_app_key.md)) 下的消息发布和送达情况。 92 | 93 | 蓝色波形为一定时间(10 秒、分钟、小时、日)内的消息发布数量;黑色波形为一定时间内的消息送达数量。(Portal 也属于一个用户) 94 | 95 | ## 云巴 Portal 的在线用户统计 96 | 97 | ![online.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_online_statistic.png) 98 | 99 | - 一段时间内的在线用户数:该时间段内持续在线(connected)的用户数量。如:“在线用户数/小时” 的单位表示该小时内持续在线,未断开与云巴的长连接的用户数量。 100 | - 一段时间内的活跃用户数:该时间段内进行过上线操作的用户数量(不一定持续在线)。如:“活跃用户数/小时” 的单位表示该小时内进行过上线操作,即连接过云巴服务的用户数量。 101 | 102 | >**注**:如果订阅了该 Topic 但未设置用户 [别名](product_kb_topic_and_alias.md)(Alias),则在 “在线用户”和“频道用户列表” 都不进行显示。 103 | 104 | ### 频道用户列表 105 | 106 | 点击 **频道用户列表**,可查看应用([AppKey](product_kb_app_key.md)) 下某个 [频道](product_kb_topic_and_alias.md) 的收听用户别名列表。 107 | 108 | 109 | ## 云巴 Portal 的设备状态查询 110 | 111 | ![productpng_portal_alias_state.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_alias_state.png) 112 | 113 | 输入设备 [别名](product_kb_topic_and_alias.md) 后,可以查看该设备的 UID、当前的在线/离线状态,以及最近一次上线的时间。 114 | 115 | ## 应用账单管理 116 | 117 | 云巴在 2017 年年初,上线了针对免费版和基础版用户的 [新的价格方案](http://blog.yunba.io/yun-ba-yunba-io-xin-jie-ge-fang-an-ji-jiang-shang-xian/)(详见 [价格页面](https://yunba.io/pricing/) 和 [计费规则](https://yunba.io/docs/product_kb_pricing_details))。 118 | 119 | 云巴 Portal 也相应做出了调整。 120 | 121 | ### 应用列表 122 | 123 | 如图所示,用户在“应用列表”页,可以查看各个应用的日活和消息量(数值会有五分钟左右的延迟),不同的日活对应的档次也显示在应用卡片上。 124 | 125 | ![productpng_portal_apps.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_apps.png) 126 | 127 | - 应用自出现第一个日活开始(第一个设备接入云巴服务器),就会按照 30 个自然日为单位进行周期性结算,并自动生成账单;在 Portal 的应用列表页面会显示账单生成日的倒计时(参考上图左侧的卡片)。 128 | - 随着日活的增长,应用会自动升级(详见 [价格页面](https://yunba.io/pricing/)):当日活超过 100 时,会由免费版本自动升级为基础 A 档;超过 1000 时,升级为基础 B 档;超过 5000 时,会升级为基础 C 档;超过 10000,则需要联系商务开通专业版。 129 | - 账单生成后,系统会自动进行扣费,如果扣费时余额不足,应用会进入欠费状态(参考上图中间的卡片);用户需要在 20 天内登录 Portal 的“我的账单”页面手动进行缴费,否则,应用会进入免费版受限状态(参考上图右侧的卡片);详见 [计费规则](https://yunba.io/docs/product_kb_pricing_details)。 130 | 131 | ### 我的账单 132 | 133 | 在“我的账单”页面,用户可以查看各个应用的日活、消息量和账单状态,并对欠费账单进行手动缴费。 134 | 135 | ![productpng_portal_bills.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_bills.png) 136 | 137 | 138 | ### 收支管理 139 | 140 | 在“收支管理”页面,用户可以进行账号充值。目前支持“微信”和“支付宝”两种支付方式。用户可以在账单结算日之前提前进行充值,以保证自动扣费成功。 141 | 142 | ![productpng_portal_payment.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_payment.png) 143 | 144 | 145 | -------------------------------------------------------------------------------- /product_kb_presence.md: -------------------------------------------------------------------------------- 1 | # 实时在线(Presence) 2 | 3 | ## 1. Presence 的由来 4 | 5 | 在 MQTT 协议中,并没有提供用户上、下线等行为的消息通知。于是,我们利用 MQTT 现有的一些特性,设计了 Presence。 6 | 7 | ## 2. 什么是 Presence 8 | 9 | 实时在线(Presence)是云巴提供的实时获取某个频道下所有用户([别名](product_kb_topic_and_alias.md))的上、下线通知以及订阅、取消订阅该频道的通知。 10 | 11 | 订阅了某个频道的 Presence 后,可以监听到的通知包括: 12 | * Online/Offline:该频道下某个已经设置了别名的用户的“上/下线通知”。 13 | * Join/Leave:某个已经设置了别名的用户订阅该频道的“加入/离开通知”。 14 | 15 | 从这个定义可以看出,**使用 Presence,只能监听已经设置了 [别名](product_kb_topic_and_alias.md) 的客户端,未设置 [别名](product_kb_topic_and_alias.md) 的客户端不会被监听。** 16 | 17 | 18 | >Q: 为什么客户端必须设置别名呢? 19 | 20 | >A: 由于 Presence 消息针对的是客户端的订阅动态和在线状态,因此,消息必须有一个客户端主体。 21 | 在云巴系统内部,会为每一个连接云巴的客户端生成一个唯一的标识符,即 UID。 22 | 由于这个 UID 是一串无意义的字符串,不便于对外公开和使用,因而,我们设计了“别名”的概念来取代 UID。 23 | 用户可以通过为客户端设置不同的 “[别名](product_kb_topic_and_alias.md)” 来唯一标识客户端。 24 | 25 | 26 | ## 3. Presence 举例 27 | 28 | 29 | 30 | ### 例一 31 | 32 | 请先看一个最简单的场景,初步了解 “Join/Leave/Online/Offline” 四种消息的含义: 33 | 34 | **描述** 35 | * 有一个频道,名为 Room 36 | * 有两个客户端,别名 分别为 Alex 和 Bob 37 | * 头像 **在 Room 内/外** 表示 **订阅/未订阅 Room** 38 | * 头像 **绿色/灰色** 表示 **在线/离线** 39 | * 头像 **有/无 眼睛图标** 表示 **订阅/未订阅 Room 的 Presence 消息** 40 | 41 | **Join/Leave 通知:** 42 | ![productpng_kb_presence_join_and_leave.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_presence_join_and_leave.png) 43 | 44 | **Online/Offline 通知:** 45 | ![productpng_kb_presence_on_offline.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_presence_on_offline.png) 46 | 47 | 48 | ### 例二 49 | 50 | 前文有提到,Presence 消息仅对设置了 别名 的客户端有效。 51 | 52 | 那么,客户端是否设置 别名 对 Presence 消息的收发具体有怎样的影响呢?请看下面两个例子: 53 | 54 | **描述** 55 | * 有一个频道,名为 Room 56 | * 有五个客户端,内部 UID 分别为 1001,1002,1003,1004 和 1005 57 | * UID 1001 和 1002 已经分别设置了 别名 Alex 和 Bob 58 | * UID 1003、1004 和 1005 未设置 别名 59 | * 头像 **在 Room 内/外** 表示 **订阅/未订阅 Room** 60 | * 头像 **绿色/灰色** 表示 **在线/离线** 61 | * 头像 **有/无 眼睛图标** 表示 **订阅/未订阅 Room 的 Presence 消息** 62 | 63 | ![productpng_kb_presence_b1.gif](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_presence_b1.gif) 64 | 65 | ![productpng_kb_presence_b2.gif](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_presence_b2.gif) 66 | 67 | 通过这个例子,可以看出: 68 | 69 | * **订阅了 Presence 才能收到 Presence 的消息** 70 | >上例中,UID 1005 虽然订阅了 Room 频道,但未订阅 Room 的 Presence,因而不会收到 Presence 消息; 71 | 72 | * **Presence 消息只对设置了别名的客户端有效** 73 | >上例中,UID 1003 和 1004 未设置别名,因而当他们进出房间或上下线时不会有 Presence 消息发出; 74 | 75 | * **Presence 消息的订阅者本身并不要求有别名** 76 | >上例中,别名为 Alex 的客户端和未设置别名的 UID 1003 或 1004 都可以收到 Presence 消息; 77 | 78 | ## 4. Presence 的原理 79 | 80 | Presence 的实质是,对 [频道](product_kb_topic_and_alias.md) 下所有用户 [别名](product_kb_topic_and_alias.md) 的状态的订阅。成功订阅后,Topic 下的任何用户别名的状态一旦发生变化,都会向 Topic + '/p' 频道发送消息。 81 | 82 | 例如,某用户(客户端)通过调用 `subscribe_presence("news")` 来监控 news 频道下的 Presence 消息。 83 | 调用成功后,云巴系统会自动为该客户端订阅一个名为 news/p 的频道,并将 news 频道的所有的 Presence 消息发给 news/p,让用户可以实时掌控该频道所有的 Presence 消息。 84 | 85 | >**注**:在调用 Presence API 时,系统自动为用户订阅的 Topic + '/p' 是一个特殊的频道,不会出现在用户实际的订阅列表中。 86 | 87 | ## 5. 相关 API 88 | 下面以 [JavaScript SDK](https://github.com/yunba/yunba-javascript-sdk) 为例,介绍一下与频道相关的 API。 89 | 90 | * [`subscribe_presence`](js_sdk_api_manual.md#subscribe_presence) 用来监听某个频道下所有用户的别名状态的变化。 91 | * [`unsubscribe_presence`](js_sdk_api_manual.md#unsubscribe_presence) 用来取消对某频道下用户别名状态变化的监听。 92 | 93 | 以云巴 [JavaScript SDK Demo](js_demo_quick_start.md) 为例。假设频道 news 下有一个名为 defy 的用户,下线后又立刻上线;后有一个名为 cat 的用户订阅了 news 频道,之后又立刻取消订阅。如果通过 `subscribe_presence` 订阅了 news,就可以实时获取到 defy 和 cat 的状态变化。 94 | 打印信息如下: 95 | 96 | * 来自频道:news/p 消息内容:{"action":"offline","alias":"defy","timestamp":1454321557378} 97 | * 来自频道:news/p 消息内容:{"action":"online","alias":"defy","timestamp":1454321558995} 98 | * 来自频道:news/p 消息内容:{"action":"join","alias":"cat","timestamp":1454321577648} 99 | * 来自频道:news/p 消息内容:{"action":"leave","alias":"cat","timestamp":1454321585416} 100 | 101 | -------------------------------------------------------------------------------- /product_kb_pricing_details.md: -------------------------------------------------------------------------------- 1 | # 云巴产品计费规则 2 | 3 | 本文针对云巴官方网站的 [价格页面](https://yunba.io/pricing/) 作补充说明。 4 | 5 | ## 计费规则 6 | 7 | 本计费规则仅针对免费版和基础版用户,专业版和私有云的用户不受影响。 8 | 9 | 应用开始使用后,会以后付费的方式,每 30 天进行一次结算。结算时,会根据用户的实际使用情况自动匹配对应的档次,如达到付费档次的标准,会进行扣费。如果用户未按时缴清欠款,会影响后续的使用。详见下方说明。 10 | 11 | ### 计费规则 12 | 13 | - 应用创建后,自出现第一个日活开始(第一个设备接入云巴服务器),每 30 个自然日进行一次结算,并自动生成账单。每次结算时,按照前 30 天日活的峰值,决定所对应的档次。可参考 [价格页面](https://yunba.io/pricing/) 的表格。 14 | - 再根据该档次的限额判断“消息量”和“频道数量”是否超额。 15 | 16 | >费用 = 日活峰值对应档次的费用 + 消息量、频道数量超额费用 17 | 18 | ### 扣费规则 19 | 20 | - 用户可以随时进行充值或提现,充值金额在开票后不可以提现。 21 | - 结算日生成账单后,如果账户内余额充足,会自动扣费,否则会扣费失败,扣费失败会有邮件和短信提醒。 22 | - 扣费失败后,会产生欠费账单,用户需要尽快充值,并付清该应用的账单款项,避免服务受到影响。 23 | 24 | ### 欠费处理 25 | 26 | - 结算日生成账单后,如果存在欠费,应用还可以正常使用 20 天,之后会进入免费版受限状态(免费版受限状态:仅可使用免费版,超过其日活限制的客户端无法连接云巴服务器,消息量、频道数量也受限于免费版规定的额度)。 27 | 28 | - 日活超过基础版 C 档时,用户需要联系商务开通专业版,如未开通,用户可以正常使用 30 天,此后会进入基础版 C 档内受限状态(基础版 C 档内受限状态:可以正常使用基础版 C 档,超出其日活限制的客户端无法连接云巴服务器,消息量、频道数量也受限于基础版 C 档规定的额度)。 29 | 30 | 31 | ## 计费举例 32 | 33 | ### 扣费日期举例 34 | 35 | 某用户在 2016/12/27 创建了应用。30 天后,即在第 31 天(2017/1/26)时,就会生成 2016/12/27 - 2017/1/25 的账单,包括当月日活所对应档次的费用,消息量、频道超出部分的费用。 36 | 37 | ### 扣费金额举例 38 | 39 | A 用户的应用在第 31 天结算时, 40 | - 实际日活在 249 元的基础 A 档次,则结算时会按照 249 元计费; 41 | - 实际消息量为 1230 万条,按照基础 A 的标准(500 万条)超出了 730 万条,按照每超出 100 万条需要多收 5 元计算,结算时需要另外支付 40 元; 42 | - 实际频道数量用了 100 个,按照基础 A 的标准(1500 个),未超出限额,不会产生额外费用; 43 | 44 | 因此,A 用户在第 31 天结算时,其账户需缴费用为:249 + 40 = 289 元。 45 | 46 | ### 欠费处理举例 47 | 48 | 日活为 4000(基础 B)的某应用,在结算日过后欠费了 20 天,就会变为免费受限状态,此后,该应用的日活会被限制在 100 以内,超出部分的客户端将无法连接云巴服务器。缴清欠费后,应用可以正常使用。 49 | 50 | ## 名词解释 51 | 52 | - 日活:日活跃用户数。一段时间内的活跃用户数是指该时间段内进行过上线操作的用户数量(不一定持续在线)。结算时,计算的是 30 天内,活跃用户最多的一天的活跃用户数量。 53 | - 消息量:按云巴服务器发出的消息来计算,qos 0:算 0.5 条,qos 1、2:算 1 条。结算时,计算的是 30 天内,累积的消息数量。 54 | - 权限管理:提供 App、Topic、Token 三个层级的权限控制权。详见官方文档。 55 | - 第三方推送:集成了华为等厂商的推送,实现了在应用被杀的情况下,也能收到通知,引导用户打开应用。同时,支持自动创建华为等应用。 56 | - 在线用户数量统计:对一段时间内持续在线的用户的数量进行统计。 57 | - 活跃用户数量统计:对一段时间内连接过云巴服务器的用户数量(不一定持续在线)进行统计。 58 | - 加密链接:支持 https。使用 SSL/TLS 方式进行连接,则 port 为 443;否则,port 为 3000。 59 | - 送达确认:当第一个目标用户(且不是消息发布者)收到消息并向服务器回复了 puback 后,服务器给消息发布者发送一个 recvack。借助这个通知,消息发布者可以了解第一个收到消息的用户的 alias 和 时间戳。 60 | - IP 固定:云巴服务的 IP 是不固定的。开通这项功能,我们可以提供 Broker 的地址和端口。 61 | - 性能优化:包括存储优化、架构调优、网络链路优化等。 62 | - 跨机房数据备份:按机房数量额外收费,具体内容请联系商务咨询。 63 | - 99.999% 可用 SLA:开通“跨机房数据备份”服务,且使用三个机房或以上,即可支持此项服务,具体报价请联系商务。SLA,即 Service-level Agreement。99.999% 可用 SLA 具体的宕机时间可参考:https://uptime.is/99.999 64 | 65 |   66 | -------------------------------------------------------------------------------- /product_kb_pub_sub.md: -------------------------------------------------------------------------------- 1 | # 发布订阅模型 2 | 3 | 4 | [如前所述](https://yunba.io/docs/product_kb_whats_yunba),云巴是一个跨平台的双向实时通信系统。云巴兼容标准的 [MQTT](http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html) 3.1 协议,并做了部分[扩展](https://yunba.io/docs/product_kb_mqtt_porting)。 5 | 6 | 本文简单介绍一下 MQTT 协议中的发布/订阅模型。 7 | 8 | ## 概念 9 | 10 | ![productpng_kb_pub_sub_1.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_pub_sub_1.png) 11 | 12 | 发布/订阅(Publish/Subscribe 或 Pub/Sub)是一种消息范式。 13 | 14 | 区别于传统的 Client/Server 模型,在 Pub/Sub 模型中,Publisher(消息的发布者)和 Subscriber(消息的订阅者)互相不知道对方的存在,而是借助 Broker 进行通信。 15 | 16 | Broker 是类似于中介作用的第三方,主要作用是存储和转发消息。每一个 Client 都只能与 Broker 进行连接,连接建立后,通过 Broker 收发消息。每一条消息都会指定一个 [Topic](product_kb_topic_and_alias.md)。收到 Publisher 发来的消息后,Broker 会根据 Topic 进行过滤,将消息分发给对 Topic 感兴趣的 Subscriber。 17 | 18 | ## 特点 19 | 20 | Broker 的引入,实现了 Publisher 和 Subscriber 在空间上、时间上和同步操作方面的解耦,带来了更好的可扩展性和更为动态的网络拓扑。 21 | 22 | * Publisher 和 Subscriber 之间无须建立联系 23 | * 在消息收发的过程中,不要求 Publisher 和 Subscriber 同时在线 24 | * Client 以异步的方式收发消息,不会阻碍其他任务的进行 25 | 26 | ## 举例 27 | 28 | 下面给出两个实际的应用场景。 29 | 30 | 31 | **图一** 32 | 33 | 下图中,两个智能灯泡订阅了名为 Light 的 Topic,智能手机向 Light 发消息,云巴 MQTT Broker 将消息转发给了灯泡。 34 | 35 | ![productpng_kb_pub_sub_2.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_pub_sub_2.png) 36 | 37 | **图二** 38 | 39 | 下图中,智能温度计向名为 Temperature 的频道发消息,云巴 MQTT Broker 将消息转发给了该频道的订阅者。未订阅的客户端不会收到消息。 40 | 41 | ![productpng_kb_pub_sub_3.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_pub_sub_3.png) 42 | 43 | 注意,上方的示意图仅演示了单向的消息传输,云巴支持 [双向的消息通信](https://yunba.io/docs/product_kb_whats_yunba#%E5%8F%8C%E5%90%91)。基于发布/订阅原理,在图一中,灯泡可以通过订阅频道的方式接收来自智能手机的消息,智能手机也可以通过订阅频道的方式接收灯泡端上报的消息。 44 | -------------------------------------------------------------------------------- /product_kb_qos.md: -------------------------------------------------------------------------------- 1 | # QoS 2 | 3 | 云巴兼容标准的 MQTT 3.1 协议,本文介绍一下协议中的 [QoS](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718099)。 4 | 5 | ## QoS 定义 6 | 7 | QoS,全称为 Quality of Service,即服务质量。在 MQTT 协议中,QoS 可分为以下三个等级: 8 | 9 | * “QoS = 0”: At most once. Fire and Forget. (至多一次,发完即删,不保证送达。) 10 | * “QoS = 1”: At least once. Acknowledged delivery. (保证至少送达一次。) 11 | * “QoS = 2”: Exactly once. Assured delivery. (保证送达,且仅送达一次。) 12 | 13 | > **最佳实践:近期,云巴 QoS 2 的逻辑正在优化中,建议使用 QoS 1,可以考虑在客户端层面进行去重处理。** 14 | 15 | ## 不同 QoS 等级下的消息流 16 | 17 | ### QoS = 0 18 | 19 | QoS 为 0 时,消息发送后,无论服务端有没有收到这条消息,都不会重发,也不会等任何回应。 20 | 这种即发即删的传输方式无疑是最高效的,网络通信的压力也比较小。 21 | 22 | |客户端|消息以及消息流向|服务器| 23 | |:----:|:----:|:----:| 24 | | QoS = 0| -- PUBLISH --> | 向订阅者发布消息 | 25 | 26 | ### QoS = 1 27 | 28 | QoS 为 1 时,服务器收到消息后会回应一个 PUBACK。 29 | 如果发送方或者通信链路出了问题,或是在既定的时间内没收到 PUBACK 的话, 30 | 发送方会把 DUP 置位,并重发消息。服务器收到重发来的消息,会重新发布给订阅者,并再次回复 PUBACK 给发送方。 31 | 因而消息至少送达一次。 32 | 在 MQTT 协议中,SUBSCRIBE 和 UNSUBSCRIBE 消息的 QoS 都为 1 级。 33 | 34 | QoS 为 1 时,消息会带 Message ID。 35 | 36 | |客户端|消息以及消息流向|服务器| 37 | |:----:|:----:|:----:| 38 | | QoS = 0
DUP = 0
Message ID = x| -- PUBLISH --> | 存储消息
向订阅者发布消息
删除消息 | 39 | |丢弃消息| <-- PUBACK -- | - | 40 | 41 | ### QoS = 2 42 | QoS 2 级是 QoS 1 级的升级版,也是消息传输的最高等级。 43 | 它不仅能保证消息送达,且保证只送达一次。 44 | 45 | 与 QoS 1 级一样,QoS 2 级的消息也带有 Message ID。 46 | 47 | 服务端接收到消息后,有两种处理流程,这两种流程效果相同。 48 | 49 | |客户端|消息以及消息流向|服务器| 50 | |:----:|:----:|:----:| 51 | | QoS = 2
DUP = 0
Message ID = x| -- PUBLISH --> |存储消息 | 52 | |丢弃消息| <-- PUBACK -- | Message ID = x| 53 | |Message ID = x | --PUBREL--> |向订阅者发布消息
删除消息| 54 | |丢弃消息| <--PUBCOMP--|Message ID = x| 55 | 56 | 57 | |客户端|消息以及消息流向|服务器| 58 | |:----:|:----:|:----:| 59 | | QoS = 2
DUP = 0
Message ID = x| -- PUBLISH --> | 存储 Message ID
向订阅者发布消息 | 60 | |丢弃消息| <-- PUBACK -- | Message ID = x| 61 | |Message ID = x | --PUBREL--> |删除消息| 62 | |丢弃消息| <--PUBCOMP--|Message ID = x| 63 | 64 | 如果传输过程中检测到错误,或者既定时间内没收到期待的回应,则会从没收到确认消息的出错处开始尝试重发。 65 | 即,重发 PUBLISH 或重发 PUBREL。 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /product_kb_topic_and_alias.md: -------------------------------------------------------------------------------- 1 | # 频道和别名 2 | 3 | 云巴支持 频道 和 别名 两种发布消息的方式。 4 | 5 | ## 概述 6 | 7 | ### 通过“频道”进行一对多的消息发布 8 | 9 | ![productpng_kb_publish2topic.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_publish2topic.png) 10 | 11 | - `Subscriber 1` 订阅了 `Topic A`,而 `Subscriber 2` 和 `Subscriber 3` 订阅了 `Topic B`; 12 | - `Publisher 1` 向 `Topic A`发布消息,则 `Subscriber 1` 可以收到; 13 | - `Publisher 2` 向 `Topic B` 发布消息,则 `Subscriber 2` 和 `Subscriber 3` 可以收到。 14 | 15 | ### 通过“别名”进行一对一通信 16 | 17 | ![productpng_kb_publish2alias.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_publish2alias.png) 18 | 19 | - `Client 1` 设置自己的别名; 20 | - `Client 2` 设置自己的别名; 21 | - `Client 1` 和 `Client 2` 向对方的别名发布消息,进行一对一的通信。 22 | 23 | ## 频道(Topic) 24 | 25 | 26 | 在电视广播中,高频影像信号和伴音信号占有一定宽度的频带,叫频道。有了不同的频道,就可以将资讯分门别类地输送给不同的目标受众。云巴的频道(Topic)也是类似的概念。 27 | 28 | ### 频道名称 29 | 30 | 在 MQTT 3.1 协议中,对 Topic Name(又叫 Subject 或 Channel)是这样描述的:The topic name is the key that identifies the information channel to which payload data is published. Subscribers use the key to identify the information channels on which they want to receive published information. 31 | 32 | 简而言之,频道名称 是用来让发布者和订阅者区分不同频道的标识符。云巴的 频道名称 支持英文、数字、正斜杠([频道分级符](product_kb_topic_filter.md#频道分级符))和下划线,长度不超过 128 个字符。 33 | 34 | 35 | ### 频道过滤器 36 | 37 | 在订阅频道时,用于指定频道的字符串中如含有 [频道通配符](product_kb_topic_filter.md#频道通配符)(#、+),则称之为 [频道过滤器](product_kb_topic_filter.md)。 38 | 39 | 40 | ### 频道的特点 41 | 42 | > **最佳实践:为了充分利用云巴服务器的性能、提升通信质量,我们建议用户不要频繁进行 subscribe / unsubscribe 的操作。** 43 |
用户在进行系统架构时,如果能合理地设计 Topic 数量和订阅关系,云巴服务器就能够有效地缓存客户端的路由信息,从而加快通信时的寻址速度,提高通信质量。 44 | 相反地,如果用户把 Topic 当作临时资源来使用(尽管目前暂无限制),则会加重服务器负载,导致通信质量的下降。 45 | 46 | 47 | * 同一个 [AppKey](product_kb_app_key.md) 下,可以创建多个频道,暂无上限。 48 | * 多个用户可以订阅同一个频道;一个用户也可以订阅多个频道。 49 | * 频道和订阅的逻辑均存储在云巴服务器上,一经生成,永不失效。 50 | * 只有订阅了某个频道,才可以收到该频道的消息。 51 | * 只要没有取消订阅某个频道,永远都可以收到这个频道的消息。 52 | * 消息的发布者并不一定需要订阅频道。 53 | * 某个频道在第一次被订阅时,会被自动创建。 54 | * 频道名称对大小写敏感。 55 | 56 | ### 相关 API 57 | 58 | 下面以 JavaScript SDK 为例,介绍一下与频道相关的 API。 59 | 60 | * [`subscribe`](js_sdk_api_manual.md#subscribe) 用来订阅某个频道。订阅频道是增加逻辑,不会影响到现有的订阅情况。 61 | * [`unsubscribe`](js_sdk_api_manual.md#unsubscribe) 取消对某个频道的订阅。 62 | * [`subscribe_presence`](js_sdk_api_manual.md#subscribe_presence) 用来监听某个频道下所有用户的别名状态的变化。 63 | * [`unsubscribe_presence`](js_sdk_api_manual.md#unsubscribe_presence) 用来取消对某频道下用户别名状态变化的监听。 64 | * [`publish`](js_sdk_api_manual.md#publish) 向某频道发布消息。 65 | * [`publish2`](js_sdk_api_manual.md#publish2) 是 `publish` 的升级版本,支持更多参数。 66 | * [`get_topic_list`](js_sdk_api_manual.md#get_topic_list) 用来查询用户订阅的频道列表。 67 | 68 | ### 应用场景 69 | 70 | 频道主要用于一对多发布的场景。服务端和客户端分别集成了云巴的 SDK 后,客户端调用`subscribe`订阅某个 Topic,服务端调用`publish`向该 Topic 发布消息,那么,所有订阅了该 Topic 的客户端都会收到消息。 71 | 72 | ### 取值范围 73 | 74 | API 中的 `topic` 参数的取值范围详见 [参数说明](product_kb_param.md#topic)。 75 | 76 | ## 别名(Alias) 77 | 78 | 79 | ### 什么是别名 80 | 81 | 客户端连到云巴服务器后,会被分配一个唯一的 UID,云巴内部用 UID 来标识 [AppKey](product_kb_app_key.md) 下的不同客户端。由于 UID 是一串毫无规律的字符串,在实际应用中难以辨识,于是我们引入了 别名 的概念。用户可以为每个客户端设置一个有意义的名字——别名,我们会将客户端的 别名 与客户端的 UID 进行绑定,让用户可以通过 别名 来标识客户端,进行一对一通信。 82 | 83 | 别名 只支持英文、数字和下划线,长度不超过 128 个字符。 84 | 85 | ### 别名的特点 86 | * 别名与客户端是一一对应的关系。 87 | * 同一个 Appkey 下,不允许存在重复的别名。 88 | * 别名的设置采用的是覆盖的方式,新设置的别名会覆盖旧的别名。 89 | * 将别名设置为空字符串,即可清除别名。 90 | * 目前,云巴支持同一个账号(别名)在不同的终端上登录,但不支持多终端同时登录。 91 | * 别名对大小写敏感。 92 | 93 | ### 相关 API 94 | 下面以 JavaScript SDK 为例,介绍一下与别名相关的 API。 95 | 96 | * [`set_alias`](js_sdk_api_manual.md#set_alias) 用来设置别名。 97 | * [`get_alias`](js_sdk_api_manual.md#get_alias) 用来获取当前的别名。 98 | * [`get_state`](js_sdk_api_manual.md#get_state) 用来查看某个别名的在线状态。 99 | * [`get_alias_list`](js_sdk_api_manual.md#get_alias_list) 用来获取订阅了某个频道的所有用户的别名。 100 | * [`publish_to_alias`](js_sdk_api_manual.md#publish_to_alias) 向用户别名发送消息。 101 | * [`publish2_to_alias`](js_sdk_api_manual.md#publish2_to_alias) 是 `publish_to_alias` 的升级版本,支持更多参数。 102 | 103 | ### 应用场景 104 | 105 | 在一对一发布的场景中,不同的客户端集成了云巴的 SDK 后,分别通过调用`set_alias`设置自己的别名,就可以用`publish_to_alias`互相收发消息,进行点对点的通信。 106 | 107 | ### 取值范围 108 | 109 | API 中的 `alias` 参数的取值范围详见 [参数说明](product_kb_param.md#alias)。 110 | -------------------------------------------------------------------------------- /product_kb_topic_filter.md: -------------------------------------------------------------------------------- 1 | # 频道过滤器 2 | 3 | 在信息过剩的今天,几乎每一款资讯产品都会对不同话题的信息做出细致的种类和层级划分,让用户可以自主筛选、获得定制的资讯。 4 | 5 | 为了满足这种话题分级管理、筛选订阅的需求,云巴实现了 MQTT v3.1.1 协议中的 [Topic Filter](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718106)(即,频道过滤器),客户端可以借助这一功能实现对不同层级的 [频道](product_kb_topic_and_alias.md) 的筛选订阅。本文将先介绍与之相关的 频道分级符、频道通配符 的概念,再给出 频道过滤器 的说明。 6 | 7 | > 注意:Android、iOS SDK 尚未支持该功能,近期会上线。 8 | 9 | 10 | ## 频道分级符 11 | 12 | 我们用 /(U+002F)表示 频道分级符(Topic level separator)。借助 频道分级符 给频道分级,可以形成一个层次清晰的频道树。 13 | 14 | 含有 频道分级符 的频道称为 多级频道 。例如,sports/ballgame/baseball/play1 就是一个四级频道。 15 | 16 | 17 | ## 频道通配符 18 | 19 | 频道通配符(Topic wildcards),顾名思义,提供的是频道匹配的功能。 20 | 频道通配符 包括多级和单级两种。 21 | 22 | ### 多级通配符 23 | 24 | 多级通配符(Multi-level wildcard)用 #(U+0023)表示,用于匹配任意层级的频道(包含 0 级)。它只能出现在 频道过滤器 的最后一级,且出现时必须占据该层级。 25 | 26 | * 正确示例:sports/# 可以匹配 sports、sports/ballgame、sports/ballgame/baseball 等; 27 | 28 | * 正确示例:# 可以匹配 sports、news、sports/ballgame/baseball 等任意等级的频道; 29 | 30 | * 错误示例:sports/ballgame# 和 sports/ballgame/#/baseball 都是错误的。 31 | 32 | ### 单级通配符 33 | 34 | 单级通配符(Single level wildcard)用 +(U+002B)表示。它可以出现在 频道过滤器 的任意一级,且出现时必须占据该层级。单级通配符 只能匹配其所在的那一级。 35 | 36 | 37 | * 正确示例:ballgame/+/player1 可以匹配 ballgame/baseball/player1、ballgame/basketball/player1 等; 38 | 39 | * 正确示例:ballgame/baseball/+ 可以匹配 ballgame/baseball/player1、ballgame/baseball/player2 等; 40 | 41 | * 正确示例:+ 可以匹配 sports、news 等频道; 42 | 43 | * 错误示例:sports+ 是错误的。 44 | 45 | 46 | ## 频道过滤器 47 | 48 | 在订阅频道时,用于指定目标频道的那串字符串中如含有 频道通配符(#、+),则称之为 频道过滤器(Topic Filter),否则称为 频道名称(Topic Name)。 49 | 50 | 例如,sports/ballgame/baseball 是 频道名称,而 ballgame/+/player1、sports/# 是 频道过滤器。 51 | 52 | 53 | 在频道种类繁多、层级复杂的情况下,如果用户需要订阅的是某一个或多个层级下的频道,就可以在订阅时指定 频道过滤器,借助 频道通配符 匹配相应的频道,实现对一系列频道的订阅。 54 | 55 | * 频道名称 可以包含英文、数字、下划线、正斜杠,长度不超过 128 个字符。 56 | * 频道过滤器 长度不超过 128 个字符,支持付费升级。 57 | 58 | API 中的 `topic` 参数的取值范围详见 [参数说明](product_kb_param.md#topic)。 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /product_kb_whats_yunba.md: -------------------------------------------------------------------------------- 1 | # 云巴是什么 2 | 3 | 云巴(Cloud Bus)是一个跨平台的双向实时通信系统,为物联网、App 和 Web 提供实时通信服务。 4 | 5 | 云巴基于 [MQTT](http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html),支持 [Socket.IO](socketio_api_api_manual.md) 协议,支持 [RESTful API](restful_api_api_manual.md)。 6 | 7 | **更多详情:[《云巴产品白皮书》](https://yunba.github.io/docs/white_paper.pdf)** 8 | 9 | ## 跨平台 10 | 11 | 云巴支持 C、Embeded C、iOS、Android 等多种 SDK,支持 RESTful API,支持 Socket.IO 协议。无论是智能硬件、移动 App,还是 Web 应用的开发者们,只需集成云巴的 SDK,就可以实现不同平台之间的实时通信。 12 | 13 | ## 大规模 14 | 15 | 云巴的产品定位,是提供大规模的实时通信服务,现有的付费用户也大多拥有极其庞大的客户群。云巴的通信系统能够在大规模并发通信的同时依然保证其高实时性。 16 | 17 | ## 双向 18 | 19 | 云巴是一个 Pub/Sub 模型的双向实时系统,任何集成了云巴 SDK 的客户端在连上了云巴服务器(Broker)后,都兼具两种角色——发布者(Publisher)和订阅者(Subscriber)。 20 | 21 | 云巴支持 [频道](product_kb_topic_and_alias.md)(Topic)和 [别名](product_kb_topic_and_alias.md)(Alias)两种发布消息的方式: 22 | * 一对多:客户端可以向某个频道发布(Publish)消息,也可以通过订阅(Subscribe)某个频道来接收消息; 23 | * 一对一:客户端还可以通过设置自己的 “别名” 来实现一对一的通信。 24 | 25 | ## 实时通信 26 | 27 | 实时性是云巴的核心。 28 | 29 | 简单说来,通信耗时主要有两部分,云巴与客户端之间消息收发的耗时和云巴内部数据处理的耗时。 30 | 31 | * 对于前者,云巴维护了与客户端之间的长连接,让客户端一直 “在线”,避免了反复建立 TCP 连接的时间和资源开销; 32 | * 对于内部耗时,云巴的系统目前已经能够做到在巨大的压力下作出快速响应。而最大限度地缩短这一耗时,是云巴长期以来努力的重点,也正是云巴的核心竞争力。 33 | -------------------------------------------------------------------------------- /product_kb_yunba_charitic.md: -------------------------------------------------------------------------------- 1 | # 云巴特色 2 | 3 | ## 零配置无缝切换 4 | 通常,产品的业务逻辑时常会随着服务的变化而变化,比如说针对服务对象的地理位置和规模进行调整和扩展。常规的后台扩展需要进行大量的工作,来解决异地扩展机房、分布式一致性和业务分流等问题,而使用云巴的服务就完全无须有这方面的顾虑。云巴可以实现零配置的业务逻辑切换,你甚至感受不到这些改变的存在,只会觉得快。下面就介绍一下云巴是怎么做到的。 5 | 6 | ![productpng_kb_connect_step](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_connect_step.png) 7 | 8 | 云巴的客户端连接简要而言有三步: 9 | 10 | 1. 客户端向 tick.yunba.io 发送 DNS 请求,此时 tick 服务会根据你的 IP 获悉你的大概位置,从而返回一个就近的 ticket service 的连接信息(称为 A1)供使用。 11 | 2. 客户端获得 A1 后,会使用自身的 Appkey 和 IP 地址等信息来连接 ticket service。ticket service 通过 Appkey 的性质(付费、免费、VIP)和 IP 地址所反映的地理位置来给客户端分配它需要和云巴建立连接的前端服务器(frontend)。这个连接信息我们简称为 A2。 12 | 3. 客户端获得了 A2 以后就会去寻找对应的 frontend 建立 MQTT 或者 web socket 的连接,这样一个连接就成功建立起来了。 13 | 14 | ### 地域切换(海外服务) 15 | 选择就近的服务器来进行交互是保障实时性的重要一环,特别是需要开展海外业务的时候。云巴在上述连接过程中有两个措施来让设备连接最近的服务器: 16 | 17 | * 首先在连接 A1 步骤的 DNS 解析阶段,服务器会给客户端返回一个较近的 ticket 服务器。 18 | * 在 A2 阶段,ticket 也会根据 Appkey、IP 地址返回最适合的 frontend(VIP 用户返回专有线路) 19 | 20 | ### 免费/付费切换(零配置扩容) 21 | 在业务发展壮大后,需要扩容以获得更好的服务质量、更高的并发和带宽,由于云巴的上述服务选择机制,用户完全不用关心升级切换的繁琐步骤,所有通道切换都交由云巴完成。比如你需要更多的资源,我们就会让 ticket 给你返回拥有更多资源的服务器节点;又或者你想要升级现在的独享节点,我们也可以给这个节点进行动态扩容。(注:只针对付费用户)而这一切对于用户而言都是透明的,你完全不用操心。 22 | 23 | ## 跨境通信延迟低 24 | 25 | 此外,云巴还针对跨境访问的延迟问题做了优化。北美、东南亚等地的用户可以通过连接到云巴在香港的服务器,再连到深圳的服务器,从而避免由于国内网络限制所导致的高延迟问题。 26 | 27 | 如图所示,假设在美国西海岸的一个客户端需要跟北京的一个客户端进行通信,如果按照常规国内路线延迟约 200ms,而如果通过云巴在美国西海岸的服务器,连接到香港、深圳的服务器,最后连到北京的这条路线,耗时约为 90ms(美国西海岸到香港)、3ms(香港到深圳)、30ms(深圳到北京)。比常规路线节省了约 80ms。 28 | 29 | 目前该项服务仅开放给付费用户。 30 | 31 | ![productpng_kb_foreign_server](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_foreign_server.png) 32 | 33 | -------------------------------------------------------------------------------- /product_kb_yunba_quick_start.md: -------------------------------------------------------------------------------- 1 | # 云巴快速入门教程 2 | 3 | ![productpng_kb_quick_start_flow.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_kb_quick_start_flow.png) 4 | 5 | ## 第一步 注册账号 6 | 7 | 打开 [云巴官方网站](https://yunba.io),注册并登录。 8 | 9 | ## 第二步 创建新应用 10 | 11 | 登录后,点击界面右上角 “创建应用”,填写应用名称、应用包名等内容。详见 [Portal 的说明文档](product_kb_portal.md)。 12 | 13 | 获得应用的 [AppKey](product_kb_app_key.md)。 14 | 15 | ## 第三步 下载 SDK 16 | 17 | 在云巴官网的 [开发者页面](https://yunba.io/downloads/) 或云巴的 [Github](https://github.com/yunba) 上找到所需平台的 SDK,并下载。 18 | 19 | 每种 SDK 的文件包内都包含一个 Demo,用来演示主要 API 的用法和功能。 20 | 建议您从运行 Demo 开始熟悉云巴的 SDK,详见各个 SDK 的 Demo 运行的文档。 21 | 22 | ## 第四步 集成 SDK 23 | 24 | 将云巴 SDK 集成到您的应用中(此时会用到第二步中的 [AppKey](product_kb_app_key.md))。详细内容可参考各个 SDK 的快速入门文档。 25 | 26 | ## 第五步 开始通信 27 | 28 | 集成 SDK 后,您可以将该应用安装在 A、B、C 三个设备上(当然,您也可以集成到不同平台的应用中,进行跨平台通信),进行实时通信了: 29 | 30 | - A 和 B 订阅一个 [频道](product_kb_topic_and_alias.md),C 向该 频道 发一条消息,那么 A 和 B 都会收到这条消息。 31 | 32 | - 给 A 设置 [别名](product_kb_topic_and_alias.md) “Alex”,就可以用 B 或 C 向 Alex 发一对一的消息。 33 | 34 | - B 和 C 还可以订阅 Alex 的 [在线](product_kb_presence.md) 状态,实时查看 Alex 的上下线和订阅状态。 35 | 36 | - 发消息时,您还可以指定消息送达的 [QoS](product_kb_qos.md) 等级(至少一次/至多一次/有且仅有一次)。如果客户端当前不在线,云巴还可以为您保存 [离线消息](product_kb_offline_message.md)。 37 | 38 | -------------------------------------------------------------------------------- /product_kb_yunba_unfixed_ip.md: -------------------------------------------------------------------------------- 1 | # 云巴服务的 IP 是不固定的 2 | 3 | 客户端在与 MQTT broker 进行长连接之前会先请求云巴 ticket 服务, 4 | ticket 服务会返回一个当前可用的 broker IP, 5 | 然后客户端会跟这个当前可用的 broker 进行长连接, 6 | 最后才开始进行 MQTT 通信。 7 | 8 | 9 | 为了保障 MQTT 数据包的分布式处理, 10 | ticket 服务返回的 broker IP 会随着用户的使用情况和当前系统负载进行相应的调整,并非一个固定的接入 IP。 11 | 12 | 13 | 如果想要申请独立的 broker 服务,可以考虑云巴的付费服务。 14 | -------------------------------------------------------------------------------- /restful_api_api_manual.md: -------------------------------------------------------------------------------- 1 | # Yunba RESTful API 使用手册 2 | 3 | 4 | ## 注册开发者账号 5 | 6 | 打开 [云巴官方网站](https://yunba.io),点击注册创建账号。 7 | 8 | ![create_accout.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_register_account.png) 9 | 10 | ## 在云巴 Portal 上创建新应用 11 | 12 | 注册账号成功后,页面跳转到 “我的应用列表” 界面。点击 “创建应用”,输入 “应用名称” 和 “应用包名”。 13 | 14 | 15 | 创建成功后,会获得与 “应用包名”一一对应的 [AppKey](product_kb_app_key.md),可在 “应用详情” 页面查看。 16 | 在下文的示例中,将 appkey 和 seckey 替换为您从 [Portal](product_kb_portal.md) 获取到的 AppKey 和 Secret Key,即可运行。 17 | 18 | 19 | >**注**:请妥善保管好您的 AppKey 和 Secret Key,不要泄露给他人。 20 | 21 | ![productpng_portal_creat_application.png](https://raw.githubusercontent.com/yunba/docs/master/image/productpng_portal_creat_app.png) 22 | 23 | ## 方法 24 | 25 | >***注:msg 字段使用了 [URL encoding](https://www.w3schools.com/tags/ref_urlencode.asp),特殊符号请遵循该标准,如百分号 '%' 的 URL encoding 为 '%25'*** 26 | 27 | ### HTTP GET 28 | 29 | **重要提示:GET 方法仅供测试,实际应用中请使用 POST 方法。([GET 与 POST 的比较](http://www.w3school.com.cn/tags/html_ref_httpmethods.asp))** 30 | 31 | **格式** 32 | 33 | ```url 34 | http://rest.yunba.io:8080?method=&appkey=&seckey=&topic=&msg="your message" 35 | ``` 36 | 可直接在浏览器地址栏中打开 URL,或使用 cURL 命令来执行。其中,method 的详细说明见下文的 HTTP POST 章节。 37 | 38 | 39 | 在使用 `publish_to_alias` 方法时,请用 alias= 替换 topic= 即可。 40 | 41 | **示例** 42 | 43 | ```bash 44 | $curl --request GET "http://rest.yunba.io:8080?method=publish&appkey=567a4a754407a3cd028aaf6b&seckey=sec-mj64xlu0ob1Xs1wWuZzmGZOYZqrpFmFxp5jHULr13eUZCVpS&topic=news&msg="good_news"" 45 | ``` 46 | **注**:上文给出的 AppKey 和 SecretKey 功能受限,仅供文档举例使用。 47 | 48 | ### HTTP POST 49 | 50 | **格式** 51 | 52 | 对于 HTTP POST 请求,请求的 body 使用 JSON 格式,请将 HTTP header 的 Content-Type 设为 application/json。 53 | 54 | 55 | 请求的 JSON 格式及参数说明如下。 56 | 57 | 58 | 同样地,在使用 `publish_to_alias` 时,请用 "alias": 替换 "topic": 即可。 59 | 60 | ```json 61 | { 62 | "method":, 63 | "appkey":, 64 | "seckey":, 65 | "topic":, 66 | "msg":, 67 | 68 | "opts": { 69 | "time_to_live":, 70 | "qos":, 71 | "apn_json": { 72 | "aps": { 73 | "alert":, 74 | "badge":, 75 | "sound":, 76 | "content-available": 77 | } 78 | }, 79 | "third_party_push": { 80 | "notification_title":"你好", 81 | "notification_content":"云巴推送" 82 | } 83 | } 84 | } 85 | ``` 86 | 87 | **参数说明:** 88 | 89 | * `time_to_live`:用来设置离线消息保留多久。单位为秒(例如,“3600”代表1小时),默认值为 3 天,最大不超过 15 天。 90 | * `qos`:用来设置服务质量等级。有三种取值:“0”表示最多送达一次;“1”表示最少送达一次;“2”表示保证送达且仅送达一次。默认为 1 。详见云巴知识库的 [QoS](product_kb_qos.md) 篇。 91 | * `opts` 为可选项。 92 | - 如果不带有 opts 参数,会发送默认的 APN。 93 | - 如果带有 opts 参数,且 opts 中出现了 apn_json (aps) 项,就会发送 APN。 94 | - **如果带有 opts 参数,且 opts 中没有出现 apn_json (aps) 项,就不会发送 APN。** 95 | - **如果不带 opts 或 opts 中没有 third_party_push 项,就不会发送小米/华为推送。** 96 | 97 | 98 | 下面是一个带有 `apn_json` 的 `opts` 参数示例,详细的参数说明请参考 [APNs 的官方文档](https://developer.apple.com/library/prerelease/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1)。 99 | 100 | ```json 101 | "opts": { 102 | "qos": 1, 103 | "time_to_live":36000, 104 | "apn_json":{ 105 | "aps": { 106 | "alert":"yunba", 107 | "badge":3, 108 | "sound":"bingbong.aiff" 109 | } 110 | } 111 | } 112 | ``` 113 | 114 | ## method 说明及示例 115 | 116 | 目前支持的 method 包括: 117 | * `publish` 118 | * `publish_to_alias` 119 | * `publish_to_alias_batch` 120 | 121 | 其中,`publish`、`publish_to_alias`和`publish_to_alias_batch`可以带 opts 参数,带上参数后,就相当于 `publish2`、`publish2_to_alias`和`publish2_to_alias_batch`。 122 | 123 | 124 | 下面逐一介绍这几种 method,并给出示例。 125 | 126 | 127 | 将下文示例中的 appkey 和 seckey 替换为您从 Portal 获取到的 AppKey 和 Secret Key,即可直接运行。 128 | 运行后,会收到返回的状态信息,详见文末的状态参数说明。 129 | 130 | ### `publish` 131 | 132 | 用于向指定的频道(topic)发送消息,所有订阅了该频道的客户端都可以收到消息。 133 | 134 | ```bash 135 | $ curl -l -H "Content-type: application/json" -X POST -d '{"method":"publish", "appkey":"567a4a754407a3cd028aaf6b", "seckey":"sec-mj64xlu0ob1Xs1wWuZzmGZOYZqrpFmFxp5jHULr13eUZCVpS", "topic":"news", "msg":"good news"}' http://rest.yunba.io:8080 136 | ``` 137 | 138 | ### `publish_to_alias` 139 | 140 | 用于向指定的别名(alias)发送一对一的消息。 141 | 142 | ```bash 143 | $ curl -l -H "Content-type: application/json" -X POST -d '{"method":"publish_to_alias", "appkey": "567a4a754407a3cd028aaf6b", "seckey":"sec-mj64xlu0ob1Xs1wWuZzmGZOYZqrpFmFxp5jHULr13eUZCVpS", "alias":"test", "msg":"message from RESTful API", "opts":{"time_to_live":20000}}' http://rest.yunba.io:8080 144 | ``` 145 | 146 | ### `publish_to_alias_batch` 147 | 148 | 用于同时向多个指定的别名(alias)发消息。群发的别名数目最好控制在 1000 以下。 149 | 150 | 151 | 例如,我们向别名为 Jack 和 Rose 的客户端同时发送消息。 152 | 153 | ```bash 154 | $ curl -l -H "Content-type: application/json" -X POST -d '{"method":"publish_to_alias_batch", "appkey":"567a4a754407a3cd028aaf6b", "seckey":"sec-mj64xlu0ob1Xs1wWuZzmGZOYZqrpFmFxp5jHULr13eUZCVpS", "aliases":["Jack","Rose"], "msg":"good news", "opts":{"time_to_live": 20}}' http://rest.yunba.io:8080 155 | ``` 156 | 157 | 发送后,返回如下。参考文末的返回状态说明可以看出,给 Jack 的消息发送成功了。但由于该 AppKey 下并不存在别名为 Rose 的客户端,向 Rose 发的消息发送失败了。 158 | 159 | ```bash 160 | {"status":0,"results":{"Jack":{"status":0,"messageId":512625795122860032},"Rose":{"status":5,"alias":"567a4a754407a3cd028aaf6b-Rose","error":"alias not found"}}} 161 | ``` 162 | 163 | 164 | ## 支持 https 165 | 166 | 云巴对付费用户支持 https。目前,免费用户可以试用 RESTful 和 socket.IO 的加密链路,实际生产使用需要付费。 167 | 168 | **注意,使用 SSL/TLS 方式进行连接,port 为 443;否则,port 为 3000。** 169 | 170 | 171 | 172 | ## 发送状态回复 173 | 174 | **发送成功** 175 | 176 | ```json 177 | {"status":0, "messageId": ""} 178 | ``` 179 | 180 | **参数错误** 181 | 182 | ```json 183 | {"status":1, "error": "invalid parameters"} 184 | ``` 185 | 186 | **内部服务错误** 187 | 188 | ```json 189 | {"status":2, "error": "internal server"} 190 | ``` 191 | 192 | **没有应用** 193 | 194 | ```json 195 | {"status":3} 196 | ``` 197 | 198 | **发布超时** 199 | 200 | ```json 201 | {"status":4, "error": "timeout"} 202 | ``` 203 | 204 | **没有找到 Alias** 205 | 206 | ```json 207 | {"status":5, "alias":"567a4a754407a3cd028aaf6b-test", "error": "alias not found"} 208 | ``` 209 | **[常见问题](restful_faq.md)** 210 | -------------------------------------------------------------------------------- /restful_faq.md: -------------------------------------------------------------------------------- 1 | # RESTful API 常见问题解答 2 | 3 | 4 | 1. **RESTful 如何设置离线消息保留时间?** 5 | 6 | 答: "opts" 设置 "qos" 值为 1 或 2,才能成功发送离线消息;设置 "time_to_live" 参数指定离线消息的保留时间,默认是 3 天,详见: [云巴的离线消息](product_kb_offline_message.md) 和 [RESTful API 的示例](restful_api_api_manual.md#httppost)。 7 | 8 | --- 9 | 2. **加 opts 参数之后,可以用 get 请求吗?** 10 | 11 | 答: GET 方法不支持复杂参数,只是用来做简单测试;可以用 POST 方法,具体参考 [官方文档](restful_api_api_manual.md#httppost)。同时注意请求头的设置: Content-type: application/json。 12 | 13 | --- 14 | 3. **RESTful API 可以指定 Message ID 吗?** 15 | 16 | 答: 云巴服务端随机生成 Message ID。 17 | 18 | --- 19 | 4. **RESTful的`publish_to_alias_batch()`API 中别名 Alias 的最大数量有限制吗?** 20 | 21 | 答: 别名的数量建议在 1000 以下。 22 | 23 | --- 24 | 5. **RESTful 的 Message 支持最大传送数据多大?** 25 | 26 | 答: 建议不要超过 1KB。 27 | 28 | --- 29 | 6. **使用 RESTful API 发送消息时需要区分 Android 和 iOS 平台设备吗?** 30 | 31 | 答: 不需要。 32 | 33 | >**注**:apn_json 参数只针对 iOS 平台的 APNs 消息。具体参考 [官方文档](restful_api_api_manual.md#httppost),apn_json 参数的完整设置方法可参考 [iOS 官方文档](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1)。 34 | 35 | --- 36 | 7. **为什么 RESTful API 没有 subscribe(订阅)的 API?** 37 | 38 | 答: 因为 RESTful 请求不是一个长连接,如果要实现 subscribe API,可以考虑使用 [Socket.IO API](socketio_api_api_manual.md)。 39 | 40 | --- 41 | 8. **RESTful API 是否支持 https?** 42 | 43 | 答: 付费用户支持。 44 | 45 | 46 | -------------------------------------------------------------------------------- /setting/README.md: -------------------------------------------------------------------------------- 1 | ##说明 2 | 该文件夹文件用于文档中心页面和SDK下载页面维护。 3 | 4 | `修改后需要到管理中心的文档页面点击更新,前端方可更新` 5 | 6 | [TOC] 7 | 8 | ###newDoc.json文件 9 | 10 | 文档中心页面配置json。请严格按照格式改动配置文件。 11 | 12 | ####字段说明 13 | * 整个json是一个对象数组。对象格式如下: 14 | ``` 15 | { 16 | "name": "概览", 17 | "show": true, 18 | "release": true, 19 | "docs": [{ 20 | "name": "平台简介", 21 | "markdown": "product_kb_whats_yunba.md", 22 | "url": "product_kb_whats_yunba", 23 | "show": true, 24 | "release": true 25 | }, { 26 | "name": "功能介绍", 27 | "markdown": "product_kb_topic_and_alias.md", 28 | "url": "product_kb_topic_and_alias", 29 | "show": true, 30 | "release": true 31 | }, { 32 | "name": "使用须知", 33 | "markdown": "product_kb_yunba_quick_start.md", 34 | "url": "product_kb_yunba_quick_start", 35 | "show": true, 36 | "release": true 37 | }] 38 | } 39 | 40 | ``` 41 | 42 | * `name` 用于显示文档中心的每一块的标题 43 | 44 | * `show/release` 未使用该字段 45 | 46 | * `docs` 文档中心的每一块的文章列表 47 | * `name` 文章名字 48 | 49 | * `markdown/url` 分别对应md文件名和url,请注意唯一性 50 | 51 | * `show/release` 未使用该字段 52 | 53 | ####newDownloads.json文件 54 | SDK下载页面配置json。请严格按照格式改动配置文件。 55 | 56 | ####字段说明 57 | * 整个json是一个对象数组。对象格式如下: 58 | 59 | ``` 60 | { 61 | "sdkName": "Android", 62 | "display": "block", 63 | "latestVersion": [{ 64 | "versionUrl": "/docs2/android_sdk_api_manual", 65 | "downloadUrl":"https://github.com/yunba/yunba-sdk-releases/raw/master/Android/YunBa-Android-sdk-1.8.0-beta.zip", 66 | "githubUrl":"", 67 | "versionNum": "Release 1.8.0-beta", 68 | "versionDetail": [ 69 | "支持小米推送、华为推送" 70 | ] 71 | }], 72 | "revisionHistory": [{ 73 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.6.4.zip", 74 | "downloadUrl":"", 75 | "versionNum": "Release 1.6.4", 76 | "versionDetail": [ 77 | "与 1.6.3 版本相同,增加了 so 文件。" 78 | ] 79 | }, { 80 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.6.3.zip", 81 | "downloadUrl":"", 82 | "versionNum": "Release 1.6.3", 83 | "versionDetail": ["后台进程相互拉起的特殊版本 SDK。"] 84 | }, { 85 | "versionUrl": "/docs2/android_sdk_api_manual", 86 | "downloadUrl":"https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.4.5.zip", 87 | "githubUrl":"", 88 | "versionNum": "Release 1.4.5", 89 | "versionDetail": [ 90 | "" 91 | ] 92 | }] 93 | } 94 | ``` 95 | 96 | * `sdkName` 用于显示SDK下载页面的导航条的每一个标题和某些attr 97 | 98 | * `display` 请设置为block 99 | 100 | * `latestVersion` SDK下载页面的最新div 101 | * `versionUrl` SDK的文档链接相对地址 102 | 103 | * `downloadUrl` SDK的文档链接绝对地址 104 | 105 | * `githubUrl` 开源SDK的github链接绝对地址,闭源则填空。 106 | 107 | * `versionNum` SDK的版本号 108 | 109 | * `versionDetail` 版本描述,格式:`数组`,用数组来区分每一个不同的特性。如['sdk特性1','sdk特性2','sdk特性3'],若为空,请设置[""] 110 | 111 | * `revisionHistory` SDK下载页面的历史版本div,若为空,请设置 `"revisionHistory":[]` 112 | 113 | * `versionNum` SDK的版本号 114 | 115 | * `versionUrl/githubUrl/downloadUrl` 未使用 116 | 117 | * `versionDetail` 版本描述,格式:`数组`,用数组来区分每一个不同的特性。如['sdk特性1','sdk特性2','sdk特性3'],若为空,请设置`"versionDetail":[""]` 118 | 119 | 120 | -------------------------------------------------------------------------------- /setting/newDownloads.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "sdkName": "Android", 3 | "display": "block", 4 | "latestVersion": [{ 5 | "versionUrl": "/docs2/android_sdk_api_manual", 6 | "downloadUrl":"https://github.com/yunba/yunba-sdk-releases/raw/master/Android/YunBa-Android-sdk-1.8.6-beta.zip", 7 | "githubUrl":"", 8 | "versionNum": "Release 1.8.6-beta", 9 | "versionDetail": [ 10 | "修复 Android 8 Crash 问题" 11 | ] 12 | }], 13 | "revisionHistory": [ 14 | { 15 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.8.5.zip", 16 | "downloadUrl":"", 17 | "versionNum": "Release 1.8.5", 18 | "versionDetail": [ 19 | "" 20 | ] 21 | }, 22 | { 23 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.8.4.zip", 24 | "downloadUrl":"", 25 | "versionNum": "Release 1.8.4", 26 | "versionDetail": [ 27 | "支持通配符" 28 | ] 29 | }, { 30 | "versionUrl": "/docs2/android_sdk_api_manual", 31 | "downloadUrl":"https://github.com/yunba/yunba-sdk-releases/raw/master/Android/YunBa-Android-sdk-1.8.0-beta.zip", 32 | "githubUrl":"", 33 | "versionNum": "Release 1.8.0-beta", 34 | "versionDetail": [ 35 | "支持华为等厂商推送" 36 | ] 37 | }, { 38 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.6.4.zip", 39 | "downloadUrl":"", 40 | "versionNum": "Release 1.6.4", 41 | "versionDetail": [ 42 | "与 1.6.3 版本相同,增加了 so 文件。" 43 | ] 44 | }, { 45 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.6.3.zip", 46 | "downloadUrl":"", 47 | "versionNum": "Release 1.6.3", 48 | "versionDetail": ["后台进程相互拉起的特殊版本 SDK。"] 49 | }, { 50 | "versionUrl": "/docs2/android_sdk_api_manual", 51 | "downloadUrl":"https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/Android/YunBa-Android-sdk-1.4.5.zip", 52 | "githubUrl":"", 53 | "versionNum": "Release 1.4.5", 54 | "versionDetail": [ 55 | "" 56 | ] 57 | }] 58 | }, { 59 | "sdkName": "iOS", 60 | "display": "none", 61 | "latestVersion": [{ 62 | "versionUrl": "/docs2/ios_sdk_api_manual", 63 | "downloadUrl":"https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.7.4.zip", 64 | "githubUrl":"", 65 | "versionNum": "Release 1.7.4", 66 | "versionDetail": [ 67 | "支持通配符" 68 | ] 69 | }], 70 | "revisionHistory": [{ 71 | "versionUrl": "/docs2/ios_sdk_api_manual", 72 | "downloadUrl":"https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.7.3.zip", 73 | "githubUrl":"", 74 | "versionNum": "Release 1.7.3", 75 | "versionDetail": [ 76 | "修复一个内存申请过多导致的问题", 77 | "修复demo中的显示错误", 78 | "修复网络状况较差时长时间connnect无返回的问题" 79 | ] 80 | },{ 81 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.7.1.zip", 82 | "downloadUrl":"", 83 | "versionNum": "Release 1.7.1", 84 | "versionDetail": [ 85 | "解决1.7.0版本在飞行模式下的assert crash bug" 86 | ] 87 | }, { 88 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.7.0.zip", 89 | "downloadUrl":"", 90 | "versionNum": "Release 1.7.0", 91 | "versionDetail": [ 92 | "优化SDK在IPv6-only网络下的链接状况", 93 | "针对新版本iOS做出链接优化", 94 | "增加iOS 9.3支持" 95 | ] 96 | }, { 97 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.6.4.zip", 98 | "downloadUrl":"", 99 | "versionNum": "Release 1.6.4", 100 | "versionDetail": [ 101 | "修复在网络状况反复失效时造成的token上传错误", 102 | "修复一个demo显示错位的问题", 103 | "修复预编译头文件编译告警" 104 | ] 105 | }, { 106 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.6.3.zip", 107 | "downloadUrl":"", 108 | "versionNum": "Release 1.6.3", 109 | "versionDetail": [ 110 | "修复一个网络层的bug", 111 | "修复Xcode7下的无效编译告警", 112 | "加快SDK链接速度" 113 | ] 114 | }, { 115 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.6.2.zip", 116 | "downloadUrl":"", 117 | "versionNum": "Release 1.6.2", 118 | "versionDetail": [ 119 | "增加API timeout和heartbeat的启动参数选项", 120 | "修复一个网络层的bug", 121 | "修复一个demo显示错误", 122 | "增加API超时后的网络检查" 123 | ] 124 | }, { 125 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.6.0.zip", 126 | "downloadUrl":"", 127 | "versionNum": "Release 1.6.0", 128 | "versionDetail": [ 129 | "修改注册请求,适配iOS9 ATS", 130 | "重构demo", 131 | "在断链通知中增加链接断开原因", 132 | "增加apns界面及apns通知处理" 133 | ] 134 | }, { 135 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.5.2.zip", 136 | "downloadUrl":"", 137 | "versionNum": "Release 1.5.2", 138 | "versionDetail": [ 139 | "允许setAlias参数为空(unset alias)", 140 | "增加iOS 8.4支持" 141 | ] 142 | }, { 143 | "versionUrl": "https://raw.githubusercontent.com/yunba/yunba-sdk-releases/master/iOS/YunBa-iOS-sdk-1.5.1.zip", 144 | "downloadUrl":"", 145 | "versionNum": "Release 1.5.1", 146 | "versionDetail": [ 147 | "增加GetStateV2/GetAliasListV2/GetTopicListV2 API", 148 | "增加带有ttl参数的publish2 API", 149 | "增加iOS8.3支持" 150 | ] 151 | }] 152 | }, { 153 | "sdkName": "JavaScript", 154 | "display": "none", 155 | "latestVersion": [{ 156 | "versionUrl": "/docs2/js_sdk_api_manual", 157 | "downloadUrl":"https://github.com/yunba/yunba-javascript-sdk/archive/2.1.2.zip", 158 | "githubUrl":"https://github.com/yunba/yunba-javascript-sdk", 159 | "versionNum": "Release 2.1.2", 160 | "versionDetail": [ 161 | "修正 file 协议下默认 server", 162 | "关闭 Demo 时会取消订阅本次订阅的所有 Topic" 163 | ] 164 | }], 165 | "revisionHistory": [{ 166 | "versionUrl": "/docs2/js_sdk_api_manual", 167 | "downloadUrl":"https://github.com/yunba/yunba-javascript-sdk/archive/2.0.3.zip", 168 | "githubUrl":"https://github.com/yunba/yunba-javascript-sdk", 169 | "versionNum": "Release 2.0.3", 170 | "versionDetail": [ 171 | "修复了 get_alias_list、get_topic_list、get_state 接口批量操作时可能存在的 callback 回调问题" 172 | ] 173 | }, { 174 | "versionUrl": "https://github.com/yunba/yunba-javascript-sdk/archive/2.0.2.zip", 175 | "downloadUrl":"", 176 | "versionNum": "Release 2.0.2", 177 | "versionDetail": [ 178 | "修正了例子中低版本 IE 浏览器判断注释的问题" 179 | ] 180 | }, { 181 | "versionUrl": "https://github.com/yunba/yunba-javascript-sdk/archive/2.0.1.zip", 182 | "versionNum": "Release 2.0.1", 183 | "versionDetail": [ 184 | "没有功能上的更新,只是修正了例子中的 JS SDK 文件名" 185 | ] 186 | }, { 187 | "versionUrl": "https://github.com/yunba/yunba-javascript-sdk/archive/2.0.0.zip", 188 | "downloadUrl":"", 189 | "versionNum": "Release 2.0.1", 190 | 191 | "versionDetail": [ 192 | "全新的 JS SDK 版本,更多的接口,强大的支持了 IE 7+ 浏览器" 193 | ] 194 | }] 195 | 196 | }, { 197 | "sdkName": "Java Over Socket.IO", 198 | "display": "none", 199 | "latestVersion": [{ 200 | "versionUrl": "/docs2/java_sdk_api_manual", 201 | "downloadUrl":"https://github.com/yunba/yunba-socket.io-java-sdk/archive/master.zip", 202 | "githubUrl":"https://github.com/yunba/yunba-socket.io-java-sdk", 203 | "versionNum": "Release 1.0.0", 204 | "versionDetail": [ 205 | "初始版本, Java sdk 目前重构的第一版的 sdk 已经开发测试,欢迎在我们的 Github 上下载" 206 | ] 207 | }], 208 | "revisionHistory": [] 209 | }, { 210 | "sdkName": "PHP", 211 | "display": "none", 212 | "latestVersion": [{ 213 | "versionUrl": "/docs2/php_demo_quick_start", 214 | "downloadUrl":"https://github.com/yunba/yunba-php-sdk/archive/master.zip", 215 | "githubUrl":"https://github.com/yunba/yunba-php-sdk", 216 | "versionNum": "Release 0.0.1", 217 | "versionDetail": [ 218 | "demo 版本,仅提供订阅和发布消息功能,仅支持Cli模式下运行" 219 | ] 220 | }], 221 | "revisionHistory": [] 222 | 223 | }, { 224 | "sdkName": "C", 225 | "display": "none", 226 | "latestVersion": [{ 227 | "versionUrl": "/docs2/c_sdk_api_manual", 228 | "downloadUrl":"https://github.com/yunba/yunba-c-sdk/archive/master.zip", 229 | "githubUrl":"https://github.com/yunba/yunba-c-sdk", 230 | "versionNum": "Release 1.0.0", 231 | "versionDetail": [ 232 | "初始版本" 233 | ] 234 | }], 235 | "revisionHistory": [] 236 | }] 237 | -------------------------------------------------------------------------------- /socketio_faq.md: -------------------------------------------------------------------------------- 1 | # Socket.IO API 常见问题解答 2 | 3 | 4 | 1. **使用什么版本的 Socket.IO-client?** 5 | 6 | 答: Node.js 请使用 1.3.5;Python 请使用 0.6.5。 7 | -------------------------------------------------------------------------------- /socketio_java_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba Socket.IO Java Demo 2 | 3 | 本文介绍如何运行 [yunba-socket.io-java-sdk](https://github.com/yunba/yunba-socket.io-java-sdk) 中的 Demo。Yunba 的 SDK 按照实现的方式,可以分为两种,一种是所谓原生 SDK,一种是基于 Socket.IO 的 SDK。Yunba Socket.IO Java SDK 是基于 Socket.IO 的 SDK。 4 | 5 | 本文涉及的运行环境如下: 6 | 7 | * Mac OS X 10.11.2 8 | * Eclipse 4.5.1 9 | 10 | ## 准备工作 11 | 12 | ###1. 注册云巴开发者账号 13 | 打开 [云巴官方网站](https://yunba.io),点击右上角的“注册”按钮创建账号。 14 | 15 | ###2. 下载云巴 Socket.IO Java SDK 16 | 下载 [yunba-socket.io-java-sdk](https://github.com/yunba/yunba-socket.io-java-sdk),并解压。 17 | 18 | ###3. 导出 socketio.jar 19 | 在 Eclipse 中打开 yunba-socket.io-java-sdk,导出为 socketio.jar 文件备用。 20 | 21 | ## 详细步骤 22 | 23 | ###1. 在云巴 Portal 上创建新应用 24 | 请参考 [运行 Yunba Android Demo](android_demo_quick_start.md) 25 | 一文中的该步骤的做法,获得一个 AppKey。 26 | 27 | ###2. 修改 APPKEY 28 | 在 Eclipse 中导入 yunba-socket.io-java-sdk 工程,将 examples/basic/BasicExample.java 里的 APPKEY 改为上一步中自己创建的 AppKey。 29 | 30 | ```java 31 | private static String APPKEY = "567a4a754407a3cd028aaf6b"; 32 | ``` 33 | 34 | ###3. 导入 socketio.jar 35 | 在 Eclipse 中,将 socketio.jar 导入到该工程的 Build Path 下。 36 | 37 | >**注**:对于这个 Demo 来说,工程里包含了 src 目录,因此不导入 socketio.jar 也可以使用。 38 | 39 | ###4. 运行 40 | 41 | 为了测试消息收发,可以增加订阅、发布的相关代码: 42 | 43 | ```java 44 | public void onConnAck(JSONObject json) throws Exception { 45 | System.out.println("onConnAck success " + json.get("success")); 46 | socket.emit("subscribe", new JSONObject("{'topic': 'news'}")); 47 | socket.emit("publish", new JSONObject("{'topic': 'news', 'msg': 'hello form java socket.io client', 'qos': 1}")); 48 | } 49 | ``` 50 | 51 | 代码修改好后,在 Eclipse 的 Package Explorer 面板中,右击 examples 文件夹下的 BasicExample.java,选择 Run as --> Java Application。 52 | 应用运行后,可以看到 Console 中打印的日志,包含建立连接、消息收发、心跳包等信息。 53 | 54 | >**注**:默认情况下,基于 Socket.IO 的 SDK 的心跳为 30 秒一次。 55 | 56 | ```bash 57 | 一月 05, 2016 3:42:59 下午 io.socket.IOConnection transportMessage 58 | 信息: < 1:: 59 | Connection established 60 | 一月 05, 2016 3:42:59 下午 io.socket.IOConnection transportMessage 61 | 信息: < 5:::{"name":"socketconnectack","args":[{"msg":"socket.io connected"}]} 62 | Server triggered event 'socketconnectack' 63 | onSocketConnectAck 64 | 一月 05, 2016 3:42:59 下午 io.socket.IOConnection sendPlain 65 | 信息: > 5:::{"args":[{"appkey":"567a4a754407a3cd028aaf6b","customid":"f02bf150-c653-4557-973f-8526b078d736"}],"name":"connect"} 66 | 一月 05, 2016 3:43:01 下午 io.socket.IOConnection transportMessage 67 | 信息: < 5:::{"name":"connack","args":[{"success":true,"sessionid":"567a4a754407a3cd028aaf6b-f02bf150-c653-4557-973f-8526b078d736"}]} 68 | Server triggered event 'connack' 69 | onConnAck success true 70 | 一月 05, 2016 3:43:01 下午 io.socket.IOConnection sendPlain 71 | 信息: > 5:::{"args":[{"topic":"news"}],"name":"subscribe"} 72 | 一月 05, 2016 3:43:01 下午 io.socket.IOConnection sendPlain 73 | 信息: > 5:::{"args":[{"msg":"hello form java socket.io client","qos":1,"topic":"news"}],"name":"publish"} 74 | 一月 05, 2016 3:43:01 下午 io.socket.IOConnection transportMessage 75 | 信息: < 5:::{"name":"suback","args":[{"success":true,"topic":"news","messageId":"531014746925719552"}]} 76 | Server triggered event 'suback' 77 | 一月 05, 2016 3:43:01 下午 io.socket.IOConnection transportMessage 78 | 信息: < 5:::{"name":"puback","args":[{"success":true,"messageId":"531014747101880320"}]} 79 | Server triggered event 'puback' 80 | conPubAck success true msg id 531014747101880320 81 | 一月 05, 2016 3:43:01 下午 io.socket.IOConnection transportMessage 82 | 信息: < 5:::{"name":"message","args":[{"topic":"news","msg":"hello form java socket.io client"}]} 83 | Server triggered event 'message' 84 | 一月 05, 2016 3:43:29 下午 io.socket.IOConnection transportMessage 85 | 信息: < 2:: 86 | 一月 05, 2016 3:43:29 下午 io.socket.IOConnection sendPlain 87 | 信息: > 2:: 88 | ``` 89 | 90 | 更多相关说明,请参考 [SDK 的 Readme 文件](https://github.com/yunba/yunba-socket.io-java-sdk/blob/master/README.markdown) 以及 [Socket.IO API 手册](socketio_api_api_manual.md)。 91 | -------------------------------------------------------------------------------- /socketio_python_demo_quick_start.md: -------------------------------------------------------------------------------- 1 | # 运行 Yunba Socket.IO Python Demo 2 | 3 | 本文以 Python 为例,演示 Yunba Socket.IO API 的使用。 4 | 5 | 本文涉及的运行环境如下。 6 | 7 | Mac 平台: 8 | * Mac OS X 10.11.1 9 | * virtualenv 13.1.2 10 | * socketIO-client 0.6.5 11 | 12 | Windows 平台: 13 | * Windows 8.1 14 | * python-2.7.10 15 | * pip-7.1.2 16 | * socketIO-client 0.6.5 17 | 18 | ## 准备工作——Mac 平台 19 | 20 | ###1. 安装 virtualenv 21 | 安装 virtualenv。安装后,可先不设置虚拟环境,根据第 2 步进行设置。 22 | 23 | ###2. 安装 socket.IO-client 24 | 打开 Mac 的 Terminal,按照 [socketIO-client 官方网站](https://pypi.python.org/pypi/socketIO-client) 的说明,输入如下命令: 25 | 26 | 设置环境变量: 27 | >$ VIRTUAL_ENV=$HOME/.virtualenv 28 | 29 | 如果想在下次打开 Terminal 时仍能使用该变量,可用下面的命令,将变量保存到“.bash_profile”文件里: 30 | >$ echo "export VIRTUAL_ENV=$HOME/.virtualenv" >> ~/.bash_profile 31 | 32 | 设置虚拟路径: 33 | >$ virtualenv $VIRTUAL_ENV 34 | 35 | 激活虚拟路径: 36 | >$ source $VIRTUAL_ENV/bin/activate 37 | 38 | 激活后,命令行的开头处会显示出虚拟环境的名称“.virtualenv”,此时,用下面的命令安装 socketIO-client, 39 | 将会安装到该目录中去: 40 | >$ pip install -U socketIO-client 41 | 42 | 有关 virtualenv 的详细用法,请参考 [virtualenv 的官方文档](https://virtualenv.pypa.io/en/latest/userguide.html)。 43 | 44 | ###3. 注册云巴开发者账号 45 | 打开 [云巴官方网站](https://yunba.io),点击右上角的“注册”按钮创建账号。 46 | 47 | ## 准备工作——Windows 平台 48 | 49 | ###1. 配置 python 运行环境 50 | 下载相应版本的 msi 文件:[官网下载地址](https://www.python.org/downloads/)。安装并配置 python 的运行环境。 51 | 52 | ###2. 安装 socket.IO-client 53 | 打开 CMD,按照 [socketIO-client 官方网站](https://pypi.python.org/pypi/socketIO-client) 的说明,输入如下命令: 54 | 55 | 创建一个虚拟路径: 56 | >virtualenv VIRTUAL_ENV 57 | 58 | 执行成功后会生成一个 VIRTUAL_ENV 文件夹。 59 | 60 | 激活虚拟路径: 61 | 62 | 执行CMD 进入 activate.bat 所在路径,输入 63 | >start activate.bat 64 | 65 | 激活后,命令行的开头处会显示出虚拟环境的名称“VIRTUAL_ENV”。 66 | 67 | 用下面的命令安装 socketIO-client: 68 | >pip install -U socketIO-client 69 | 70 | 有关 virtualenv 的详细用法,请参考 [virtualenv 的官方文档](https://virtualenv.pypa.io/en/latest/userguide.html) 。 71 | 72 | ## 详细步骤 73 | 74 | 75 | ###1. 申请 AppKey 76 | 77 | 为了演示消息收发的功能,我们先准备好一个集成了云巴 SDK 的客户端程序,之后与 Python 的 Demo 进行通讯。 78 | 79 | 例如,就使用 Yunba Android SDK 中提供的 Demo 程序, 80 | 其创建方法可参考 [运行 Yunba Android Demo](android_demo_quick_start.md) 一文。在 Portal 上创建新应用后,会获得一个 AppKey。 81 | 82 | ###2. 创建 Python 程序 83 | 新建一个文本文件,保存下面的 Python 示例程序。比如取名为 python_demo.py。 84 | 将代码中的“appkey”替换为步骤 1 中获得的 AppKey。只有这两个客户端使用同一个 AppKey,才能相互通信。 85 | 86 | **注**:下文给出的 AppKey 功能受限,仅供文档举例使用。 87 | 88 | ```python 89 | from socketIO_client import SocketIO 90 | import logging 91 | logging.basicConfig(level=logging.INFO) 92 | 93 | def on_socket_connect_ack(args): 94 | print 'on_socket_connect_ack', args 95 | socketIO.emit('connect_v2', {'appkey': '567a4a754407a3cd028aaf6b', 'customid': 'python_demo'}) 96 | 97 | def on_connack(args): 98 | print 'on_connack', args 99 | socketIO.emit('subscribe', {'topic': 'testtopic2'}) 100 | 101 | print "publish2_to_alias" 102 | socketIO.emit('publish2_to_alias', {'alias': 'alias_mqttc_sub', 'msg': "hello to alias from publish2_to_alias"}); 103 | 104 | def on_puback(args): 105 | print 'on_puback', args 106 | if args['messageId'] == '11833652203486491112': 107 | print ' [OK] publish with given messageId' 108 | 109 | def on_suback(args): 110 | print 'on_suback', args 111 | socketIO.emit('publish', {'topic': 'testtopic2', 'msg': 'from python', 'qos': 1}) 112 | 113 | socketIO.emit('publish', { 114 | 'topic': 'testtopic2', 115 | 'msg': 'from python with given messageId', 116 | 'qos': 1, 117 | 'messageId': '11833652203486491112' 118 | }) 119 | 120 | socketIO.emit('publish2', { 121 | 'topic': 't2thi', 122 | 'msg': 'from publish2', 123 | "opts": { 124 | 'qos': 1, 125 | 'apn_json': {"aps":{"sound":"bingbong.aiff","badge": 3, "alert":"douban"}}, 126 | 'messageId': '11833652203486491113' 127 | } 128 | }) 129 | 130 | socketIO.emit('set_alias', {'alias': 'mytestalias1'}) 131 | 132 | def on_message(args): 133 | print 'on_message', args 134 | 135 | def on_set_alias(args): 136 | print 'on_set_alias', args 137 | 138 | socketIO.emit('publish2', { 139 | 'topic': 'testtopic2', 140 | 'msg': 'from publish2', 141 | "opts": { 142 | 'qos': 1, 143 | 'apn_json': {"aps":{"sound":"bingbong.aiff","badge": 3, "alert":"douban"}} 144 | } 145 | }) 146 | 147 | 148 | socketIO.emit('get_alias') 149 | socketIO.emit('publish_to_alias', {'alias': 'mytestalias1', 'msg': "hello to alias"}) 150 | socketIO.emit('get_topic_list', {'alias': 'mytestalias1'}) 151 | socketIO.emit('get_state', {'alias': 'mytestalias1'}) 152 | 153 | def on_get_alias(args): 154 | print 'on_get_alias', args 155 | 156 | def on_alias(args): 157 | socketIO.emit('get_alias_list', {'topic': 'testtopic2'}) 158 | print 'on_alias', args 159 | 160 | def on_get_topic_list_ack(args): 161 | print 'on_get_topic_list_ack', args 162 | 163 | def on_get_alias_list_ack(args): 164 | print 'on_get_alias_list_ack', args 165 | 166 | def on_publish2_ack(args): 167 | print 'on_publish2_ack', args 168 | if args['messageId'] == '11833652203486491113': 169 | print ' [OK] publish2 with given messageId' 170 | 171 | def on_publish2_recvack(args): 172 | print 'on_publish2_recvack', args 173 | 174 | def on_get_state_ack(args): 175 | print 'on_get_state_ack', args 176 | 177 | socketIO = SocketIO('sock.yunba.io', 3000) 178 | socketIO.on('socketconnectack', on_socket_connect_ack) 179 | socketIO.on('connack', on_connack) 180 | socketIO.on('puback', on_puback) 181 | socketIO.on('suback', on_suback) 182 | socketIO.on('message', on_message) 183 | socketIO.on('set_alias_ack', on_set_alias) 184 | socketIO.on('get_topic_list_ack', on_get_topic_list_ack) 185 | socketIO.on('get_alias_list_ack', on_get_alias_list_ack) 186 | socketIO.on('puback', on_publish2_ack) 187 | socketIO.on('recvack', on_publish2_recvack) 188 | socketIO.on('get_state_ack', on_get_state_ack) 189 | socketIO.on('alias', on_alias) # get alias callback 190 | 191 | socketIO.wait() 192 | 193 | ``` 194 | 195 | ###3. 收发消息 196 | 197 | 为了收到 python_demo 发来的消息,需在 Android Demo 端订阅“testtopic2”、“t2thi”, 198 | 并将别名设置为 “alias_mqttc_sub”,如图所示: 199 | 200 | ![socketiopng_demo_setting.png](https://raw.githubusercontent.com/yunba/docs/master/image/socketiopng_demo_setting.png) 201 | 202 | 准备好后,开始运行 Python 的 Demo。在 Mac Terminal 中,激活虚拟环境。假设 Python 文件就在当前路径下,在虚拟环境下,运行 python_demo.py,如下: 203 | 204 | >$ source $VIRTUAL_ENV/bin/activate 205 | 206 | >$ python python_demo.py 207 | 208 | 运行成功后,会在 Terminal 中打印出执行的信息。而 Android Demo 端,也可以收到消息,如下: 209 | 210 | ![socketiopng_demo_client_receive.png](https://raw.githubusercontent.com/yunba/docs/master/image/socketiopng_demo_client_receive.png) 211 | 212 | 同样地,可以通过 Android Demo 的 MAIN 标签页下的“Msg to publish”项向 python_demo 订阅的频道发送消息。 213 | 另外,在代码中可以看到,python_demo 的别名已设置为“mytestalias1”。 214 | 可以通过 Android Demo 的 API 标签页下的 “Msg to Alias” 项发送一对一消息给 python_demo。 215 | 发送和接收的截图如下: 216 | 217 | ![socketiopng_demo_publish2_topic.png](https://raw.githubusercontent.com/yunba/docs/master/image/socketiopng_demo_publish2_topic.png) 218 | 219 | ![socketiopng_demo_publish2_alias.png](https://raw.githubusercontent.com/yunba/docs/master/image/socketiopng_demo_publish2_alias.png) 220 | 221 | ![socketiopng_demo_term_receive.png](https://raw.githubusercontent.com/yunba/docs/master/image/socketiopng_demo_term_receive.png) 222 | 223 | ## 注意事项 224 | 225 | 在使用 python 的 socket io client 库的时候,在监听事件的时候,你的 `on_message` 函数可能会监听到一些开头为 `2` 的消息事件,而这里面的内容和你的其它监听函数监听到的内容可能十分类似。比如: 226 | 227 | ![socketiopng_demo_python_on_message.png](https://raw.githubusercontent.com/yunba/docs/master/image/socketiopng_demo_python_on_message.png) 228 | 229 | 这个现象的原因是: 230 | 231 | - 这个 socket io 的库会根据前面的 nsp key(namespace key) 来判断这个事件的属性,而我们的 event 都是通过 nsp key = 2 这个方式发出去的,所以 socket io client 就认为这是一个 message event,然后就被 on_message 捕获到了,而 socket io 的协议还有一个 event 的表述方式,就是用一个 array,然后以第一个元素作为 event 的名字。所以这一个 json 就被两个事件监听捕获到了。 232 | 233 | 解决办法:过滤 on_message 捕获到的这类前面有 `2` 的消息。 234 | 235 | 更多用法和功能,请参考 [Socket.IO API 手册](socketio_api_api_manual.md)。 236 | -------------------------------------------------------------------------------- /socketio_wxapp_usage.md: -------------------------------------------------------------------------------- 1 | # 在微信小程序中使用云巴实时通信系统 2 | 3 | ## 准备 4 | 5 | 云巴在微信小程序中的使用基于 socket io,有关 socket io 的接口详细介绍可以参考我们的[socket io 官方文档](https://yunba.io/docs/socketio_api_api_manual)。 6 | 7 | 由于微信原生 API 中只支持 WebSocket,没有提供 socket io 的接口。为方便起见,本 demo 使用了 [socket io client](https://github.com/wxsocketio/wxapp-socket-io) 的库来连接云巴。 8 | 9 | 参考我们的[微信小程序 demo](https://github.com/yunba/yunba-wxapp-demo) 来在微信小程序中中集成云巴。关键的使用说明如下: 10 | 11 | ## 使用 12 | 13 | 首先,参考该 socket io client 的[使用说明](https://github.com/wxsocketio/wxapp-socket-io)在项目中引入该库。 14 | 15 | 在本例中即在 app.js 中 import 并初始化一个全局的 io 对象以供调用: 16 | 17 | ```javascript 18 | import io from './lib/wxsocket.io/index' 19 | ... 20 | onLaunch: function () { 21 | this,globalData.io = io 22 | } 23 | ``` 24 | 25 | 然后,在需要连接到云巴的时候,首先连接到我们的 socket io 服务器: 26 | 27 | ```javascript 28 | const socket = app.globalData.io("wss://abj-rest-fc1.yunba.io:443/") 29 | ``` 30 | 31 | 本例中即在 index.js 中使用全局的 io 对象连接到 `wss://abj-rest-fc1.yunba.io:443/`,在监听到 `connect` 事件的时候,就说明连接上云巴的 socket io 服务器了。 32 | 33 | ```javascript 34 | socket.on('connect', function () { 35 | self.setData({ 36 | connected: true 37 | }) 38 | ``` 39 | 40 | 此时就可以 emit 一个 `connect_v2` 事件,使用 appkey 和 customid 来连接云巴,在监听到 `connack` 事件的时候说明已经连接上云巴的实时通信系统,可以开始使用云巴的实时通信了。(***注:customid 即自定义的会话 id(session id),云巴会保留 session 信息,也就是下次再用此 customid 来连接的话,别名和订阅关系等信息均会保留。同时这也意味着同一时间只允许一个同名的 customid 在线,后上线的会挤掉前面的。***) 41 | 42 | ```javascript 43 | app.globalData.socket.emit('connect_v2', { 'appkey': this.data.appkey, 'customid': this.data.customid }) 44 | ``` 45 | 46 | ```javascript 47 | socket.on('connack', function (msg) { 48 | if (msg['success'] == true) { 49 | app.globalData.Online = true 50 | wx.navigateTo({ 51 | url: '../yunba/yunba' 52 | }) 53 | } 54 | }) 55 | ``` 56 | 57 | --- 58 | reference: [socket io 接口列表](https://yunba.io/docs/socketio_api_api_manual) 59 | -------------------------------------------------------------------------------- /white_paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunba/docs/659c80c3fb4a0ee109622d43e0fb13d70407c569/white_paper.pdf --------------------------------------------------------------------------------