赞
踩
在6月19号,我在深圳分会场参与了“消失的服务器”HSD线下活动,HSD线下活动主要讲解了华为Serverless如何帮助开发者无服务器构建应用。在后面的限时Codelabs中,要求利用云函数做一个猜数字的安卓应用或者鸿蒙应用。我选择了后者,碍于没有提前做准备,集成云函数环境耗费了太多时间,也踩了很多坑,导致最后没能完成。本文将从零开始集成云函数服务,在云端完成猜数字的函数,Serverless服务或许是正在被引导的一种方向。
关于Serverless服务,在华为开发者论坛上有一篇博文讲得非常详细,读者可仔细阅读。
Serverless服务帮您无服务器构建应用
那么Serverless到底有哪些优点,能帮我们做哪些事情呢?
我粗浅的理解,一个前端开发者也能借助Serverless的简易便捷性,在低学习成本下,也能快速从前到后构建一个APP。
我们需要利用云函数,在云端判断猜测是否正确,应用端只负责接收用户传入的猜测的数字和传递随机数,数字传入云函数,云函数判断是大了,还是小了,还是猜对了,并且返回应用端。
说白了,这个判断在云端完成,HarmonyOS应用侧只负责编写页面,接收数据,返回结果,不做任何判断的事情。
这个环节,也是我踩坑比较多的环节,导致最后没能完成!
选择下载配置文件,不包含密匙。
配置文件中默认会包含AGC为应用分配的客户端密钥和API密钥信息,但是经过尝试存在一定BUG。所以我们选择不包含密匙,在应用启动时候再分配密匙。
进入应用级的build.gradle文件。
添加依赖, implementation ‘com.huawei.agconnect:agconnect-function-harmony:1.3.1.300’
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
testImplementation 'junit:junit:4.13.1'
ohosTestImplementation 'com.huawei.ohos.testkit:runner:2.0.0.200'
/*****************添加云函数依赖*********************/
implementation 'com.huawei.agconnect:agconnect-function-harmony:1.3.1.300'
}
我们可以看到关键词,function这里对应的就是云函数的服务,还有云数据库之类的服务也有对应的关键词,但是似乎存在一定的bug,并且服务版本较低,相对提供给安卓的服务还是有一定差距。
前面我们在工程文件中放入了不含密匙的配置文件,我们需要在应用启动时候分配密匙。
package com.example.random; import com.huawei.agconnect.AGConnectInstance; import com.huawei.agconnect.AGConnectOptionsBuilder; import ohos.aafwk.ability.AbilityPackage; import ohos.global.resource.RawFileEntry; import ohos.global.resource.Resource; import ohos.global.resource.ResourceManager; public class MyApplication extends AbilityPackage { @Override public void onInitialize() { super.onInitialize(); in(); } private void in(){ //添加如下代码 try { AGConnectOptionsBuilder builder = new AGConnectOptionsBuilder(); ResourceManager resourceManager = getResourceManager(); // agconnect-services.json 文件路径 RawFileEntry rawFileEntry = resourceManager.getRawFileEntry("resources/rawfile/agconnect-services.json"); Resource resource = rawFileEntry.openRawFile(); builder.setInputStream(resource ); // 如果您的json文件中不存在client_id、client_secret和api_key参数,需通过以下接口设置 builder.setClientId("865143442517281664"); builder.setClientSecret("6CDCF90B48310A1A80DF1B818848133BF3AE1EA8A61BE09C628894B262E7FC93"); builder.setApiKey("DAEDADSYJyrB0DwxGwAReXl8nyYuCugvsdM4iCRmgf+jZhm+vzyPf+ViiznkGCTSI51Tv9JzxVpQlTjJuddZnqu9VuQ3nymhk8M7MA=="); AGConnectInstance.initialize(this, builder); } catch (Exception e) { e.printStackTrace(); } //TODO: 添加代码结束 } }
注意:
代码中所需要的,client_id、client_secret和api_key参数分别来自于AGC构建的对应的项目页面上。
进入config.json文件
在"abilities"下添加
{
"permissions": [
"com.huawei.agconnect.core.DataAbilityShellProvider.PROVIDER"
],
"name": "com.huawei.agconnect.core.provider.AGConnectInitializeAbility",
"type": "data",
//com.yzj.card 此处为自己工程的包名
"uri": "dataability://com.yzj.card.AGConnectInitializeAbility"
}
至此,应用侧环境配置完成,下面为项目编写猜数字的云函数。
我们进行在线的云函数编写。
let myHandler = function(event, context, callback, logger) { var res = new context.HTTPResponse(context.env, { "res-type":"context.env", "faas-content-type":"json", },"application/json", "200"); //定义一个全局变量,接收用户传来的数据 var guess_num; //定义一个全局变量,接收应用端生成的随机数 var random_num; //random_num = Math.ceil(Math.random()*100); if (event.body) { //如果传过来的是一个对象 那么解析,获取对应数据。 var _body = JSON.parse(event.body); //设置随机数 random_num =_body.random_num; //当前猜测的数据 guess_num = _body.guess_num; } else { guess_num = event.guess_num; } //定义一个变量 用来返回结果 var result=""; //执行猜测函数 result = randNumgame(guess_num); res = result; //返回结果 context.callback(res); function randNumgame (inputNum) { var resultString; //判断猜测数据是否合法 if (!isNumber(inputNum)) { resultString = "input is not a number"; } else { var remainder = inputNum; //大于正确数据 if(remainder>random_num) resultString="大了"; //等于正确数据 else if(remainder ==random_num) resultString = "正确" else resultString = "小了" } //返回字符串结果 return resultString; } //判断数据是否合法 function isNumber (input) { if (parseInt(input).toString == "NaN") { return false; } else { return true; } } } ; module.exports.myHandler =myHandler;
至此,云函数已经编写配置完成了,接下来是应用的简单编写。
启动云函数功能,只需要实例化AGConnectFunction即可
private AGConnectFunction function;
function = AGConnectFunction.getInstance();
我们对云函数的调用都是通过function实现的
private void getWeek(int num) { HashMap<String,Integer> map = new HashMap(); //两个对象,分别对应JS云函数中的 random_num 和 guess_num map.put("random_num",random_num); map.put("guess_num", num); /* 注意! 这里的“guess-test” 就是我们在触发器配置信息里面的标识 */ function2.wrap("guess-$latest").call(map) .addOnCompleteListener(new OnHarmonyCompleteListener<FunctionResult>() { @Override public void onComplete(HarmonyTask<FunctionResult> task) { if (task.isSuccessful()) { //获取返回值,对应JS云函数中的res String value = task.getResult().getValue(); HiLog.info(LABEL,value); tx.setText(value); //如果正确 再刷新随机数 if(value=="正确"){ random_num=new Random().nextInt(100); } } else { Exception e = task.getException(); if (e instanceof AGCFunctionException) { AGCFunctionException functionException = (AGCFunctionException) e; int errCode = functionException.getCode(); String message = functionException.getMessage(); HiLog.error(LABEL,message); } // ... } } }); }
package com.example.random.slice; import com.example.random.ResourceTable; import com.huawei.agconnect.AGConnectInstance; import com.huawei.agconnect.AGConnectOptionsBuilder; import com.huawei.agconnect.auth.AGConnectAuthCredential; import com.huawei.agconnect.function.AGCFunctionException; import com.huawei.agconnect.function.AGConnectFunction; import com.huawei.agconnect.function.FunctionResult; import com.huawei.hmf.tasks.HarmonyTask; import com.huawei.hmf.tasks.OnHarmonyCompleteListener; import ohos.aafwk.ability.AbilitySlice; import ohos.aafwk.content.Intent; import ohos.agp.components.Button; import ohos.agp.components.Component; import ohos.agp.components.Text; import ohos.agp.components.TextField; import ohos.global.resource.RawFileEntry; import ohos.global.resource.Resource; import ohos.global.resource.ResourceManager; import ohos.hiviewdfx.HiLog; import ohos.hiviewdfx.HiLogLabel; import ohos.utils.zson.ZSONObject; import java.util.HashMap; import java.util.Random; public class MainAbilitySlice extends AbilitySlice { private AGConnectFunction function2 ; private TextField textField; private Text tx; private Button btn; private int random_num; private static final HiLogLabel LABEL = new HiLogLabel(0, 0, "=>JAVA:" ); @Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); //启动AGC服务 start(); //生成随机数 Random r = new Random(); random_num = r.nextInt(100); //测试控件 textField = (TextField) findComponentById(ResourceTable.Id_tf); btn = (Button) findComponentById(ResourceTable.Id_btn); tx= (Text) findComponentById(ResourceTable.Id_tx); //绑定事件,点击一次进行数字猜测 btn.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { getWeek(Integer.parseInt(textField.getText())); HiLog.info(LABEL, String.valueOf(Integer.parseInt(textField.getText()))); } }); } private void start(){ //启动函数 try { function2= AGConnectFunction.getInstance(); } catch (Exception e) { e.printStackTrace(); } } private void getWeek(int num) { HashMap<String,Integer> map = new HashMap(); //两个对象,分别对应JS云函数中的 random_num 和 guess_num map.put("random_num",random_num); map.put("guess_num", num); /* 注意! 这里的“guess-test” 就是我们在触发器配置信息里面的标识 */ function2.wrap("guess-$latest").call(map) .addOnCompleteListener(new OnHarmonyCompleteListener<FunctionResult>() { @Override public void onComplete(HarmonyTask<FunctionResult> task) { if (task.isSuccessful()) { //获取返回值,对应JS云函数中的res String value = task.getResult().getValue(); HiLog.info(LABEL,value); tx.setText(value); //如果正确 再刷新随机数 if(value=="正确"){ random_num=new Random().nextInt(100); } } else { Exception e = task.getException(); if (e instanceof AGCFunctionException) { AGCFunctionException functionException = (AGCFunctionException) e; int errCode = functionException.getCode(); String message = functionException.getMessage(); HiLog.error(LABEL,message); } // ... } } }); } @Override public void onActive() { super.onActive(); } @Override public void onForeground(Intent intent) { super.onForeground(intent); } }
关于codelab的内容其实是非常简单的,只是在环境配置上走了不少弯路,尤其是权限的赋予非常重要。在Serverless的加持下,开发人员能够专注于核心业务的开发,一些运维后端的处理可以交由云端托管。目前Serverless的全套服务在安卓上有非常多的案例,也比较好适配。鸿蒙开发上似乎资料不多,案例较少,但未来Serverless势必会全套适配鸿蒙开发。届时,必大有可为。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。