一个帖子教你实现 商品下单、获取商品订单信息、商品送货时发送通知 一体化功能
原创
©著作权归作者所有:来自51CTO博客作者华为开发者论坛的原创作品,请联系作者获取转载授权,否则将追究法律责任
1、介绍
总览
通过无缝数据库结构,在保证数据的可用性、一致性、安全性外,云数据库能够实现数据在客户端和云端之间的无缝同步。云函数提供serverless环境,AppGallery Connect的其他服务为云函数提供事件源。监听事件源可以触发相关函数。
您将建立什么
在本次codelab中,您将建立一个示例项目用于体验云数据库和云函数。云数据库中数据发生变化时,云函数HTTP触发器触发函数发送通知。流程如下:
- 商品下单。
- 获取商品订单信息。
- 商品送货时,发送通知。
您将学会什么
在本次codelab中,您将学习:
- 如何在AppGallery Connect中创建项目和新建应用。
- 如何集成云数据库和云函数。
- 如何使用云函数并且使用HTTP触发器发送通知。
2、您需要什么
硬件需求
- 一台笔记本或台式电脑。
- 一部装有EMUI 8.0或以上版本的华为手机,运行HMS Core (APK) 5.0.1.301或以上版本;或一部装有安卓7.0或以上版本的非华为手机,运行HMS Core (APK) 5.0.1.301或以上版本。该手机用于demo的运行和调测。
软件需求
- JDK版本:1.8或以上
- Android Studio版本:3.X或以上
- SDK平台版本:24或以上
- targetSdkVersion:29
- compileSdkVersion:29
- Gradle版本:4.6或以上
必备知识
安卓应用开发基础知识
3、能力接入准备
集成前,需要完成以下准备工作:
在进行准备前,请先注册开发者帐号。
- 在AppGallery Connect中创建项目和应用。
- 创建Android Studio项目。
- 生成签名证书。
- 生成签名证书指纹。
- 在AppGallery Connect中将签名指纹添加到应用中。
- 添加必要配置。
- 配置项目签名。
- 同步项目。
详情请参见HUAWEI HMS Core集成准备。
4、集成HMS Core SDK
添加您应用的AppGallery Connect配置文件
- 登录AppGallery Connect,点击“我的项目”,在项目列表中找到并点击您的项目。
- 在“项目设置”页面选择“常规”页签。
- 在“项目”区域下点击“数据处理位置”后的“启用”。
- 点击“应用”区域的“agconnect-services.json”下载配置文件。
- 把agconnect-services.json文件拷贝到项目的应用级根目录下。
添加编译依赖
- 打开应用级的“build.gradle”文件。
- 在dependencies中添加如下编译依赖。
dependencies {
//添加云函数和云数据库依赖。
implementation 'com.huawei.agconnect:agconnect-cloud-database:{version}'
implementation 'com.huawei.agconnect:agconnect-function-ktx:{version}'
}
注意:
将{version}替换为云数据库的最新版本号,例如,com.huawei.agconnect:agconnect-cloud-database:1.5.3.300。最新的版本号请参见SDK版本更新说明。
将{version}替换为云函数的最新版本号,例如,com.huawei.agconnect:agconnect-function-ktx 1.7.1.300。最新的版本号请参见SDK版本更新说明
- 在build.gradle文件中,设置Java源代码的兼容性模式。
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
- 在应用级build.gradle文件中设置minSdkVersion。
android {
...
defaultConfig {
...
minSdkVersion 26
...
}
...
}
- 检查是否已添加AppGallery Connect插件。如没有,在应用级build.gradle文件中添加该插件。
apply plugin: 'com.huawei.agconnect'
配置混淆脚本
编译APK前需要配置混淆脚本,避免混淆HMS Core SDK。如果出现混淆,HMS Core SDK可能无法正常工作。
Android Studio开发环境里的混淆脚本是“proguard-rules.pro”。
- 加入排除HMS SDK的混淆配置。
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
5、设计UI





6、集成云函数
- 需要在handler.js文件中写入发送通知的函数。
- 在AppGallery Connect中创建函数。
- 输入函数名,上传创建的handler.js文件,并保存设置。
- 函数创建完成后,添加HTTP触发器。
7、初始化云数据库
- 初始化云数据库。
override suspend fun initialize(): Result<Unit> {
handler = CompletableDeferred()
AGConnectCloudDB.initialize(context)
initializeCloudDB()
initializeZone()
handler?.let { return it.await() }
?: run { return Result.Error() }
}
private fun initializeCloudDB() {
val instance = AGConnectInstance.buildInstance(
AGConnectOptionsBuilder().setRoutePolicy(
AGCRoutePolicy.GERMANY
).build(context)
)
mCloudDB = AGConnectCloudDB.getInstance(instance, AGConnectAuth.getInstance())
mCloudDB.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo())
}
private fun initializeZone() {
val mConfig = CloudDBZoneConfig(
"CourierDbZone",
CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC
)
mConfig.persistenceEnabled = true
val task = mCloudDB.openCloudDBZone2(mConfig, true)
task.addOnSuccessListener {
cloudDBZone = it
handler?.complete(Result.Success(Unit))
}.addOnFailureListener {
handler?.complete(Result.Error(it.message))
}
}
- 产品列表由云数据库提供。用户在产品列表中选择某个产品时,售卖该产品的商店的经纬度发送到快递员的界面上。
override suspend fun getOrders(): List<Order> {
val result = CompletableDeferred<List<Order>>()
cloudDBZone?.let { dbZone ->
dbZone.executeQuery(
CloudDBZoneQuery.where(Order::class.java),
CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_DEFAULT
).addOnCompleteListener{
if(it.isSuccessful) {
val cursor = it.result.snapshotObjects
val orders = mutableListOf<Order>()
while(cursor.hasNext()) {
orders.add(cursor.next())
}
result.complete(orders)
}else {
throw it.exception
}
}
}?: run {
throw Exception("Cloud DB not initialized.")
}
return result.await()
}
8、使用Location和Directions API
- 查看权限。
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- 在Android Studio页面,选择File > Sync Project with Gradle Files同步项目。
- 根据用户位置信息,通过Directions API创建路径。
private fun getLastLocation() {
val mLocationRequest = LocationRequest()
mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
mLocationRequest.numUpdates = 1
fusedLocationProviderClient.requestLocationUpdates(
mLocationRequest,
mLocationCallback,
Looper.getMainLooper()
)
}
private val mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
courierTrackingViewModel.createRoute(
args.storeLocation,
locationResult.lastLocation,
DirectionType.DRIVING
)
}
}
@POST("{type}")
suspend fun getDirections(
@Path(value = "type",encoded = true) type : String,
@Body directionRequest: DirectionsRequest,
@Query("key") api_key: String,
): DirectionsNetwork
- 当Directions API返回成功结果后,标记用户和商店位置。
private fun addMarker(latLng: LatLng, title: String, icon: Int): Marker? {
val options = MarkerOptions()
.position(latLng)
.title(title)
.icon(BitmapDescriptorFactory.fromResource(icon))
return hMap?.addMarker(options)
}
- 在地图上,用折现添加Directions API返回的经纬度信息。
private fun addPolylines(route: Route) {
route.pathPoints?.let { pathPoints ->
val options = PolylineOptions()
pathPoints.forEach { latLng ->
options.add(latLng)
}
options.color(
ContextCompat.getColor(
requireContext(), R.color.yellow_700
)
)
options.width(5f)
hMap?.addPolyline(options)
}
}
9、HTTP触发器场景
您可以指定云函数的HTTP触发器给用户发送消息,通知他们快递员已到达。用户可以在地图上查看订单位置。
private suspend fun starSimulation(pathPoints: List<LatLng>?) {
var marker: Marker?
pathPoints?.let { paths ->
paths.forEach { latLng ->
marker = addMarker(latLng,"Courier",R.drawable.scooter_icon_128)
animateCamera(latLng)
delay(100)
marker?.remove()
}
}
sendNotification()
}
private fun sendNotification() {
val pushToken = activity?.getSharedPreferences(
"device_token", Context.MODE_PRIVATE
)?.getString("device_token",null)
pushToken?.let { token ->
val parameterMap: HashMap<String, String> = HashMap()
parameterMap["deviceToken"] = token
AGConnectFunction.getInstance()
.wrap("courier-tracking-notification-\$latest")
.call(parameterMap)}
findNavController().popBackStack()}

10、恭喜您
祝贺您,您已经成功完成本codelab并学到了:
- 如何继承云数据库和云函数。
- 如何通过HTTP触发器发送通知。
11、参考文件
您可以下载源代码。
欲了解更多更全技术文章,欢迎访问https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh