(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{462:function(t,a,n){t.exports=n.p+"assets/img/cml_doc_android_02.bd113158.png"},463:function(t,a,n){t.exports=n.p+"assets/img/cml_doc_android_03.14b87b33.png"},464:function(t,a,n){t.exports=n.p+"assets/img/cml_doc_android_04.31081a1a.png"},509:function(t,a,n){"use strict";n.r(a);var s=n(17),e=Object(s.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"cml-android-sdk-使用范例"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#cml-android-sdk-使用范例"}},[t._v("#")]),t._v(" CML Android SDK 使用范例")]),t._v(" "),s("p",[t._v("以一个小 Demo 工程,讲述 CML Android SDK 的使用方式,引领轻松入门。"),s("font",{attrs:{color:"#FF0000"}},[t._v("Demo 工程在根目录 app 目录下")]),t._v(",用 Android Studio 导入并 run 起来后,再对照以下说明文档看会好理解。")],1),t._v(" "),s("p",[s("font",{attrs:{color:"#FF0000"}},[t._v("根目录 assets 目录下的 cml-demo-say.zip 是个简单的示例工程")])],1),t._v(" "),s("p",[t._v("用来演示 Native 和 Weex 容器或 web 容器的双向通信。app 目录下 Demo 工程加载的 Weex bundle 和 H5 页就是这个工程实现的。")]),t._v(" "),s("h2",{attrs:{id:"compile-依赖添加"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#compile-依赖添加"}},[t._v("#")]),t._v(" compile 依赖添加")]),t._v(" "),s("h3",{attrs:{id:"项目根目录-build-gradle-里添加-maven-仓库地址"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#项目根目录-build-gradle-里添加-maven-仓库地址"}},[t._v("#")]),t._v(" 项目根目录 build.gradle 里添加 maven 仓库地址")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("buildscript {\n repositories {~~~~\n jcenter()\n maven {\n url 'https://maven.google.com/'\n }\n }\n ...\n}\n\nallprojects {\n repositories {\n maven {\n url 'https://maven.google.com/'\n }\n jcenter()\n mavenCentral()\n ...\n }\n}\n")])])]),s("h3",{attrs:{id:"在-app-模块的-build-gradle-里添加依赖"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#在-app-模块的-build-gradle-里添加依赖"}},[t._v("#")]),t._v(" 在 App 模块的 build.gradle 里添加依赖")]),t._v(" "),s("h4",{attrs:{id:"首先添加如下依赖"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#首先添加如下依赖"}},[t._v("#")]),t._v(" 首先添加如下依赖")]),t._v(" "),s("div",{staticClass:"language-gradle extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('dependencies {\n ...\n compile "com.android.support:support-v4:$SUPPORT_VER"\n compile "com.android.support:appcompat-v7:$SUPPORT_VER"\n compile "com.android.support:recyclerview-v7:$SUPPORT_VER"\n\tcompile "com.didiglobal.chameleon:cmlsdk:$VERSION"\n\tcompile "com.didiglobal.chameleon:cmlweb:$VERSION"\n}\n')])])]),s("h4",{attrs:{id:"添加渲染引擎依赖"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#添加渲染引擎依赖"}},[t._v("#")]),t._v(" 添加渲染引擎依赖")]),t._v(" "),s("p",[t._v("CML Native SDK 采用 Weex 作为渲染引擎,当前依赖的 Weex 版本是")]),t._v(" "),s("ul",[s("li",[t._v("weex -> com.taobao.android:weex_sdk:0.20.0.2")])]),t._v(" "),s("div",{staticClass:"language-gradle extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('dependencies {\n ...\n\tcompile "com.didiglobal.chameleon:cmlweex:$VERSION"\n}\n')])])]),s("p",[t._v("com.android.tools.build:gradle 3.0 以后的版本用 "),s("code",[t._v("implementation")]),t._v(" 替换 "),s("code",[t._v("compile")]),t._v(",完整的依赖列表可参考示例工程。")]),t._v(" "),s("h2",{attrs:{id:"权限添加及-android-6-0-以上系统授权"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#权限添加及-android-6-0-以上系统授权"}},[t._v("#")]),t._v(" 权限添加及 Android 6.0 以上系统授权")]),t._v(" "),s("p",[t._v("CML SDK 已经添加了如下权限,android 6.0 以上系统版本需要在调起相关页面后手动授权。")]),t._v(" "),s("div",{staticClass:"language-gradle extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v(' \n \n \n \n')])])]),s("h2",{attrs:{id:"混淆"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#混淆"}},[t._v("#")]),t._v(" 混淆")]),t._v(" "),s("p",[t._v("参考示例工程")]),t._v(" "),s("h2",{attrs:{id:"初始化入口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#初始化入口"}},[t._v("#")]),t._v(" 初始化入口")]),t._v(" "),s("p",[t._v("实现自己的 Application 类,在应用启动的时候进行初始化调用。")]),t._v(" "),s("h3",{attrs:{id:"application-demo"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#application-demo"}},[t._v("#")]),t._v(" Application demo")]),t._v(" "),s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyApplication")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Application")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implements")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CmlConfig")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("onCreate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("onCreate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CmlEngine")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInstance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("configAdapter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 开发阶段可以禁用js bundle缓存")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CmlEnvironment")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("CML_ALLOW_BUNDLE_CACHE "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 开发阶段手动降级测试")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// CmlEnvironment.CML_DEGRADE = false;")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 注册降级Adapter")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CmlEnvironment")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setDegradeAdapter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CmlDegradeDefault")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// CmlEnvironment.setToastAdapter(xxx);")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// CmlEnvironment.setLoggerAdapter(xxx);")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// CmlEnvironment.setDialogAdapter(xxx);")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// CmlEnvironment.setNavigatorAdapter(xxx);")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// CmlEnvironment.setStatisticsAdapter(xxx);")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// CmlEnvironment.setImageLoaderAdapter(xxx);")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("registerModule")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CmlEngine")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInstance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("registerModule")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ModuleDemo")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"将-application-添加到-androidmanifest-xml"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#将-application-添加到-androidmanifest-xml"}},[t._v("#")]),t._v(" 将 Application 添加到 AndroidManifest.xml")]),t._v(" "),s("div",{staticClass:"language-xml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-xml"}},[s("code",[t._v('")])]),t._v("\n")])])]),s("h3",{attrs:{id:"适配器的实现"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#适配器的实现"}},[t._v("#")]),t._v(" 适配器的实现")]),t._v(" "),s("p",[t._v("适配器是暴露给 SDK 使用者的一组接口,用于提供扩展 SDK 的能力,其中一部分接口提供了默认实现,未提供默认实现的需要使用者自己实现并注册到 SDK 中。")]),t._v(" "),s("p",[s("img",{attrs:{src:n(462),alt:"image"}})]),t._v(" "),s("ul",[s("li",[s("p",[t._v("以下适配器提供了默认实现\nhttp / json / log / modal / storage / thread / websocket / imagloader")])]),t._v(" "),s("li",[s("p",[t._v("以下适配器未提供默认实现\nnavigator / degrade / statistics")])])]),t._v(" "),s("p",[t._v("以降级适配器举例,只需要两个步骤:")]),t._v(" "),s("ul",[s("li",[t._v("新建类 CmlDegradeDefault,实现接口 ICmlDegradeAdapter")]),t._v(" "),s("li",[t._v("在 MyApplication 的 configAdapter 方法里注册适配器。")])]),t._v(" "),s("h3",{attrs:{id:"module-的实现"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#module-的实现"}},[t._v("#")]),t._v(" Module 的实现")]),t._v(" "),s("p",[t._v("module 的基本概念可参看"),s("RouterLink",{attrs:{to:"/docs/sdk.html#module-的使用"}},[t._v("这里")]),t._v(", SDK 层实现在如下位置:")],1),t._v(" "),s("p",[s("img",{attrs:{src:n(463),alt:"image"}})]),t._v(" "),s("p",[t._v("module 的实现主要分两个步骤,一个是 Native 侧的代码实现,一个是 js 侧的代码实现。同时,native 和 js 的通信是双向的,及 Native 可以主动调用 js 侧的方法,js 侧也可以主动调用 Native 侧的方法。")]),t._v(" "),s("p",[s("img",{attrs:{src:n(464),alt:"image"}})]),t._v(" "),s("h4",{attrs:{id:"native-侧的实现"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#native-侧的实现"}},[t._v("#")]),t._v(" Native 侧的实现")]),t._v(" "),s("p",[s("font",{attrs:{color:"#FF0000"}},[t._v("以下内容请在 CML SDK Demo 运行起来的前提下阅读,方便理解即将描述的内容。")])],1),t._v(" "),s("p",[t._v("实现一个 Module 扩展需要如下几个步骤:")]),t._v(" "),s("ul",[s("li",[t._v("根据需求和前端 RD 确定 module/method/args 参数")]),t._v(" "),s("li",[t._v("Native RD 根据约定实现 Module 扩展,前端 RD 根据约定实现 js 并打包成 jsbundle")]),t._v(" "),s("li",[t._v("Native RD 可以将 jsbundle 放到 assets 目录下加载调试,也可以远程加载调试")])]),t._v(" "),s("p",[t._v("demo 实现了双向通信,js 调用 Native 接口约定如下"),s("RouterLink",{attrs:{to:"/docs/sdk.html#module-的使用"}},[t._v("(module 的概念)")]),t._v(":")],1),t._v(" "),s("ul",[s("li",[t._v("Module 名是 "),s("code",[t._v("moduleDemo")])]),t._v(" "),s("li",[t._v("method 名是 "),s("code",[t._v("sayHello")])]),t._v(" "),s("li",[t._v("args 名是 "),s("code",[t._v('{"content":"测试"}')])])]),t._v(" "),s("p",[t._v("实现的效果是点击 jsbundle 里的按钮,会弹 "),s("code",[t._v("测试")]),t._v(" toast")]),t._v(" "),s("p",[t._v("native 调用 js 接口约定如下:")]),t._v(" "),s("ul",[s("li",[t._v("Module 名是 "),s("code",[t._v("moduleDemo")])]),t._v(" "),s("li",[t._v("method 名是 "),s("code",[t._v("NaTellJS")])]),t._v(" "),s("li",[t._v("args 名是 "),s("code",[t._v('{"content":"测试"}')])])]),t._v(" "),s("p",[t._v("实现的效果是点击 Native 侧的按钮,会动态改变 jsbundle 里的文字显示。")]),t._v(" "),s("p",[t._v("module 的实现需要先了解 3 个注解")]),t._v(" "),s("ul",[s("li",[t._v("@CmlModule 标注这个类是扩展模块")]),t._v(" "),s("li",[t._v("@CmlMethod 标注可供 JS 侧调用的方法")]),t._v(" "),s("li",[t._v("@CmlParam 标注调用的参数")])]),t._v(" "),s("p",[t._v("以下是根据约定实现的 Module 扩展示例")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('@CmlModule(alias = "moduleDemo")\npublic class ModuleDemo {\n @CmlMethod(alias = "sayHello")\n public void sayHello(ICmlActivityInstance instance, @CmlParam(name = "content") String content) {\n Toast.makeText(instance.getContext(), content, Toast.LENGTH_SHORT);\n }\n}\n')])])]),s("p",[t._v("将 Module 注册到 SDK")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("public class MyApplication extends Application implements CmlConfig {\n @Override\n public void onCreate() {\n super.onCreate();\n\n CmlEngine.getInstance().init(this, this);\n CmlEngine.getInstance().registerModule(ModuleDemo.class); // 在这里注册\n }\n\t...\n}\n")])])]),s("p",[t._v("从前端 RD 拿到 JSBundle, 进行渲染,重点关注 Demo 工程里 CmlViewActivity")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('private static final String URL_JS_BUNDLE_OK = "https://www.example.com/degradle.html?cml_addr=http://172.22.138.92:8000/weex/cml-demo-say.js";\n\n@Override\nprotected void onCreate(Bundle savedInstanceState) {\n\t....\n\t// cmlView.render(URL_JS_BUNDLE_OK, null); // 加载远程jsbundle\n\tcmlView.render("file://local/cml-demo-say.js", null); // 加载assets目录里的jsbundle\n\t...\n}\n')])])]),s("p",[t._v("js 侧的实现以及 jsbundle 打包参看接下来的 4.4.2 小结。")]),t._v(" "),s("h4",{attrs:{id:"js-侧的实现"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#js-侧的实现"}},[t._v("#")]),t._v(" js 侧的实现")]),t._v(" "),s("p",[t._v("同样以上面要实现的 Module 和方法为例,我们来看一下 js 侧的实现。")]),t._v(" "),s("p",[s("font",{attrs:{color:"#FF0000"}},[t._v("参考根目录 assets 目录下的 cml-demo-say.zip")])],1),t._v(" "),s("p",[t._v("1.初始化前端项目(也可以使用已有的项目)")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("cml init project\n请输入项目名称 cml-demo-say\n")])])]),s("p",[t._v("2.打开项目下 src/pages/index/index.cml 文件,粘贴以下代码。以下代码主要是展示了 js 和 Native 双向的通信的方法实现。先粘贴,然后我们在下面介绍通信封装的原理。")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('\n\n