Writing in the front

A recent business requirement required that after entering the page, the user’s location be retrieved and relevant content be displayed based on that location.

Sounds like a very simple requirement, but.. If your company has a LBS service and doesn’t think about adaptation, it’s really, really easy. Import an SDK or access a background interface to get the corresponding location. Of course, there are only a few companies with complete LBS service links in China.

The other is adaptation. The adaptation of geographical location services is not adaptation of models, but adaptation of platforms. The services provided by different platforms are also inconsistent.

lbs

Let’s talk about LBS first, not so much useless, location based services, from the name you should know what it is.

Most mature Internet platforms more or less use LBS to recommend or search users based on their current geographic location.

This is just to show that LBS is very common and is a very important abbreviation to know.

location

The environment

First of all, let’s talk about the platform our business needs to adapt to:

  1. In the station, that is, inside the app of the team;
  2. Wechat, the largest off-site sharing platform;
  3. Other mobile terminal off-site platforms, including but not limited to QQ, Weibo and various browsers;
  4. Some users may even open wechat on the computer side.

Harsh environment, isn’t it? If your team has their own app and wants their content to be shared and viewed off-site, you should probably consider all four of these.

If you do is micro channel small program, then congratulations to you, basically do not need to see the following, because micro channel to small program development environment is very good, do not need to consider so many things.

methods

Mobile terminal GPS positioning

The method of mobile TERMINAL GPS positioning is limited to your own app. As a front-end developer, you generally do not need to know how Native gives you various Jsbridges. But it’s good to know a little about it.

Speaking of native and Web communication, it has to be said that JSBridge, through which Native provides all kinds of necessary methods but not available on the Web, such as the use of native positioning, microphone, camera and other devices.

function setupWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
    if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
    window.WVJBCallbacks = [callback];
    var WVJBIframe = document.createElement('iframe');
    WVJBIframe.style.display = 'none';
    WVJBIframe.src = 'https://__bridge_loaded__';
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
setupWebViewJavascriptBridge(function(bridge) {
    /* Initialize your app here */
    var button = document.querySelector(".JSToNativeButton");
    button.addEventListener('click'.function(event) {
        bridge.callHandler('JsToNative'."This is a message from javascript to native");
    })
    bridge.registerHandler('NativeToJs'.function(data, responseCallback) {
        alert(data);
    })
    // bridge.callHandler('ObjC Echo', {'key':'value'}, function responseCallback(responseData) {
    //     console.log("JS received response:", responseData)
    // })
})
Copy the code

This is a very simple Web and native example, above is the Web side of the code. As you can see, the method of communication is the event listening mechanism we use most often. The above code looks a little convoluted, but it should make sense without much explanation. Because it seems a little off topic. Let’s just say it off topic Orz. The following is a bit of OC code snippet.

[self.bridge registerHandler:@"JsToNative" handler:^(id data, WVJBResponseCallback responseCallback) {
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"message from JS" message:data preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"close" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    [alertController addAction:actionCancel];
    [self presentViewController:alertController animated:YES completion:nil];
}];
Copy the code

In short, JSBridge can implement communication between the two ends. Native can register an object above the window, which provides methods for web registration events (bridge. RegisterHandler in the code above). Enable native notification to the Web. You can register events in Native, and then you can call the event function in the Web, passing in parameters, so that the Web can call native functions.

It’s a long way off, but it’s a long way off because there’s really nothing to be said for this solution. Native gives you a protocol, and then you call that protocol, pass in a function and wait for a callback. Basically there is no great difficulty and workload for our front end.

What? Your Native does not provide this protocol? The next iteration fills them up.

Is that a good idea?

Of course, very good. Accurate positioning, friendly hints, except pop-up permissions (of course, this is also a must), basically the best solution within the app. Of course, if you have a lot of location data, and you can make sure it’s available in real time, forget it. Even if there is an interface, it is up to your interaction and planning to determine whether silent positioning will cause user aversion.

This small demo has a project on my Github, wow, just found that I wrote a paper for half a year, Github has not updated for a long time.

H5 positioning

The new standards give us a lot of opportunities to speak the same language. I have to say that the compatibility of H5 positioning is good. At present, the mobile compatibility of our team supports Android 4.4.2 and above, and all phones above this version basically support the function of H5 positioning. Just when I was ready to use this as the first solution, I found a problem that could drive the interaction crazy.

First of all, H5 positioning will require the location permission of the third party platform, that is, app. Secondly, H5 positioning will pop up a pop-up window of the location permission of WebView.

If either of these two permissions is cancelled, then H5 location can only be located by IP.

The most important thing is H5 positioning. The webView’s pop-up will show: www.xxx.com wants to get your location. This can be very confusing to users, who may not know your domain name, but only what your software is called.

In addition to these two issues, H5 positioning is a very good choice both for compatibility and for uniformity of front-end positioning.

const noop = () => {};
getH5Location(options = {}) {
    const cb = options.cb || noop;
    const errCb = options.errCb || noop;
    let isLocation = false;
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(
            res => {
                isLocation = true;
                cb(res.coords.longitude, res.coords.latitude);
            },
            () => {
                isLocation = true; errCb(); }); } // position the bottom of the pocketsetTimeout(() => {
        if (!isLocation) {
            errCb();
        }
    }, 5000);
},
Copy the code

This is a simple H5 positioning package, in case some devices do not support H5 positioning, added a back-pocket method. The delay triggered by the bottom pocket can be set as required.


Note here that the H5 located a small pit that took me a long time to climb. As we all know, H5 positioning in newer browsers requires HTTPS for positioning. When you switch to HTTPS, you will find that all HTTP resources are blocked by H5 positioning. However, if you comment out the code that H5 locates, you will see that the HTTP resource will only display a warning, but it will display normally.

If your static resource hashttpsVersion of the word, or recommend you use//via.placeholder.com/333x333This protocol – free mode is introduced to automatically switch resource protocols to prevent resource congestion.


WeChat API

In wechat platform, because of all kinds of small problems of H5 positioning, although it does not affect the use, but the effect is always so bad. If your team can apply for the wechat SDK, then it is great.

Simple call, the premise is that you have introduced wechat JS-SDK, this is not a very difficult thing. The document sent by wechat has been very detailed, so I will not repeat it here.

wx.getLocation({
    type: 'wgs84'// The default GPS coordinates are wGS84. If you want to return the Mars coordinates directly for openLocation, you can pass them in'gcj02'
    success: function(res) { var latitude = res.latitude; // Latitude, floating point, 90 ~ -90 var longitude = res.longitude; // The longitude is a floating point number ranging from 180 to -180. var speed = res.speed; Var accuracy = res.accuracy; // position precision}});Copy the code

In wechat platform, using wechat interface is undoubtedly the best choice. It’s perfect, it’s simple, it’s been used by countless people, it’s NICE, and the wechat platform is the platform you have to adapt, because the wechat platform is the first landing point for most of your landing pages.

How to use wechat public platform documents have been written in great detail.

Third-party SDK (Baidu Map, Autonavi, etc.)

This is the most unreliable method, I spent a whole day, Baidu Map, Autonavi Map, Tencent map introduced, and tried. He has a desperate style.

Later, I thought about this problem fundamentally. What are they based on. Don’t they do it via IP when they don’t have GPS access?

Sure enough, after several attempts, some of these third-party SDKS will use H5 for location, because api.map.xxx.com popped up trying to get your location, so why don’t I use H5 for location? Background fathers have provided an IP location interface, if or through the third-party SDK IP location, it is not a waste of background fathers’ hard work.

Third party maps are great, but their location services are not always good. If you only need location, then don’t consider this method because the main function of the third party map SDK is to get visualized maps.

It took me half a day to figure it out after the test.

If you want a visual map service, choose a third party map SDK, if only for positioning, then other methods are better than this method.

IP position

Depending on the interface given by the back-end dad, you can get the location information stored in the back-end database directly through the interface. Or by the user’s IP address, to obtain the geographical location.

It looks beautiful. If you’re looking for accuracy, skip this method. IP location is very poor on 4G networks.

On a 4G network, IP location is usually based on the carrier’s home or base station. If you live on Beijing’s Fourth ring Road, chances are it will lead you to Shijiazhuang.

But there is no way, in the case of access, IP positioning can be used as a bottom of the scheme, or more realistic.

The ultimate solution

Haha, in fact, the so-called ultimate solution is to adapt the above multiple solutions.

  • First of all, the app internally allows the client developers to build a JSBridge for you to properly call native location methods.

  • Secondly, as the first sharing platform wechat, of course, special care should be taken of wechat through the JS-SDK of wechat to position.

  • Again, the same can be said for all other mobile and client platforms. All use H5 positioning, violence and easy to use.

  • Finally, after any location fails, obediently IP location.

Of course, the above complex adaptation is designed to give you a better user experience. If you find it troublesome or certain conditions do not allow (client scheduling expired? Does not exist). Can be based on the advantages and disadvantages of the above, for replacement, suitable for their own plan is the best plan.

Finally, don’t forget to encapsulate your location function to make it easier for others to reuse. You don’t want to come back to this dry article the next time you need positioning

export const getLocation = (options = {
    cb: () => {},
    errCb: () => {},
}) => {
    const isInApp = Utils.getEnv().isInApp();
    const isInWechat = Utils.isInWechat();
    if(isInApp) {// Station positioningreturn this.getAppLocation(options);
    }
    if(isInWechat) {// wechatreturnthis.getWechatLocation(options); } // H5 positioningreturn this.getH5Location(options);
},
Copy the code