【问题标题】:Retrieving last known geolocation - Phonegap检索最后一个已知的地理位置 - Phonegap
【发布时间】:2012-06-05 12:12:08
【问题描述】:

以下代码

navigator.geolocation.getCurrentPosition(getGeo_Success, getGeo_Fail, {
    enableHighAccuracy : true,
    maximumAge : Infinity,
    timeout : 15000
});

获取当前 GPS 位置 - 但是 - 必须有有效的 GPS 信号(当然,设备的 GPS 功能应该打开)。

如果我们查看其他应用程序(例如,Android 设备上的地图) - 它知道如何检索 最后已知 位置 - 即使我没有使用更新地理位置的应用程序 在打开地图之前 - 它会在地图上显示我的位置,即使我在完全没有 GPS 信号的建筑物内。

澄清一下:我对我的应用程序检索到的最后一个地理位置不感兴趣,因为下次我将启动它时,该地理位置可能无关紧要。

问题是:我们如何使用 HTML5/Phonegap 实现这一点?似乎navigator.geolocation 只知道检索当前位置,即使maximumAge 设置为Infinity (这意味着,最后缓存位置的年龄无关,所以任何命中都可以(或者,应该是! ))

【问题讨论】:

    标签: jquery android iphone html geolocation


    【解决方案1】:

    ANDROID 解决方案(iPhone 解决方案如下):

    这很整洁:

    我使用了 Android 的原生 LocationManager,它提供了一个 getLastKnownLocation 函数 - 名字就说明了一切

    这是相关代码

    1) 将以下 java 类添加到您的应用程序中

    package your.package.app.app;
    
    import org.apache.cordova.DroidGap;
    
    import android.content.Context;
    import android.location.*;
    import android.os.Bundle;
    import android.webkit.WebView;
    
    public class GetNativeLocation implements LocationListener {
        private WebView mAppView;
        private DroidGap mGap;
        private Location mostRecentLocation;
    
        public GetNativeLocation(DroidGap gap, WebView view) {
            mAppView = view;
            mGap = gap;
        }
    
        public void onLocationChanged(Location location) {
            // TODO Auto-generated method stub
            getLocation();
        }
    
        public void getLocation() {
            LocationManager lm = 
                            (LocationManager)mGap.
                                            getSystemService(Context.LOCATION_SERVICE);
            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            String provider = lm.getBestProvider(criteria, true);
    
            lm.requestLocationUpdates(provider, 1000, 500, this);
            mostRecentLocation = lm
                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
        }
    
        public void doInit(){
            getLocation();
        }
    
        public double getLat(){ return mostRecentLocation.getLatitude();}
        public double getLong() { return mostRecentLocation.getLongitude(); }
        public void onProviderDisabled(String arg0) {
            // TODO Auto-generated method stub  
        }
    
        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub  
        }
    
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO Auto-generated method stub
        }
    }
    

    2) 确保您的主类如下所示:

    public class App extends DroidGap {
    
        // Hold a private member of the class that calls LocationManager
        private GetNativeLocation gLocation;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // This line is important, as System Services are not available
            // prior to initialization
            super.init();
    
            gLocation = new GetNativeLocation(this, appView);
    
            // Add the interface so we can invoke the java functions from our .js 
            appView.addJavascriptInterface(gLocation, "NativeLocation");
    
            try {
                super.loadUrl("file:///android_asset/www/index.html");
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
    
        @Override
        public void onDestroy() {
            // TODO Auto-generated method stub
            super.onDestroy();
        }
    
        @Override
        protected void onStop() {
            // TODO Auto-generated method stub
            super.onStop();
        }
    }
    

    3) 在您的 JS 代码上,只需使用以下命令调用本机 java:

    window.NativeLocation.doInit();
    alert(window.NativeLocation.getLat());
    alert(window.NativeLocation.getLong());
    

    这就是所有人! :-)

    编辑: iPhone 解决方案:

    我编写了一个小型 Phonegap 插件,它创建了一个自定义类的接口,该类使用 iOS 的原生 CLLocationManager

    1) Phonegap 插件 (JS)

    var NativeLocation = {
        doInit: function(types, success, fail) {
            return Cordova.exec(success, fail, "NativeLocation", "doInit", types);
        },
    
        getLongitude: function(types, success, fail){
            return Cordova.exec(success, fail, "NativeLocation", "getLongitude", types);
        },
    
        getLatitude: function(types, success, fail){
            return Cordova.exec(success, fail, "NativeLocation", "getLatitude", types);
        }
    }
    

    2) 使我们能够调用'CCLocationManager's 函数的objective-c 类 *NativeLocation.h*

    #import <Foundation/Foundation.h>
    #import <Cordova/CDVPlugin.h>
    #import <CoreLocation/CoreLocation.h>
    
    @protocol NativeLocationDelegate
    @required
    - (void)locationUpdate:(CLLocation *)location;
    - (void)locationError:(NSError *)error;
    
    @end
    
    @interface NativeLocation : CDVPlugin <CLLocationManagerDelegate> {
        id delegate;
        NSString* callbackID;
        CLLocationManager *lm;
        Boolean bEnabled;
        double nLat;
        double nLon;
    }
    
    @property (nonatomic, copy) NSString* callbackID;
    @property (nonatomic, retain) CLLocationManager *lm;
    @property (nonatomic, readonly) Boolean bEnabled;
    @property (nonatomic, assign) id delegate;
    
    - (void) doInit:(NSMutableArray*)arguments
                                     withDict:(NSMutableDictionary*)options;
    - (void) getLatitude:(NSMutableArray*)arguments 
                                     withDict:(NSMutableDictionary *)options;
    - (void) getLongitude:(NSMutableArray*)arguments 
                                     withDict:(NSMutableDictionary *)options;
    
    @end
    

    NativeLocation.m

    #import "NativeLocation.h"
    
    @implementation NativeLocation
    
    @synthesize callbackID;
    @synthesize lm;
    @synthesize bEnabled;
    @synthesize delegate;
    
    - (void)doInit:(NSMutableArray *)arguments 
                                     withDict:(NSMutableDictionary *)options{
        if (self != nil){
            self.lm = [[[CLLocationManager alloc] init] autorelease];
            self.lm.delegate = self;
            if (self.lm.locationServicesEnabled == NO)
                bEnabled = FALSE;
            else bEnabled = TRUE;
        }
    
        nLat = 0.0;
        nLon = 0.0;
    
        if (bEnabled == TRUE)
            [self.lm startUpdatingLocation];
    
        CDVPluginResult* pluginResult = [CDVPluginResult 
                                        resultWithStatus:CDVCommandStatus_OK 
                                        messageAsString[@"OK"
                                        stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    
        if (bEnabled == TRUE){
            [self writeJavascript: [pluginResult 
                                   toSuccessCallbackString:self.callbackID]];
        } else {
            [self writeJavascript: [pluginResult 
                                   toErrorCallbackString:self.callbackID]];
        }
    }
    
    - (void)locationManager:(CLLocationManager *)manager 
                            didUpdateToLocation:(CLLocation *)newLocation 
                            fromLocation:(CLLocation *)oldLocation {
        if ([self.delegate conformsToProtocol:@protocol(NativeLocationDelegate)])
            [self.delegate locationUpdate:newLocation ];
    }
    
    - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
        if ([self.delegate conformsToProtocol:@protocol(NativeLocationDelegate)])
            [self.delegate locationError:error];
    }
    
    - (void)dealloc {
        [self.lm release];
        [super dealloc];
    }
    
    - (void)locationUpdate:(CLLocation *)location {
        CLLocationCoordinate2D cCoord = [location coordinate];
        nLat = cCoord.latitude;
        nLon = cCoord.longitude;
    
    }
    
    - (void)getLatitude:(NSMutableArray *)arguments 
                                          withDict:(NSMutableDictionary *)options{
    
        self.callbackID = [arguments pop];
    
        nLat = lm.location.coordinate.latitude;
        nLon = lm.location.coordinate.longitude;
    
        CDVPluginResult* pluginResult = [CDVPluginResult 
                                        resultWithStatus:CDVCommandStatus_OK 
                                        messageAsDouble:nLat];
    
        [self writeJavascript: [pluginResult toSuccessCallbackString:self.callbackID]];
    
    }
    - (void)getLongitude:(NSMutableArray *)arguments 
                                           withDict:(NSMutableDictionary *)options{
    
        self.callbackID = [arguments pop];
    
        nLat = lm.location.coordinate.latitude;
        nLon = lm.location.coordinate.longitude;
    
        CDVPluginResult* pluginResult = [CDVPluginResult 
                         resultWithStatus:CDVCommandStatus_OK messageAsDouble:nLon];
    
        [self writeJavascript: [pluginResult toSuccessCallbackString:self.callbackID]];
    
    }
    
    @end
    

    3) 最后,从主 .js 调用所有内容

    function getLongitudeSuccess(result){
        gLongitude = result;
    }
    
    function getLatitudeSuccess(result){
        gLatitude = result;
    }
    
    function runGPSTimer(){
        var sTmp = "gps";
    
        theTime = setTimeout('runGPSTimer()', 1000);
    
        NativeLocation.getLongitude(
                                    ["getLongitude"],
                                    getLongitudeSuccess,
                                    function(error){ alert("error: " + error); }
                                    );
    
        NativeLocation.getLatitude(
                                   ["getLatitude"],
                                   getLatitudeSuccess,
                                   function(error){ alert("error: " + error); }
                                   );
    

    【讨论】:

    • 请记住,此解决方案仅适用于 android,正如我之前所说 - 您必须为每种设备类型本地找到解决方案。祝你好运
    【解决方案2】:

    在我的 PhoneGap/Sencha Touch 2 应用程序中,我创建了函数

    function getLastKnownLocation(){
        if(typeof localStorage.lastKnownPosition == "undefined"){
            localStorage.lastKnownPosition = JSON.stringify(null);
        }
    
        navigator.geolocation.getCurrentPosition(
            function(position){
                localStorage.lastKnownPosition = JSON.stringify(position);
            }
        );
    
        return JSON.parse(localStorage.lastKnownPosition);
    }
    

    所以每次我调用 getLastKnownLocation() 时,我都会立即得到结果。就我的目的而言,这是一个很好的解决方法。

    【讨论】:

      【解决方案3】:

      我建议在您的getGeo_Success 函数调用setLocation([the_location]) 中将其存储在localStorage
      您可以假设每个使用phoneGap 的设备都已经实现了localStorage。
      这样,您总是在那里有有效的位置。然后只要你需要就弹出它。

      function getLocation() {
        return JSON.parse(localStorage.getItem('location'));
      }
      function setLocation(location) {
        localStorage.setItem('vibesList', JSON.stringify(vibes));
      }
      

      编辑:如果你想检索设备知道的最新位置(不是应用程序),你必须通过background从设备中提取当前数据的过程。这是有问题的方法,因为:

      1. 并非所有设备都允许这样做。
      2. 您必须编写自己的本地自定义 plugin 才能连接 phonegap。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-22
        • 1970-01-01
        • 2013-12-13
        • 2014-10-18
        • 2015-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多