zl程序教程

您现在的位置是:首页 >  后端

当前栏目

一文教你集成通知系统的多种HMS Core服务,实现数据安全和真实用户验证

集成Core系统服务 实现 用户 验证 数据安全
2023-09-11 14:20:22 时间

1、介绍

Overview

云数据库是AppGallery Connect提供的服务之一,实现云端数据的同步,提供统一的数据模型和丰富的数据管理接口。在保证数据的可用性、可靠性、一致性,以及安全等特性基础上,能够实现数据在客户端和云端之间的无缝同步,并为应用提供离线支持,以帮助开发者快速构建端云、多端协同的应用。

您将建立什么

在本次codelab中,您将建立一个MVVM架构的安卓项目,实现Video Calling应用的云数据库和WebRTC功能,集成通知系统的推送服务、分析服务、机器学习服务、安全检测服务以及崩溃服务,实现数据安全和真实用户验证。

您将会学到什么

  • 集成AppGallery Connect的华为帐号登录认证服务。

  • 集成AppGallery Connect的崩溃服务。

  • 集成AppGallery Connect的云数据库。

  • 使用云数据库和WebRTC开发应用。

  • 通过Safety Detect检查运行应用的设备是否安全。

  • 使用推送服务和分析服务实现给受众发送通知。

  • 使用机器学习服务活体检测特性验证用户帐号。

2、您需要什么

硬件需求

  • 安装Android Studio并已连网的电脑

  • 华为或安卓手机(带USB线),用于调测和运行

软件需求

  • JDK版本:1.8.211或以上

  • Android API 21或以上

  • HMS Core (APK) 6.0.0.300或以上

  • Android Studio版本:3.6.1或以上

  • 华为手机:EMUI 5.0版本或以上;非华为手机:Android 5.0或以上

3、能力接入准备

如果您需要正式发布一款集成音频编辑服务的应用,请参阅HUAWEI HMS Core集成准备做好相关准备工作。本codelab提供的样例已为您完成准备工作。如您使用示例代码,忽略本步骤。

准备集成HMS Core前,在华为开发者联盟上注册成为开发者并完成实名认证,具体方法可参考帐号注册认证

4、配置开发环境

  1. 登录AppGallery Connect,点击“我的项目”。

  2. 在项目列表中找到您的项目,在项目下的应用列表中选择您需要集成SDK的应用。

  3. 在“项目设置”页面选择“常规”页签。点击“应用”区域里的“agconnect-services.json”下载配置文件。

  4. 把agconnect-services.json文件复制到项目里。

    cke_21649.png

配置HMS Core SDK的Maven仓地址

Android Studio的Maven仓地址配置方式在Gradle插件7.0以下版本、7.0版本和7.1及以上版本有所不同。

Maven仓地址无法直接在浏览器中打开访问,只能在IDE中配置。如需添加多个Maven代码库,请将华为公司的Maven仓地址配置在最后。

以7.1及以上版本为例。

  1. 打开Android Studio项目根路径下的build.gradle文件。

    cke_34172.png

  2. 如agconnect-services.json文件已添加到应用中,选择buildscript > dependencies添加AppGallery Connect和Android Gradle插件配置。

    buildscript { 
        dependencies { 
            ... 
            //添加Android Gradle插件配置。将{version}替换为真实的Gradle插件版本,例如,7.1.1。
            classpath 'com.android.tools.build:gradle:{version}' 
            //添加AppGallery Connect插件配置。
            classpath 'com.huawei.agconnect:agcp:1.6.0.300' 
        } 
    }
  3. 打开项目及settings.gradle文件,为HMS Core SDK配置Maven仓地址。

    pluginManagement { 
        repositories { 
            gradlePluginPortal() 
            google() 
            mavenCentral() 
            //为HMS Core SDK配置Maven仓地址。
            maven { url 'https://developer.huawei.com/repo/' } 
        } 
    } 
    dependencyResolutionManagement { 
        ... 
        repositories { 
            google() 
            mavenCentral() 
            //为HMS Core SDK配置Maven仓地址。
            maven { url 'https://developer.huawei.com/repo/' } 
        } 
    }

5、启用服务

集成云数据库SDK前,请启用云数据库服务。步骤如下:

  1. 登录AppGallery Connect,点击“我的项目”。

  2. 在项目列表中选择您需要开通云数据库服务的项目。

  3. 在导航树上点击“构建 > 云数据库”。在云数据库服务界面,点击“立即开通”。

  4. 在引导界面选择“数据处理位置”。

  5. 启用认证服务,机器学习服务,推送服务,安全检测服务和华为分析。

    cke_150460.png

   

6、设计UI

本codelab将设计app主页,联系人页面,以及携带用户资料页面。在主页中,您可以输入会议ID进入会议。

cke_155310.png

7、集成认证服务 – 华为账号登录

示例代码使用华为帐号登录模式,所以您需要在AppGallery Connect中启用认证服务的华为帐号认证模式。否则,登录将会失败。

  1. 登录AppGallery Connect,点击“我的项目”。

  2. 在项目列表中选择您的项目。

  3. 点击“构建 > 认证服务”,进入认证服务的页面。如果首次使用认证服务,请点击“立即开通”开通服务。

  4. 进入“认证服务”界面后,选择“认证方式”页签,点击“华为帐号”对应“操作”列的“启用”。

    cke_195548.png

  5. 在项目里调用认证服务相关方法。使用云数据库函数前,确保您已使用华为账号登录应用。

    示例代码:

    authParams = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
    .setAccessToken()
    .createParams()
    
    private fun signInHuaweiId(){
    val signInIntent = service.signInIntent
    startActivityForResult(signInIntent, HUAWEI_ID_SIGN_IN)
    } 

8、集成崩溃服务

启用华为分析服务

崩溃服务使用华为分析能力实现崩溃事件上报,因此您在集成崩溃SDK前需要启用华为分析

  1. 将编译依赖项添加到“dependencies”中。

    dependencies {
          implementation 'com.huawei.hms:hianalytics:5.2.0.301'
          implementation 'com.huawei.agconnect:agconnect-crash:1.5.1.300'
    }
  2. 在左侧导航栏选择“质量 > 崩溃”。如果首次使用崩溃服务,请点击“立即开通”开通服务。

    cke_231743.png

    buildscript { 
        repositories { 
            google() 
            jcenter() 
            //为HMS Core SDK配置Maven仓地址。
            maven {url 'https://developer.huawei.com/repo/'} 
        } 
        dependencies { 
            ... 
            //添加AppGallery Connect插件配置。
            classpath 'com.huawei.agconnect:agcp:1.6.0.300' 
        } 
    } 
    
    allprojects { 
        repositories { 
            google() 
            jcenter() 
            //为HMS Core SDK配置Maven仓地址。
            maven {url 'https://developer.huawei.com/repo/'} 
        } 
    } 

9、添加和导出对象类型

  1. 登录AppGallery Connect,点击“我的项目”。

  2. 在项目列表中选择您的项目。

  3. 在导航树上点击“构建 > 云数据库”。

  4. 单击“新增”,进入创建对象类型页面。

    cke_283157.png

  5. 输入“对象类型名”为“CallsSdp”后,单击“下一步”。

  6. 单击“新增字段”,新增如下字段后,单击“下一步”。

    字段名称

    类型

    主键

    非空

    加密

    默认值

    meetingID

    String

    sdp

    Text

    callType

    String

  7. 设置索引,单击“下一步”。

    cke_298233.png

  8. 设置所需的角色和权限。

    cke_307254.png

  9. 单击“确定”。创建完成后返回对象类型列表中,可以查看已创建的对象类型。

  10. 单击“导出”。

    cke_316476.png

  11. 选择导出文件格式,选择“java格式”。

  12. 单击“确定”。导出的JAVA文件包含该版本中所有的对象类型信息。在接下来的步骤中,该文件将被添加到本地开发环境中。

10、新增存储区

  1. 登录AppGallery Connect,选择“我的项目”。

  2. 在项目列表页面中选择项目。

  3. 在导航树上点击“构建 > 云数据库”。

  4. 单击“存储区”页签。

  5. 单击“新增”,进入创建存储区页面。

    cke_341793.png

  6. 设置“存储区名称”为“QuickLine”。

  7. 单击“确定”。

11、添加对象类型文件

将导出的JAVA格式文件添加至本地开发环境。如已存在,请覆盖原文件。为保证集成成功,请勿修改导出的JAVA文件。

cke_381637.png

​12、初始化云数据库

在添加对象类型文件后,您可以使用云数据库开发应用。开发应用前,需要初始化AGConnectCloudDB,然后创建Cloud DB zone和对象类型。示例代码已在各步骤中列出,方便您查看。

  1. 在application类中初始化云数据库。您需在CloudDbWrapper.kt中创建initialize方法来初始化AGConnectCloudDB。

    AGConnectCloudDB.initialize(context)
  2. 为云数据库创建RoutePolicy、Instance、和ObjectTypes。

      instance = AGConnectInstance.buildInstance(AGConnectOptionsBuilder()
                   .setRoutePolicy(AGCRoutePolicy.GERMANY)
                   .build(context))     
    
       cloudDB = AGConnectCloudDB.getInstance(
                 AGConnectInstance.getInstance(),
                 AGConnectAuth.getInstance())
    
       cloudDB?.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo())
  3. 创建存储区配置对象并打开该存储区。

    config = CloudDBZoneConfig(
                    Constants.CloudDbZoneName,
                    CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
                    CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC
                )
    
                config?.persistenceEnabled = true
                val task = cloudDB?.openCloudDBZone2(config!!, true)
                task?.addOnSuccessListener {
                    cloudDBZone = it
                    cloudDbInitializeResponse(true)
                }?.addOnFailureListener {
                    Log.e(TAG, "Open cloudDBZone failed for " + it.message)
                    cloudDbInitializeResponse(false)
                }

13、写入数据

本节主要介绍如何使用云数据库服务在应用中写入数据。本例使用executeUpsert方法写入数据。如下代码通过方法调用将SDP示例代码写入数据库中。

fun call() {
        Log.d(TAG, "contacts: called")

        peerConnection?.createOffer(
            SdpObserverImpl(
                onCreateSuccessCallback = { sdp ->
                    Log.d(TAG, "contacts: onCreateSuccessCallback called")

                    peerConnection?.setLocalDescription(SdpObserverImpl(
                        onSetSuccessCallback = {
                            Log.d(TAG, "contacts: onSetSuccess called")

                            val offerSdp = CallsSdp()
                            offerSdp.meetingID = meetingID
                            offerSdp.sdp = Text(sdp.description)
                            offerSdp.callType = sdp.type.name

                            val upsertTask = cloudDBZone?.executeUpsert(offerSdp)
                            upsertTask?.addOnSuccessListener { cloudDBZoneResult ->
                                Log.i(TAG, "Calls Sdp Upsert success: $cloudDBZoneResult")
                            }?.addOnFailureListener {
                                Log.e(TAG, "Calls Sdp Upsert failed: ${it.message}")
                            }
                            Log.e(TAG, "onSetSuccess")
                        }
                    ), sdp)
                }
            ), _mediaConstraints
        )
    }

14、查看数据

不同场景下需要查看的数据不同,例如,查看注册用户列表。我们使用executeQuery方法实现这个功能。如您定义查询和策略参数后收到成功消息,您可以通过收到的截图访问数据并添加到用户列表中。

Sample code:

fun queryUsers(userList: (ArrayList<Users>) -> Unit) {

            val queryUsers = CloudDBZoneQuery.where(Users::class.java)

            val queryTask = cloudDBZone?.executeQuery(
                queryUsers,
                CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY
            )

            queryTask?.addOnSuccessListener { snapshot ->
                val usersList = arrayListOf<Users>()
                try {
                    while (snapshot.snapshotObjects.hasNext()) {
                        val user = snapshot.snapshotObjects.next()
                        usersList.add(user)
                    }
                } catch (e: AGConnectCloudDBException) {
                    Log.e(TAG, "processQueryResultExc: " + e.message)
                } finally {
                    userList(usersList)
                    snapshot.release()
                }
            }?.addOnFailureListener {
                Log.e(TAG, "Fail processQueryResult: " + it.message)
            }
        }

15、使用安全检测服务提高设备安全性

安全检测服务提供强健的安全能力。本项目使用SysIntegrity来检查运行应用的设备是否安全,例如,检查设备是否被root过。

  1. 将编译依赖项添加到“dependencies”中。

    dependencies {
        implementation 'com.huawei.hms:safetydetect:5.0.5.302'
    }
  2. 新增SysIntegrity代码块。

    private fun invokeSysIntegrity() {
            val nonce = ByteArray(24)
            try {
                val random: SecureRandom = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    SecureRandom.getInstanceStrong()
                } else {
                    SecureRandom.getInstance("SHA1PRNG")
                }
                random.nextBytes(nonce)
            } catch (e: NoSuchAlgorithmException) {
                Log.e("NoSuchAlgorithmException", e.message!!)
            }
    
            SafetyDetect.getClient(this)
                .sysIntegrity(nonce, "YOUR_APPID")
                .addOnSuccessListener { response ->
                    val jwsStr = response.result
                    val jwsSplit = jwsStr.split(".").toTypedArray()
                    val jwsPayloadStr = jwsSplit[1]
                    val payloadDetail = String(
                        Base64.decode(
                            jwsPayloadStr.toByteArray(StandardCharsets.UTF_8),
                            Base64.URL_SAFE
                        ), StandardCharsets.UTF_8
                    )
                    try {
                        val jsonObject = JSONObject(payloadDetail)
                        val basicIntegrity = jsonObject.getBoolean("basicIntegrity")
                        val isBasicIntegrity = basicIntegrity.toString()
                        val basicIntegrityResult = "Basic Integrity: $isBasicIntegrity"
    
                        Log.i("Basic Integrity", basicIntegrityResult)
                        showToastLong(this, "The device is secure")
    
                        if (!basicIntegrity) {
                            Log.i("Advice", jsonObject.getString("advice"))
                        }
                    } catch (e: JSONException) {
                        val errorMsg = e.message
                        Log.e("JsonException", errorMsg ?: "unknown error")
                    }
                }
                .addOnFailureListener { e ->
                    val errorMsg: String? = if (e is ApiException) {
                        SafetyDetectStatusCodes.getStatusCodeString(e.statusCode) + ": " + e.message
                    } else {
                        e.message
                    }
                    Log.e("TAG", errorMsg.orEmpty())
                    errorMsg?.let { showToastShort(this, it) }
                }

16、使用推送服务和分析服务实现面向受众的推送

推送服务实现消息发送。分析服务提供用户数据,推送服务能更精准地把消息推送给目标用户。

  1. 将编译依赖项添加到“dependencies”中。

    dependencies {
              implementation 'com.huawei.hms:push:6.5.0.300'
    		implementation 'om.huawei.hms:hianalytics:6.5.0.300'
    }
  2. 在Activity或Fragment中启用华为分析服务。

    HiAnalyticsTools.enableLog()
    HiAnalytics.getInstance(this)
  3. Generate a user's token.

    fun getPushToken(context: Context) {
            coroutineScope.launch {
                async(dispatcher) {
                    val tokenScope = "HCM"
                    val token = HmsInstanceId.getInstance(context).getToken("YOUR_APP_ID", tokenScope)
                    Log.i("PushNotificationTAG", "get token:$token")
    
                    userPushTokenLiveData.postValue(token)
                }
            }
        }
  4. 在AppGallery Connect推送服务页面发送通知。

    cke_677044.png

17、真实用户验证

静态活体检测服务实时捕捉人脸,无需用户另外操作即可检测是否为真实人脸还是虚假人脸(例如,捕捉的人脸图片、视频截图、面具等)

  1. 将编译依赖项添加到“dependencies”中。

    dependencies {
        implementation 'com.huawei.hms:ml-computer-vision-livenessdetection:2.2.0.300302'}
  2. 在AndroidManifest.xml文件中添加权限,确保活体检测服务能访问摄像机。

    <uses-permission android:name="android.permission.CAMERA" />
  3. 添加必要条件并获得用户同意后,添加验证用户是否真实的代码。

    private fun livenessDetection() {
            //获取活体检测配置并设置面具和太阳镜检测。
            val captureConfig: MLLivenessCaptureConfig = MLLivenessCaptureConfig.Builder().setOptions(
                MLLivenessCaptureConfig.DETECT_MASK
            ).build()
    
            //获取活体检测插件实体。
            val capture: MLLivenessCapture = MLLivenessCapture.getInstance()
            capture.setConfig(captureConfig)
            capture.startDetect(requireActivity(), this.callback)
        }

18、测试和验证

完成必要步骤后,将手机和电脑连接,启用USB调测模式。在Android Studio页面,点击运行 cke_799510.png您创建的项目,生成APK包。在手机上安装APK包。

  1. 安装完成后,打开应用。

  2. 使用华为账号登录。

    cke_887166.png

  3. 如您没有会议ID,输入一个ID并点击“CREATE”按钮生成会议。然后您可以把会议ID分享给好友,开始视频会议。

    cke_903520.png

  4. 如需呼叫联系人,在“Contacts”页面点击cke_869145.png

    cke_943172.png

       注意:如对方在忙,呼叫将失败。

19、恭喜您

祝贺您,您已经成功完成了本codelab并学到了:

  • 如何集成Cloud DB和WebRTC。

  • 如何集成机器学习服务和真实用户验证。

  • 如何使用推送服务和分析服务实现面向受众的提醒。

  • 如何使用Kotlin和MVVM架构。

20、参考文件

华为认证服务

开发指南 | FAQs

华为崩溃服务

开发指南 | FAQs

华为云数据库

开发指南 | FAQs

华为安全检测服务

开发指南 | FAQs

华为推送服务

开发指南 | FAQs

华为分析服务

开发指南 | FAQs

华为机器学习服务

开发指南 | FAQs

WebRTC

开发指南

您可以下载源代码

欲了解更多更全技术文章,欢迎访问https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh