zoukankan      html  css  js  c++  java
  • 如何用Nearby Service开发针对附近人群的精准广告推送功能

      当你想找一家餐厅吃饭,却不知道去哪家,这时候手机跳出一条通知,为你自动推送附近优质餐厅的信息,你会点击查看吗?当你还在店内纠结于是否买下一双球鞋时,手机应用给了你发放了老顾客5折优惠券,这样的广告你有拒绝的理由吗?

      这样的广告不仅不会引起用户的厌烦,还满足了用户的需求。更准确的广告推送,减少对用户不必要的打扰,提高用户对应用的满意度。那如何才能给自己的APP增加一个针对附近人群的精准广告推送功能呢?

    在这里插入图片描述

      可以接入华为近距离通信服务,通过蓝牙信标消息订阅功能(Nearby Beacon Message)来实现. 在商场中部署Beacon,Beacon消息提供精确的相对位置信息,当用户走近餐厅、商店时,就会收到本店预先配置好的促销消息,例如优惠券、打折信息等等,从而可以很便捷的对本店进行推广,下图是功能演示。

    在这里插入图片描述

      如果你对实现方式感兴趣,可以在Github上下载源码:
      https://github.com/HMS-Core/hms-nearby-demo/tree/master/NearbyCanteens

    1.开发准备

      如果您已经是华为的开发者,可以省略此步骤。如果您以前没有集成华为移动服务的经验,那么需要先配置AppGallery Connect,开通近距离通信服务并集成HMS SDK。相关步骤请参考官方文档

    1.1 在项目级gradle里添加华为maven仓和agcp配置

      增量添加如下maven地址和agcp配置,以下不用修改,拷贝即可。

    buildscript {
         repositories {
             google()
             jcenter()
             maven { url 'http://developer.huawei.com/repo/' }
         }
         dependencies {
             classpath 'com.android.tools.build:gradle:3.4.1'
             classpath 'com.huawei.agconnect:agcp:1.2.1.301'
         }
     }
      
     allprojects {
         repositories {
             google()
             jcenter()
             maven { url 'http://developer.huawei.com/repo/' }
         }
     }
    

    1.2 在应用级的build.gradle里面加上SDK依赖

      把近距离通信服务SDK引入,最重要的是以下com.huawei开头的SDK。

    dependencies {
         implementation fileTree(dir: 'libs', include: ['*.jar'])
         implementation 'androidx.appcompat:appcompat:1.1.0'
         implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
         testImplementation 'junit:junit:4.12'
         androidTestImplementation 'androidx.test.ext:junit:1.1.1'
         androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
         implementation "com.huawei.hmf:tasks:1.3.1.301"
         implementation "com.huawei.hms:network-grs:1.0.9.302"
         implementation 'com.huawei.agconnect:agconnect-core:1.2.1.301'
         implementation 'com.huawei.hms:nearby:4.0.4.300'
         api 'com.google.code.gson:gson:2.8.5'
     }
    

    1.3 在AndroidManifest.xml文件里面申请网络权限、蓝牙权限和位置权限

      以下权限见名知义,比如android.permission.INTERNET就是需要网络权限,android.permission.BLUETOOTH就是需要蓝牙权限。以下权限都是必须的。

    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    

    2. 代码开发

    2.1 初始化以及动态权限申请

      onCreate是当前activity创建时会调用的方法,在这个方法里头,我们可以做一些准备动作,比如必要权限的申请,以及检查手机网络、蓝牙、GPS是否开启等。

    @RequiresApi(api = Build.VERSION_CODES.P)
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         Log.i(TAG, "onCreate");
         setContentView(R.layout.activity_canteen);
         boolean isSuccess = requestPermissions(this, this);
         if (!isSuccess) {
             return;
         }
         Log.i(TAG, "requestPermissions success");
         if (!NetCheckUtil.isNetworkAvailable(this)) {
             showWarnDialog(Constant.NETWORK_ERROR);
             return;
         }
         if (!BluetoothCheckUtil.isBlueEnabled()) {
             showWarnDialog(Constant.BLUETOOTH_ERROR);
             return;
         }
         if (!GpsCheckUtil.isGpsEnabled(this)) {
             showWarnDialog(Constant.GPS_ERROR);
             return;
         }
         intView();
         init();
     }
    

      注册监听,当检测到手机蓝牙、GPS、网络未连接时,给出提示: 以下使用的是Android中的AlertDialog组件来做提示。

    private void showWarnDialog(String content) {
         DialogInterface.OnClickListener onClickListener =
             new DialogInterface.OnClickListener() {
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                     android.os.Process.killProcess(android.os.Process.myPid());
                 }
             };
         AlertDialog.Builder builder = new AlertDialog.Builder(this);
         builder.setTitle(R.string.warn);
         builder.setIcon(R.mipmap.warn);
         builder.setMessage(content);
         builder.setNegativeButton(getText(R.string.btn_confirm), onClickListener);
         builder.show();
     }
    

    2.2 接收Beacon消息的过程

      以下这个startScanning方法,是在onStart方法中被调用的,表示开始启动蓝牙扫描,并且以下的MessageHandler对象中,封装了4个回调方法(onFound表示获取到beacon消息,OnLost表示消息丢失,onDistanceChanged表示beacon与本手机的距离变化,onBleSignalChanged表示监测到beacon的信号变化)。

      最重要的就是以下的doOnFound方法,表示接收到beacon消息时,客户端的处理方式,可以做个性化展示。

    private void doOnFound(Message message) {
         if (message == null) {
             return;
         }
         String type = message.getType();
         if (type == null) {
             return;
         }
         String messageContent = new String(message.getContent());
         Log.d(TAG, "New Message:" + messageContent + " type:" + type);
         if (type.equalsIgnoreCase(Constant.CANTEEN)) {
             operateOnFoundCanteen(messageContent);
         } else if (type.equalsIgnoreCase(Constant.NOTICE)) {
             operateOnFoundNotice(messageContent);
         }
     }
    

    自定义展示:
      下面的方法只是简单的演示其中一种消息处理方式,包括客户端上的通知栏横幅通知、页面字体滑动展示等操作。

    private void operateOnFoundCanteen(String messageContent) {
         CanteenAdapterInfo canteenAdapterInfo =
                 (CanteenAdapterInfo) JsonUtils.json2Object(messageContent, CanteenAdapterInfo.class);
         if (canteenAdapterInfo == null) {
             return;
         }
         String canteenName = canteenAdapterInfo.getCanteenName();
         if (canteenName == null) {
             return;
         }
         Log.d(TAG, "canteenName:" + canteenName);
         if (!canteenNameList.contains(canteenName)) {
             return;
         }
      
         String notice = "";
         if (receivedNoticeMap.containsKey(canteenName)) {
             notice = receivedNoticeMap.get(canteenName);
         }
         int canteenImage = getCanteenImage(canteenName);
         int requestCode = getRequestCode(canteenName);
         canteenAdapterInfo.setNotice(notice);
         canteenAdapterInfo.setCanteenImage(canteenImage);
         canteenAdapterInfo.setShowNotice(true);
         canteenAdapterInfo.setRequestCode(requestCode);
      
         canteenAdapterInfoMap.put(canteenName, canteenAdapterInfo);
         canteenAdapterInfoList.add(canteenAdapterInfo);
      
         sendNotification(Constant.NOTIFICATION_TITLE, Constant.NOTIFICATION_SUBTITLE, canteenName, requestCode);
         runOnUiThread(
             new Runnable() {
                 @Override
                 public void run() {
                     searchTipTv.setText(R.string.found_tip);
                     loadingLayout.setVisibility(View.GONE);
                     canteenAdapter.setDatas(canteenAdapterInfoList);
                 }
             });
     }
    

    结后语

      本次给大家演示的demo用到了华为Nearby Service的蓝牙信标消息订阅功能

      基于Nearby Beacon Message能力不仅仅可以用来做广告推送,还可以实现如下相关功能:

    1. 汽车生活类应用集成Nearby Beacon Message功能后,可以识别用户靠近汽车,通知App启用无钥匙进入,记录行驶轨迹等。

    2. 办公类应用集成Nearby Beacon Message功能后,可快速准确记录员工打卡位置。

    3. 旅游、展览类应用集成Nearby Beacon Message功能后,当用户靠近某个展品或文物时候,能够获取相应的介绍信息。

    4. 游戏类应用使用Nearby Beacon Message,可以实现游戏和现实场景互动。通过现实物体触发游戏关卡,或者对参与线下活动的游戏玩家给予游戏道具奖励。

      更详细的开发指南可参考华为开发者联盟官网


    往期链接:超简单集成ML kit 实现听写单词播报
    原文链接:https://developer.huawei.com/consumer/cn/forum/topicview?tid=0201283747724140328&fid=18
    原作者:赵照

  • 相关阅读:
    HUAWEI防火墙双出口据链路带宽负载分担
    HUAWEI防火墙双出口根据链路优先级主备备份
    HUAWEI防火墙双出口环境下私网用户通过NAPT访问Internet
    如何实现IP话机接入交换机?
    WLAN-AC+AP,动态负载均衡用户量,避免某一个AP负载过重
    WLAN-AC+AP射频一劳永逸的调优方式
    中大型企业有线无线用户统一接入(实施笔记)
    js获取当前时间,返回日期yyyy-MM-dd
    cookie和token都存在在请求头header中,有什么区别,为什么建议使用token?
    vue中cookie的使用——将cookie放在请求头header中
  • 原文地址:https://www.cnblogs.com/developer-huawei/p/13218963.html
Copyright © 2011-2022 走看看