web-dev-qa-db-ja.com

navigator.geolocationのreact-nativeでGPSなしで現在位置を取得することはできません

ディスカッションと回答後の概要

eXPO SDKを使用すると、AndroidでFINE_LOCATIONを付与しないとデバイスの位置を取得できません。 FINE_LOCATIONは位置を取得する唯一の方法であるため、hardware.network.locationを取得することはできません。つまり、Android> 6では、WIFI /モバイルネットワークを使用して現在の場所を取得できないため、場所を有効にする必要があります。

Expo githubディスカッション:https://github.com/expo/expo/issues/1339

最初の問題:

react-nativeアプリケーションで作業中のim、expoとreact-native-mapsを使用、ユーザーの現在位置の緯度と経度を取得する必要があります。

navigator.geolocation API を使用している

gPSをオンにすると問題はありませんが、ネットワークプロバイダーに基づいて、GPSなしで現在の位置を取得する必要があります。

問題は、アプリケーションの実行時にandroiodでの博覧会> 6このエラーが発生することです:

21:50:53:449msでJavaScriptバンドルの構築を終了21:50:55:位置情報サービスは無効-node_modules\react-native\Libraries\BatchedBridge\NativeModules.js:80:57 in-node_modules\react-native\Libraries\__invokeCallbackのBatchedBridge\MessageQueue.js:347:19-...フレームワーク内部からのさらに4つのスタックフレーム

IOと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 depencendiesです:

"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のGeolocation API(この例を試しました: https://snack.expo.io/@schazers/expo-map-and-location-example )とGPSを有効にしてOFF位置情報を取得できません。

だから..私が欲しいものを達成する方法はありますか?私は何かが欠けていますか?

編集(EXPO貢献者の回答):

私は同じことをexpo githubに投稿しました( https://github.com/expo/expo/issues/1339 )、彼らによると、navigator.geolocationを使用せずに現在の位置を取得することは不可能ですAndroidデバイスで有効になっている場所のレベル.。.唯一起こりうることは、Android 5よりも古いバージョンではデフォルトで場所が有効になっており、 GPSのみをオンにすることができます。バージョン6以降では、位置レベルを指定する必要があります..

何か案は?

EDIT2(重要!!):

私はこれを確認しました:

enter image description here

これは、Android 6デバイスのセキュリティ設定です。デフォルトではGPSを使用します。Android 5以下はそうではないので、それが問題です。 2番目のオプションを使用すると、場所が取得されます!

実際には、ユーザーにロケーションの有効化を強制することは「ちょっと、GPSを使う!」のようなものであり、ロケーションをオンにせずに近接位置を提供するアプリケーションがたくさんあります(たとえばUberなど)。 wifiのみを使用して、このAPIで位置を取得する方法はありますか?

11

Android 5(API 21)の後にロケーションリクエストAPIが変更されたため、ここで扱っている問題はEXPOにあります。

API 21より前は、ACCESS_FINE_LOCATION(Wifi /ネットワークと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のドキュメントでは、分離プロセスは このリンク で説明されています。手順は簡単です:

  1. npmを使用してexpoパッケージをグローバルにインストールします。

    npm install -g exp

  2. プロジェクトディレクトリ内でデタッチメントコードを実行すると、プロジェクトディレクトリにAndroidおよびiosフォルダーが構築されます。

    exp detach

その後、Androidマニフェストファイルで必要な変更を加えることができます。

8

Androidの一般的なバグ。 3番目のパラメーターを使用せずに試してください。

getCurrentLocation = () =>
         navigator.geolocation.getCurrentPosition(
            (position) => {
                let currentUserPosition = position.coords;
                alert(JSON.stringify(currentUserPosition));
            },
            (error) => {
                console.log(error);
            }
        );

したがって、コードを少し掘り下げただけで、基本的にLocationModuleが行うことは、Androidに直接リクエストを送信することだけです。

このメソッドを呼び出すだけです:

https://developer.Android.com/reference/Android/location/LocationManager.html#getLastKnownLocation(Java.lang.String)

今、あなたがそれを読んだ場合、場所はFINE_LOCATIONまたはCOARSE_LOCATIONと言います。

通常、ロケーションの許可を追加するだけですが、Wifiの場所にアクセスするには、アプリに粗い許可を追加する必要があると思います。両方ありますか?

https://developer.Android.com/reference/Android/Manifest.permission.html#ACCESS_COARSE_LOCATION

そうでない場合は、その許可をアプリに追加して、再試行します。

3
sfratini

私の場合、AndroidManifest.xmlに以下を追加して問題を解決しました。

<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
0

まず、アプリに権限を付与しますIosの場合:Info.plistにNSLocationWhenInUseUsageDescriptionキーを含める必要があります

アンドロイド用:

<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />

ここから緯度経度経度を取得しますCODE ==>

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 });
0