精准推送是移动端产品留存阶段的主要运营手段,精准推送常常会与用户画像紧密结合,针对用户的喜好、画像,采用不同策略,但基于用户所属区域推送消息却很难实现。目前市面上大多数第三方消息推送服务商,在系统未深度定制的情况下,通常不支持将推送人群范围精确到某个商圈或较小的区域,而地理围栏技术可以很好地弥补这一点。地理围栏就是用一个虚拟的栅栏围出一个虚拟地理边界,当手机进入、离开或在这个围起来的特定地理区域内活动时,手机可以自动接收通知和警告消息。将地理围栏和消息推送相结合,即可实现对特定区域人群的精准消息推送。
举个例子,一款旅游出行类App想在江苏推广其门票业务,他可以针对南京、苏州等城市的热门旅游景点划定地理围栏,当目标受众在特定时间段到达某个旅游景点附近时,将会收到一条特定消息推送“XX景点门票优惠券已放入账户中,立即领取>>”在用户有购买XX景点门票需求时应景推送优惠信息,让用户无法拒绝。
实现方法
用华为定位服务地理围栏能力结合推送服务消息推送能力,就可实现对指定范围人群的精准消息推送。通过设置特定的区域,可以检测用户的事件状态,例如他们何时进入、离开或停留在该区域,一旦满足触发条件,用户设备将实时收到消息推送。即使应用不在后台运行,也可以在用户设备上传递和显示消息,消息传递率可达99%。
效果展示:
- 在测试设备上安装演示应用。
- 启动演示应用程序,点击地理围栏屏幕上的添加地理围栏,然后设置相关参数以创建地理围栏。
- 等待地理围栏被触发。
- 在触发地理围栏时检查收到的消息。
开发步骤
- 配置SDK的Maven仓地址。
- (Android Studio的代码库配置在Gradle插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请根据您当前的Gradle插件版本,选择对应的配置过程。这里以7.1版本为例)
a) 在“buildscript > dependencies”中增加agcp插件配置。
buildscript {
i. dependencies {
ii. ...
iii. // 增加agcp插件配置,推荐您使用最新版本的agcp插件。
iv. classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
v. }
b) 项目级“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/' }
}
}
2.在“dependencies ”中添加如下编译依赖。
//应用级的“build.gradle”文件
dependencies {
implementation 'com.huawei.hms:location: 6.4.0.300'
implementation 'com.huawei.hms:push: 6.3.0.304'
}
- 在 AndroidManifest.xml 文件中声明系统权限。
因华为定位服务采用GNSS、Wi-Fi、基站等多种混合定位模式进行定位,赋予您的应用程序快速、精准地获取用户位置信息的能力,需要用到网络,精确的位置权限,粗略的位置权限如果您需要应用程序在后台执行时也具备持续定位能力,需要在Manifest文件中申请ACCESS_BACKGROUND_LOCATION权限:
注:由于ACCESS_FINE_LOCATION,WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE是危险的系统权限,因此,您需要动态的申请这些权限。如果权限不足,Location Service将会拒绝为您的应用开启定位。
关键代码说明
代码文件路径: com.huawei.hmssample2.geofence\GeoFenceActivity.java
如果您的应用需要集成围栏Service实现服务推送,仅仅需要参考将GeoFenceActivity集成到您的应用中在接收围栏回调的同时发出推送的广播,即可实现。
- 触发地理围栏。
a) 根据需要创建地理围栏和地理围栏组,并设置相应的参数,比如围栏半径,触发时间等。
if (checkStyle(geofences, data.uniqueId) == false) {
LocationLog.d("GeoFenceActivity", "not unique ID!");
LocationLog.i("GeoFenceActivity", "addGeofence failed!");
return;
}
geoBuild.setRoundArea(data.latitude, data.longitude, data.radius);
geoBuild.setUniqueId(data.uniqueId);
geoBuild.setConversions(data.conversions);
geoBuild.setValidContinueTime(data.validContinueTime);
geoBuild.setDwellDelayTime(data.dwellDelayTime);
geoBuild.setNotificationInterval(data.notificationInterval);
geofences.add(geoBuild.build());
LocationLog.i("GeoFenceActivity", "addGeofence success!");
b) 设置好相关参数之后通过intent注册广播
GeofenceRequest.Builder geofenceRequest = new GeofenceRequest.Builder();
geofenceRequest.createGeofenceList(GeoFenceData.returnList());
if (trigger.getText() != null) {
int trigGer = Integer.parseInt(trigger.getText().toString());
geofenceRequest.setInitConversions(trigGer);
LocationLog.d(TAG, "trigger is " + trigGer);
} else {
geofenceRequest.setInitConversions(5);
LocationLog.d(TAG, "default trigger is 5");
}
final PendingIntent pendingIntent = getPendingIntent();
try {
geofenceService.createGeofenceList(geofenceRequest.build(), pendingIntent)
.addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(Task task) {
if (task.isSuccessful()) {
LocationLog.i(TAG, "add geofence success!");
setList(pendingIntent, GeoFenceData.getRequestCode(), GeoFenceData.returnList());
GeoFenceData.createNewList();
} else {
// Get the status code for the error and log it using a user-friendly message.
LocationLog.w(TAG, "add geofence failed : " + task.getException().getMessage());
}
}
});
} catch (Exception e) {
LocationLog.i(TAG, "add geofence error:" + e.getMessage());
}
private PendingIntent getPendingIntent() {
Intent intent = new Intent(this, GeoFenceBroadcastReceiver.class);
intent.setAction(GeoFenceBroadcastReceiver.ACTION_PROCESS_LOCATION);
Log.d(TAG, "new request");
GeoFenceData.newRequest();
return PendingIntent.getBroadcast(this, GeoFenceData.getRequestCode(), intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
- 触发消息推送。
在GeoFenceBroadcastReceiver的onReceive接收到围栏触发成功提示后发送推送通知,在通知栏接收通知并展示。
GeofenceData geofenceData = GeofenceData.getDataFromIntent(intent);
if (geofenceData != null) {
int errorCode = geofenceData.getErrorCode();
int conversion = geofenceData.getConversion();
ArrayList list = (ArrayList) geofenceData.getConvertingGeofenceList();
Location myLocation = geofenceData.getConvertingLocation();
boolean status = geofenceData.isSuccess();
sb.append("errorcode: " + errorCode + next);
sb.append("conversion: " + conversion + next);
if (list != null) {
for (int i = 0; i < list.size(); i++) {
sb.append("geoFence id :" + list.get(i).getUniqueId() + next);
}
}
if (myLocation != null) {
sb.append("location is :" + myLocation.getLongitude() + " " + myLocation.getLatitude() + next);
}
sb.append("is successful :" + status);
LocationLog.i(TAG, sb.toString());
Toast.makeText(context, "" + sb.toString(), Toast.LENGTH_LONG).show();
//
new PushSendUtils().netSendMsg(sb.toString());
}
注意:使用示例代码创建的地理围栏将触发转化类型 1 和 4 的两个回调。一个在用户进入地理围栏时触发,另一个在用户停留在地理围栏内时触发。如果在代码中将 Trigger 设置为 7,则会配置所有方案(包括进入、停留和离开地理围栏)的回调。
完成以上开发步骤就可以完成地理围栏推送功能,实现在指定区域内推送消息通知实现精准营销。
了解更多详情>>
访问华为开发者联盟官网
获取开发指导文档
华为移动服务开源仓库地址:GitHub、Gitee
关注我们,第一时间了解 HMS Core 最新技术资讯~