无法在没有 GPS 的情况下在 navigator.geolocation
Cannot get current position without GPS on react-native with navigator.geolocation
讨论和回答后的小结:
使用 EXPO sdk,您无法在 android 中未经授权 FINE_LOCATION 获取设备位置。 FINE_LOCATION 是获取位置的唯一方法,因此,您无法获取 hardware.network.location。这意味着:如果 android > 6,您无法使用 WIFI/mobile 网络获取当前位置,您必须启用位置。
博览会github讨论:https://github.com/expo/expo/issues/1339
初始问题:
我正在开发 react-native 应用程序,使用 expo 和 react-native-maps,我需要获取纬度和用户当前位置的经度。
我正在使用 navigator.geolocation API
打开 GPS 我没问题,但我需要根据网络提供商在没有 GPS 的情况下获取当前位置。
问题是当应用程序运行 with expo on android > 6 我得到这个错误:
21:50:53: Finished building JavaScript bundle in 449ms 21:50:55:
Location services are disabled
- node_modules\react-native\Libraries\BatchedBridge\NativeModules.js:80:57
in
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:347:19
in __invokeCallback
- ... 4 more stack frames from framework internals
在 IOs 和 android <=5 中效果很好。
组件代码如下:
class MyComponent extends Component {
componentWillMount = () => {
this.getCurrentLocation();
}
getCurrentLocation = () =>
navigator.geolocation.getCurrentPosition(
(position) => {
let currentUserPosition = position.coords;
alert(JSON.stringify(currentUserPosition));
},
(error) => {
console.log(error);
},
{
enableHighAccuracy: false,
timeout: 20000,
maximumAge: 0,
distanceFilter: 10
}
);
}
这是我的 package.json 亲属:
"dependencies": {
"expo": "23.0.4",
"native-base": "^2.3.5",
"react": "16.0.0",
"react-native": "0.50.4",
"react-native-extend-indicator": "^0.1.2",
"react-native-maps": "^0.19.0",
"react-native-maps-directions": "^1.3.0",
"react-native-router-flux": "4.0.0-beta.21",
"react-navigation": "1.0.0-beta.21",
"react-navigation-redux-debouncer": "^0.0.2",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
}
我希望 navigator.geolocation 在那种情况下(没有 gps)根据网络提供商获取位置,规范说..
我也尝试了 expo 的地理定位 API(试过这个例子:https://snack.expo.io/@schazers/expo-map-and-location-example),但在关闭 GPS 的情况下我无法获取我的位置。
所以..有没有办法实现我想要的?我错过了什么?
编辑(EXPO 贡献者答案):
我在 expo github (https://github.com/expo/expo/issues/1339) 上发布了相同的内容,根据他们的说法,如果没有在android 设备.. 所以.. 唯一可能发生的事情是 android 5 之前的版本默认启用位置,你可以只打开 GPS,而版本 6 和更高版本你必须指定位置级别..
有什么想法吗?
EDIT2(重要!!):
我已确认:
这是 Android 6 设备的安全设置,默认情况下它使用 GPS,我认为 android 5 或更低版本不会,所以就是这样.. 什么时候我使用第二个选项来获取位置!
事实上,强制用户启用位置就像 "hey, use your GPS!",并且有很多应用程序可以在不打开位置的情况下为您提供近似位置(例如优步),所以问题是的,有没有办法只使用 wifi 获取这个 api 的位置?
Android 中的常见错误。不使用第三个参数试试:
getCurrentLocation = () =>
navigator.geolocation.getCurrentPosition(
(position) => {
let currentUserPosition = position.coords;
alert(JSON.stringify(currentUserPosition));
},
(error) => {
console.log(error);
}
);
所以,我只是稍微研究了一下代码,基本上所有 LocationModule 所做的就是将请求直接发送到 Android。
它只是调用这个方法:
现在,如果您阅读该位置,则位置显示为 FINE_LOCATION 或 COARSE_LOCATION。
通常只是添加精细的位置权限,但我认为也许要访问 Wifi 位置,您需要将粗略的权限添加到应用程序中。你们都有吗?
https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION
如果没有,我会将该权限添加到应用程序中,然后重试。
您在这里处理的问题是关于 EXPO 的,因为位置请求 API 在 Android 5(API 21).
之后发生了变化
在 API 21 之前,您需要添加到 ACCESS_FINE_LOCATION
(Wifi/Network 和 GPS 提供商)和 ACCESS_COARSE_LOCATION
(仅 GPS 许可)位置权限。但是,自 Android 5 起,api 更改为 android.hardware.location.network
和 android.hardware.location.gps
。
当您的目标用户包括 Android 5 +/-。您需要将这两种权限类型添加到您的 android 清单中,例如:
<manifest ... >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- for Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.location.network" />
</manifest>
但是,世博会的人似乎只包括 android 清单中的新权限。因此,您需要做的是更改 android 清单。然而,expo 只允许访问程序的纯 JS 部分,而不是本地代码。因此,您需要从 EXPO 分离以添加本机模块或更改。
在expo文档中,在this link中解释了分离过程,过程很简单:
使用 npm 全局安装 expo 包:
npm install -g exp
在您的项目目录中,运行 分离代码,它将在您的项目目录中构建 android 和 ios 文件夹:
exp detach
然后您可以在 android 清单文件中进行所需的更改。
我遇到了同样的问题并尝试了很多库来获取用户位置。 navigator.geolocation API did not gave me location every time on android instead it just give mostly timeout error only. So then I tried react native background geolocation that start using the gps continuously then I find react native geolocation service and the author clearly mentioned 即:
Since this library was meant to be a drop-in replacement for the RN's
Geolocation API, the usage is pretty straight forward, with some extra
error cases to handle.
这就是我一直需要的,我想你也应该试试这个。
看看这个 AndroidManifest
文件,作者正在使用所有类型的位置。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.agontuk.RNFusedLocation">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
对于测试示例,您只需遵循 RN Geolocation API 建议的相同说明。这是使用 React Native 地理定位服务的简单示例:
import Geolocation from 'react-native-geolocation-service';
componentDidMount() {
// Instead of navigator.geolocation, just use Geolocation.
if (hasLocationPermission) {
Geolocation.getCurrentPosition(
(position) => {
console.log(position);
},
(error) => {
// See error code charts below.
console.log(error.code, error.message);
},
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
);
}
}
因此在 getCurrentPosition
的第三个参数中使用 enableHighAccuracy
false 以使用网络获取用户位置,使用 true 以使用 gps 获取更准确的位置。参见 this option documentation。
此 repo 的作者还提供了 example project 您可以尝试使用 enableHighAccuracy
false 并第一次关闭位置但是当您 运行 该应用程序时它会要求位置权限将显示应用程序想要访问 wifi 或手机网络提供的位置。
由于您正在使用 expo,因此您不能使用 react native geolocation service for that you need to follow 进行分离并获取 android 和 iOS 项目,以便您可以配置这两个项目。如果您需要更多信息,请告诉我。
就我而言,我通过在 AndroidManifest.xml 中添加以下内容解决了我的问题。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
首先在您的应用中授予权限
对于 Ios:您需要在 Info.plist
中包含 NSLocationWhenInUseUsageDescription
键
对于android:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
从这里我们得到纬度和经度
代码 ==>
navigator.geolocation.getCurrentPosition(
(position) => {
const initialPosition = JSON.stringify(position);
// console.log(initialPosition);
this.setState({ initialPosition });
},
//(error) => alert(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
this.watchID = navigator.geolocation.watchPosition((position) => {
const lastPosition = JSON.stringify(position);
//this.setState({ longitude: position.coords.longitude, latitude: position.coords.latitude });
//this._getWheaterData();
AsyncStorage.setItem('latitude',position.coords.latitude.toString())
AsyncStorage.setItem('longitude',position.coords.longitude.toString())
},
// (error) => alert(error.message),
// console.log(error),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 });
讨论和回答后的小结:
使用 EXPO sdk,您无法在 android 中未经授权 FINE_LOCATION 获取设备位置。 FINE_LOCATION 是获取位置的唯一方法,因此,您无法获取 hardware.network.location。这意味着:如果 android > 6,您无法使用 WIFI/mobile 网络获取当前位置,您必须启用位置。
博览会github讨论:https://github.com/expo/expo/issues/1339
初始问题:
我正在开发 react-native 应用程序,使用 expo 和 react-native-maps,我需要获取纬度和用户当前位置的经度。
我正在使用 navigator.geolocation API
打开 GPS 我没问题,但我需要根据网络提供商在没有 GPS 的情况下获取当前位置。
问题是当应用程序运行 with expo on android > 6 我得到这个错误:
21:50:53: Finished building JavaScript bundle in 449ms 21:50:55: Location services are disabled - node_modules\react-native\Libraries\BatchedBridge\NativeModules.js:80:57 in - node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:347:19 in __invokeCallback - ... 4 more stack frames from framework internals
在 IOs 和 android <=5 中效果很好。
组件代码如下:
class MyComponent extends Component {
componentWillMount = () => {
this.getCurrentLocation();
}
getCurrentLocation = () =>
navigator.geolocation.getCurrentPosition(
(position) => {
let currentUserPosition = position.coords;
alert(JSON.stringify(currentUserPosition));
},
(error) => {
console.log(error);
},
{
enableHighAccuracy: false,
timeout: 20000,
maximumAge: 0,
distanceFilter: 10
}
);
}
这是我的 package.json 亲属:
"dependencies": {
"expo": "23.0.4",
"native-base": "^2.3.5",
"react": "16.0.0",
"react-native": "0.50.4",
"react-native-extend-indicator": "^0.1.2",
"react-native-maps": "^0.19.0",
"react-native-maps-directions": "^1.3.0",
"react-native-router-flux": "4.0.0-beta.21",
"react-navigation": "1.0.0-beta.21",
"react-navigation-redux-debouncer": "^0.0.2",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
}
我希望 navigator.geolocation 在那种情况下(没有 gps)根据网络提供商获取位置,规范说..
我也尝试了 expo 的地理定位 API(试过这个例子:https://snack.expo.io/@schazers/expo-map-and-location-example),但在关闭 GPS 的情况下我无法获取我的位置。
所以..有没有办法实现我想要的?我错过了什么?
编辑(EXPO 贡献者答案):
我在 expo github (https://github.com/expo/expo/issues/1339) 上发布了相同的内容,根据他们的说法,如果没有在android 设备.. 所以.. 唯一可能发生的事情是 android 5 之前的版本默认启用位置,你可以只打开 GPS,而版本 6 和更高版本你必须指定位置级别..
有什么想法吗?
EDIT2(重要!!):
我已确认:
这是 Android 6 设备的安全设置,默认情况下它使用 GPS,我认为 android 5 或更低版本不会,所以就是这样.. 什么时候我使用第二个选项来获取位置!
事实上,强制用户启用位置就像 "hey, use your GPS!",并且有很多应用程序可以在不打开位置的情况下为您提供近似位置(例如优步),所以问题是的,有没有办法只使用 wifi 获取这个 api 的位置?
Android 中的常见错误。不使用第三个参数试试:
getCurrentLocation = () =>
navigator.geolocation.getCurrentPosition(
(position) => {
let currentUserPosition = position.coords;
alert(JSON.stringify(currentUserPosition));
},
(error) => {
console.log(error);
}
);
所以,我只是稍微研究了一下代码,基本上所有 LocationModule 所做的就是将请求直接发送到 Android。
它只是调用这个方法:
现在,如果您阅读该位置,则位置显示为 FINE_LOCATION 或 COARSE_LOCATION。
通常只是添加精细的位置权限,但我认为也许要访问 Wifi 位置,您需要将粗略的权限添加到应用程序中。你们都有吗?
https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION
如果没有,我会将该权限添加到应用程序中,然后重试。
您在这里处理的问题是关于 EXPO 的,因为位置请求 API 在 Android 5(API 21).
之后发生了变化在 API 21 之前,您需要添加到 ACCESS_FINE_LOCATION
(Wifi/Network 和 GPS 提供商)和 ACCESS_COARSE_LOCATION
(仅 GPS 许可)位置权限。但是,自 Android 5 起,api 更改为 android.hardware.location.network
和 android.hardware.location.gps
。
当您的目标用户包括 Android 5 +/-。您需要将这两种权限类型添加到您的 android 清单中,例如:
<manifest ... >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- for Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.location.network" />
</manifest>
但是,世博会的人似乎只包括 android 清单中的新权限。因此,您需要做的是更改 android 清单。然而,expo 只允许访问程序的纯 JS 部分,而不是本地代码。因此,您需要从 EXPO 分离以添加本机模块或更改。
在expo文档中,在this link中解释了分离过程,过程很简单:
使用 npm 全局安装 expo 包:
npm install -g exp
在您的项目目录中,运行 分离代码,它将在您的项目目录中构建 android 和 ios 文件夹:
exp detach
然后您可以在 android 清单文件中进行所需的更改。
我遇到了同样的问题并尝试了很多库来获取用户位置。 navigator.geolocation API did not gave me location every time on android instead it just give mostly timeout error only. So then I tried react native background geolocation that start using the gps continuously then I find react native geolocation service and the author clearly mentioned 即:
Since this library was meant to be a drop-in replacement for the RN's Geolocation API, the usage is pretty straight forward, with some extra error cases to handle.
这就是我一直需要的,我想你也应该试试这个。
看看这个 AndroidManifest
文件,作者正在使用所有类型的位置。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.agontuk.RNFusedLocation">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
对于测试示例,您只需遵循 RN Geolocation API 建议的相同说明。这是使用 React Native 地理定位服务的简单示例:
import Geolocation from 'react-native-geolocation-service';
componentDidMount() {
// Instead of navigator.geolocation, just use Geolocation.
if (hasLocationPermission) {
Geolocation.getCurrentPosition(
(position) => {
console.log(position);
},
(error) => {
// See error code charts below.
console.log(error.code, error.message);
},
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
);
}
}
因此在 getCurrentPosition
的第三个参数中使用 enableHighAccuracy
false 以使用网络获取用户位置,使用 true 以使用 gps 获取更准确的位置。参见 this option documentation。
此 repo 的作者还提供了 example project 您可以尝试使用 enableHighAccuracy
false 并第一次关闭位置但是当您 运行 该应用程序时它会要求位置权限将显示应用程序想要访问 wifi 或手机网络提供的位置。
由于您正在使用 expo,因此您不能使用 react native geolocation service for that you need to follow
就我而言,我通过在 AndroidManifest.xml 中添加以下内容解决了我的问题。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
首先在您的应用中授予权限 对于 Ios:您需要在 Info.plist
中包含NSLocationWhenInUseUsageDescription
键
对于android:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
从这里我们得到纬度和经度 代码 ==>
navigator.geolocation.getCurrentPosition(
(position) => {
const initialPosition = JSON.stringify(position);
// console.log(initialPosition);
this.setState({ initialPosition });
},
//(error) => alert(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
this.watchID = navigator.geolocation.watchPosition((position) => {
const lastPosition = JSON.stringify(position);
//this.setState({ longitude: position.coords.longitude, latitude: position.coords.latitude });
//this._getWheaterData();
AsyncStorage.setItem('latitude',position.coords.latitude.toString())
AsyncStorage.setItem('longitude',position.coords.longitude.toString())
},
// (error) => alert(error.message),
// console.log(error),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 });