Android技术知识Android开发经验谈Android开发

Android WebView关于定位部分研究

2018-11-03  本文已影响11人  Jaesoon

啥是H5定位

HTML5标准中提供Geolocation API,js中调用该API,用于获得用户的地理位置。
鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的。 该API被设计成即支持一次性请求,也支持反复的位置更新,以及显示的查询缓存的位置的能力。位置信息通过经纬度来呈现。需要注意的是:根据世界大地测量系统坐标[WGS84]提供地理位置信息(GPS使用的是WGS84坐标)。

The geographic position information is provided in terms of World Geodetic System coordinates [WGS84].

如何使用H5定位

Navigator接口扩展

partial interface Navigator {  
    readonly attribute Geolocation geolocation;  
};

Navigator的geolocation属性提供了与主设备相关联的位置信息的访问。

The geolocation attribute gives access to location information associated with the hosting device.

Geolocation接口

[NoInterfaceObject]  
interface Geolocation {
  void getCurrentPosition(PositionCallback successCallback,optional PositionErrorCallback errorCallback,optional PositionOptions options);  
  
  long watchPosition(PositionCallback successCallback,optional PositionErrorCallback errorCallback,optional PositionOptions options);  
  
  void clearWatch(long watchId);  
};

PositionOptions接口

dictionary PositionOptions {
  boolean enableHighAccuracy = false;
  [Clamp] unsigned long timeout = 0xFFFFFFFF;
  [Clamp] unsigned long maximumAge = 0;
};

Position接口

[NoInterfaceObject]
interface Position {
  readonly attribute Coordinates coords;
  readonly attribute DOMTimeStamp timestamp;
};

Coordinates接口

[NoInterfaceObject]
interface Coordinates {
  readonly attribute double latitude;
  readonly attribute double longitude;
  readonly attribute double? altitude;
  readonly attribute double accuracy;
  readonly attribute double? altitudeAccuracy;
  readonly attribute double? heading;
  readonly attribute double? speed;
};

he geographic coordinate reference system used by the attributes in this interface is the World Geodetic System (2d) [WGS84]. No other reference system is supported.

PositionError接口

[NoInterfaceObject]
interface PositionError {
  const unsigned short PERMISSION_DENIED = 1;
  const unsigned short POSITION_UNAVAILABLE = 2;
  const unsigned short TIMEOUT = 3;
  readonly attribute unsigned short code;
  readonly attribute DOMString message;
};

The code attribute MUST return the appropriate code from the following list:

下面一些示例展示如何获取基础位置信息

EXAMPLE 1: Example of a "one-shot" position request

function showMap(position) {
  // Show a map centered at (position.coords.latitude, position.coords.longitude).
}

// One-shot position request.
navigator.geolocation.getCurrentPosition(showMap);

EXAMPLE 2: Example of requesting repeated position updates

function scrollMap(position) {
  // Scrolls the map so that it is centered at
  //  (position.coords.latitude, position.coords.longitude).
}

// Request repeated updates.
var watchId = navigator.geolocation.watchPosition(scrollMap);

function buttonClickHandler() {
  // Cancel the updates when the user clicks a button.
  navigator.geolocation.clearWatch(watchId);
}

EXAMPLE 3: Example of requesting repeated position updates and handling errors

function scrollMap(position) {
  // Scrolls the map so that it is centered at
  //  (position.coords.latitude, position.coords.longitude).
}

function handleError(error) {
  // Update a div element with error.message.
}

// Request repeated updates.
var watchId = navigator.geolocation.watchPosition(scrollMap, handleError);

function buttonClickHandler() {
  // Cancel the updates when the user clicks a button.
  navigator.geolocation.clearWatch(watchId);
}

EXAMPLE 4: Example of requesting a potentially cached position

// Request a position. We accept positions whose age is not
// greater than 10 minutes. If the user agent does not have a
// fresh enough cached position object, it will automatically
// acquire a new one.
navigator.geolocation.getCurrentPosition(successCallback,
                                         errorCallback,
                                         {maximumAge:600000});

function successCallback(position) {
  // By using the 'maximumAge' option above, the position
  // object is guaranteed to be at most 10 minutes old.
}

function errorCallback(error) {
  // Update a div element with error.message.
}

EXAMPLE 5: Forcing the user agent to return a fresh cached position

// Request a position. We only accept cached positions whose age is not
// greater than 10 minutes. If the user agent does not have a fresh
// enough cached position object, it will immediately invoke the error
// callback.
navigator.geolocation.getCurrentPosition(successCallback,
                                         errorCallback,
                                         {maximumAge:600000, timeout:0});

function successCallback(position) {
  // By using the 'maximumAge' option above, the position
  // object is guaranteed to be at most 10 minutes old.
  // By using a 'timeout' of 0 milliseconds, if there is
  // no suitable cached position available, the user agent
  // will asynchronously invoke the error callback with code
  // TIMEOUT and will not initiate a new position
  // acquisition process.
}

function errorCallback(error) {
  switch(error.code) {
    case error.TIMEOUT:
      // Quick fallback when no suitable cached position exists.
      doFallback();
      // Acquire a new position object.
      navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
      break;
    case ... // treat the other error cases.
  };
}

function doFallback() {
  // No fresh enough cached position available.
  // Fallback to a default position.
}

EXAMPLE 6: Forcing the user agent to return any available cached position

// Request a position. We only accept cached positions, no matter what
// their age is. If the user agent does not have a cached position at
// all, it will immediately invoke the error callback.
navigator.geolocation.getCurrentPosition(successCallback,
                                         errorCallback,
                                         {maximumAge:Infinity, timeout:0});

function successCallback(position) {
  // By setting the 'maximumAge' to Infinity, the position
  // object is guaranteed to be a cached one.
  // By using a 'timeout' of 0 milliseconds, if there is
  // no cached position available at all, the user agent
  // will immediately invoke the error callback with code
  // TIMEOUT and will not initiate a new position
  // acquisition process.
  if (position.timestamp < freshness_threshold &&
      position.coords.accuracy < accuracy_threshold) {
    // The position is relatively fresh and accurate.
  } else {
    // The position is quite old and/or inaccurate.
  }
}

function errorCallback(error) {
  switch(error.code) {
    case error.TIMEOUT:
      // Quick fallback when no cached position exists at all.
      doFallback();
      // Acquire a new position object.
      navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
      break;
    case ... // treat the other error cases.
  };
}

function doFallback() {
  // No cached position available at all.
  // Fallback to a default position.
}

如何给Android设备的Webview添加定位功能

  1. 首先在AndroidManifest.xml中添加定位权限申明
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    

如果应用的target小于Android.M,至此就完成了给WebView添加支持定位功能。因为默认是许可网站获取位置的。如图:。But,你看到这篇文章时,肯定target不下于Android.M了,所以,接着看。

  1. 给WebView设置setWebChromeClient;
  2. 重写setWebChromeClient的 onGeolocationPermissionsShowPrompt() 方法;
  3. 判断App是否获得了定位权限,如果没有请求定位权限;
  4. 判断设备是否开启了定位服务,在某些情况下如果没有开启定位无法获取到定位的,如下:
  1. 调用 GeolocationPermissionsCallback 回调,设置是否许可js获取当前设备的权限

整体逻辑就是这样。中间比较复杂的是第4步。这一步需要考虑到这一点:App申请定位权限时,系统会给用户三种选择,分别是:

嗯,但愿你没有晕倒[苦笑]。我也想给你讲的简单点,但是,事实就是这么复杂,我能怎么办,我也很无奈啊[笑哭]。
好了,你们一定想说,别扯淡了,赶紧放码出来。诺,这是你要的代码

会遇到哪些问题

上一篇 下一篇

猜你喜欢

热点阅读