什么是AppGallery Connect云函数

云函数是一项Serverless计算服务,提供FaaS(Function as a Service)能力,可以帮助开发者大幅简化应用开发与运维相关事务,降低应用功能的实现门槛,快速构建业务能力。

您将建立什么

在本次Codelab中,您将实现一个能够使用AppGallery Connect云函数与客户端进行交互的功能,您需要完成的功能将包含:

您将会学到什么

开发环境及技能要求

运行终端要求

必须为Android 4.2及以上版本。

集成AppGallery Connect云函数,需要完成以下准备工作:

具体操作,请按照《AppGallery Connect应用集成准备》中的详细说明来完成。

开通服务

  1. 登录AppGallery Connect网站,点击"我的项目"。
  2. 在项目列表中选择您需要开通云函数服务的项目。
  3. 在左侧导航栏选择"构建 > 云函数"。
  4. 点击页面右上角"立即开通"。

集成SDK

针对Android Studio开发环境,华为提供了maven仓集成方式的SDK包,开发前需集成SDK到您的Android Studio项目中。

  1. 在AppGallery Connect页面点击"我的项目",在项目下的应用列表中选择您需要开通云函数的应用。
  2. 在项目设置的"常规"页签下,点击"应用"栏下的"agconnect-services.json"下载配置文件。
  3. 将"agconnect-services.json"文件拷贝到应用级根目录下。
  4. 打开Android Studio应用级build.gradle文件,添加如下代码集成Cloud Functions SDK。
    //配置如下地址 apply plugin:'com.huawei.agconnect' dependencies { //配置如下地址 implementation 'com.huawei.agconnect:agconnect-function:1.6.5.300' }
  5. 点击界面上的"Sync Now"链接同步已完成的配置。

创建云函数

  1. 开通云函数服务后,在云函数界面,点击"+创建云函数"。
  2. 在创建界面中,完成函数定义。
    • "函数名称"和"描述"栏输入函数名称与描述。
    • "代码输入类型"选择"在线编辑"。
    • "部署信息"中输入部署信息,可使用默认配置。
  3. 在handler.js文件的代码输入框中输入以下代码。
    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 year; if (event.body) { var _body = JSON.parse(event.body); year = _body.year; } else { year = event.year; } var body = { result:'' }; body.result = animal(year); res.body = body; context.callback(res); function animal (inputYear) { var resultString; if (!isNumber(inputYear)) { resultString = "input is not a number"; } else { var remainder = inputYear % 12; switch (remainder) { case 0: resultString = "Monkey"; break; case 1: resultString = "Chicken"; break; case 2: resultString = "Dog"; break; case 3: resultString = "Pig"; break; case 4: resultString = "Mouse"; break; case 5: resultString = "Cow"; break; case 6: resultString = "Tiger"; break; case 7: resultString = "Rabbit"; break; case 8: resultString = "Dragon"; break; case 9: resultString = "Snake"; break; case 10: resultString = "Horse"; break; case 11: resultString = "Sheep"; break; default: resultString = "No symbolic Animal"; } } return resultString; } function isNumber (input) { if (parseInt(input).toString == "NaN") { return false; } else { return true; } } } ; module.exports.myHandler =myHandler;

测试函数

  1. 您可以通过两种方式进入函数测试页面。
    • 点击函数详情界面右上角的"测试"按钮。
    • 在Cloud Functions主界面上左侧导航栏点击"函数",在函数页面点击"测试"页签。
  2. 选择刚刚创建的函数及其版本,在事件中输入如下代码:
    { "year": 2020 }
  3. 在执行结果中查看结果,判断是否与如下结果一致:

添加触发器

  1. 在函数列表中点击函数名称进入函数详情页面。如果是函数别名,则进入函数别名配置页面。
  2. 点击"配置"页签下的"添加触发器",显示触发器创建界面。
  3. 在"配置触发器"区域配置"触发器类型"等信息,此处以HTTP触发器类型和POST请求方式为例。
  4. 参数

    说明

    触发器类型

    HTTP。

    请求方式

    HTTP触发器目前仅支持POST请求方式。

    认证类型

    HTTP触发器的认证类型。API客户端鉴权(Client适用):端侧网关认证,适用于来自APP客户端侧的函数调用。API客户端鉴权(Server适用):云侧网关认证,适用于来自APP服务器侧的函数调用。

    启用decode

    通过HTTP触发器触发函数时,对于contentType为"application/x-www-form-urlencoded"的触发请求,是否使用URLDecoder对请求body进行解码再转发到函数中。

  5. 完成后点击"添加"并点击"保存"。
  6. 将"详细信息"中的"触发URL"的后缀保存,作为后续客户端请求时的触发器标识。

本次Codelab中您可以在您的Android Studio工程中创建一个布局页面,参照下图进行UI设计,具备简单的年份输入,云函数返回结果的展示功能即可。

具体的界面布局,可参考如下activity_main.xml文件中的相关代码:

<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.4"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/instruction"/> <EditText android:id="@+id/year_text" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> <TextView android:id="@+id/rst_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/instruction_result" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.6"/> <Button android:id="@+id/rst_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/OK_button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.7"/>
  1. 在应用启动的onCreate方法中获取控件实例并设置按钮的点击事件。
    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); resultBtn = findViewById(R.id.rst_btn); resultText = findViewById(R.id.rst_text); inputYear = findViewById(R.id.year_text); resultBtn.setOnClickListener(new ButtonClickListener()); }
  2. 在点击事件中,首先获取输入框的输入值进行判空,并对其合法性进行校验。
    String inputText = inputYear.getText().toString(); if (inputText.equals("") || !isInputLegit(inputText)){ resultText.setText(R.string.year_error); return; }

    IsInputLegit方法:

    private boolean isInputLegit(String input){ for (int i = 0; i < input.length(); i++){ System.out.println(input.charAt(i)); if (!Character.isDigit(input.charAt(i))){ return false; } } return true; }
  3. 初始化云函数服务。
    AGConnectFunction function = AGConnectFunction.getInstance();
  4. 生成云函数所需要的事件的map对象,这里因为我们的云函数中设置的事件的key值为"year",所以我们设置map的key值为"year"。
    HashMap<String, String> map = new HashMap<>(); map.put("year", inputText);
  5. 调用云函数SDK中的wrap方法指定触发器,call方法传入事件的map作为参数,发送事件的HTTP请求并使用云函数进行计算,并且添加请求的回调接受云函数的返回结果显示到Textview中。
    function.wrap("symbolic-animals-$latest").call(map) .addOnCompleteListener(new OnCompleteListener<FunctionResult>() { @Override public void onComplete(Task<FunctionResult> task) { if (task.isSuccessful()){ String value = task.getResult().getValue(); try { JSONObject object = new JSONObject(value); String result = (String)object.get("result"); resultText.setText(result); } catch (JSONException e) { e.printStackTrace(); } Log.i(TAG, value); } else { Exception e = task.getException(); if (e instanceof AGCFunctionException){ AGCFunctionException functionException = (AGCFunctionException)e; int errCode = functionException.getCode(); String message = functionException.getMessage(); Log.e(TAG, "errorCode: " + errCode + ", message: " + message); } } } });
  1. 运行Android Studio工程生成APK包,并在测试手机中安装APK包。
  2. 在输入框中输入任意一个年份,查看界面是否展示当年的生肖。

祝贺您,您已经成功地构建了您的第一个集成AppGallery Connect云函数服务的应用程序,并学到了:

Code copied