Android P版本 新功能介绍和兼容性处理(五)利用 Wi-Fi RTT进行室内定位

这里我们将对Android P版本的室内定位功能做个详细的说明

1)原理
在提供硬件支持的 Android P 设备上,应用可以使用全新的 RTT API 来测量与附近支持 RTT 的 Wi-Fi 接入点 (AP) 的距离。

2)要求
2.1)启用定位并开启了 Wi-Fi 扫描(在 Settings > Location 下)
2.2)具有 ACCESS_FINE_LOCATION 权限。
设备不需要连接至 AP 即可使用 RTT. 为保证隐私性,只有手机可以确定与 AP 的距离;AP 不具备该信息

3)Android P支持IEEE802.11mcWi-Fi协议(即Wi-FiRound-Trip-Time,RTT),利用此项技术及可以进行室内定位,因此为了使用此项技术,只有在硬件支持的设备上,应用才可以使用最新的RTT API以测量附近具有RTT功能的Wi-FiAP,我们可以使用uses-feature来标注这一特性

<uses-feature android:name="android.hardware.wifi.rtt" />

先看下这个标签的一些扩展

<uses-feature android:name="string"
        android:required=["true" | "false"]
        android:glEsVersion="integer" />

这里的required表示是否需要这个特征,ture表示需要这个硬件特征,才能正常工作;false表示即使手机没有这样的硬件特征,只是功能不全罢了, 但是app还是可以使用的

uses-feature主要是给应用市场的,应用市场通过读取该属性,来决定手机是否能够看见该App

举个例子:
例如一个app在uses-feature中声明了需要摄像头,且required为true,那么应用市场在分发app时就不会将该app分发给那些没有摄像头的设备上,一个没有摄像头的设备也不能通过应用市场搜索和下载到该app。但是如果用户通过其他渠道(例如官网)下载该app对应的apk文件到某个设备上,在该设备上安装此apk时,系统并不会检查uses-feature所声明的软硬件特征是否满足,如果该设备没有摄像头,同样可以安装该app。

同时uses-feature声明对应用的运行也不会产生影响(除非应用自己在代码中去判断某项feature是否满足)。这点和uses-permission是不一样的,Android系统会读取应用的uses-permission,并对应用的运行产生影响;

具体代码如下

扫描二维码关注公众号,回复: 1099289 查看本文章
package com.hwj.android.learning;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.net.wifi.rtt.RangingRequest;
import android.net.wifi.rtt.RangingResult;
import android.net.wifi.rtt.RangingResultCallback;
import android.net.wifi.rtt.WifiRttManager;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.util.List;

/**
 * Created by huangwangjian on 2018/5/7.
 * 功能描述: WIFI RTT 室内定位测试类
 */
public class WiFiRtt {

    private Context mContext;

    public WiFiRtt(Context c){
        this.mContext = c;
        IntentFilter wifiFileter = new IntentFilter();
        wifiFileter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        wifiFileter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        wifiFileter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        mContext.registerReceiver(new WifiChangeReceiver(), wifiFileter);
    }

    public class WifiChangeReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)){
                 useWifiRtt();
             }
        }
    }


    private WifiManager mWifiManager;
    private WifiRttManager mWifiRttManager;
    private WifiRttHandler mWifiRttHandler;

    /*
     * 室内定位主要使用WifiRttManager.java
     * 该类主要利用 IEEE802.11mc Wi-Fi Round Trip Time (RTT) technology去侦测手机和Ap之间的距离
     * 主要api为 startRanging,其作用是测量AP的距离,因为测试需要对多个ap侦测,是一个批量侦测行为
     * 顾我们会用到以下Api:addAccessPoint(ScanResult)和addAccessPoints(List)来表示侦测这些AP
     *
     * startRanging接口Requires the ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE and ACCESS_WIFI_STATE permissions.
     * startRanging接口参数详解
     * 第一个参数:表示发起测距请求,必须不为null
     * 第二个参数:表示请求有结果之后的回调
     */
    @SuppressLint("WrongConstant")
    private void useWifiRtt(){
        mWifiRttHandler = new WifiRttHandler();
        mWifiManager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
        boolean hasRtt = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
        Log.d("hwj","**useWifiRtt**" + hasRtt);
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
            mWifiRttManager = (WifiRttManager)mContext.getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
            RangingRequest.Builder builder = new RangingRequest.Builder();
            if(mWifiManager != null){
                builder.addAccessPoints(mWifiManager.getScanResults());
            }
            if(mWifiRttManager != null){
                mWifiRttManager.startRanging(builder.build(),new RangingResultCallback(){

                    @Override
                    public void onRangingFailure(int i) {

                    }

                    /**
                     * @param list:返回的测距的ap
                     */
                    @Override
                    public void onRangingResults(List<RangingResult> list) {

                    }
                },mWifiRttHandler);
            }
        }
    }

    private class WifiRttHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    }
}
package com.hwj.android.learning;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class AndroidPDemoActivity extends Activity{


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_android_p_demo_layout);
        new WiFiRtt(this);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.hwj.android.learning">

    <uses-feature android:name="android.hardware.wifi.rtt" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

    <uses-sdk
        android:targetSdkVersion="27"></uses-sdk>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".AndroidPDemoActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

猜你喜欢

转载自blog.csdn.net/yi_master/article/details/80083365