How to expand the shared location URL from Google

2020-04-07 04:25发布

问题:

I am trying to get the location from google map shared location link so I am using Google Shorten URL API to expand the URL but when I shared URL from Google Map application from the android device it gives me https://maps.app.goo.gl/eEhh3 this kind of URL. It does not give me actual expanded URL to provide Location information.

how to expand this:

https://maps.app.goo.gl/eEhh3

In this link:

https://www.google.com/maps/place/Siddique+Trade+Center/@31.5313297,74.3504459,17z/data=!3m1!4b1!4m5!3m4!1s0x391904e4af9b1e35:0xee6f3c848c9e5341!8m2!3d31.5313297!4d74.3526346

Here is the API URL which I am using to expand it.

"https://www.googleapis.com/urlshortener/v1/url?shortUrl=https://maps.app.goo.gl/eEhh3&key=(API_KEY)"

But instead of giving me the above location information URL it returns me this Long URL.

https://maps.app.goo.gl/?link=https://www.google.com/maps/place//data%3D!4m2!3m1!1s0x391904e4af9b1e35:0xee6f3c848c9e5341?utm_source%3Dmstt_1&apn=com.google.android.apps.maps&ibi=com.google.Maps&ius=comgooglemapsurl&isi=585027354

Please help me how can I get above-mentioned Location Info URL by Google API to get Location (Lat, Lng) through Google Map shared location Url from any device (IOS, WebAPP, Specifically Android).

回答1:

Seems now (in 2019) there is no separate API or service for expanding shared location URL from Google Maps, but you can use workaround based on that trick: Google server can do it via Google Maps web interface.

TLDR;

You don't need expand API. For example, if

https://maps.app.goo.gl/eEhh3

URL typed in the web browser on PC (e.g. FireFox) than that URL was expanded and the marker was shown. And during that you can see in address field "partially expanded" URL like:

https://www.google.com/maps/place//data=!4m2!3m1!1s0x391904e4af9b1e35:0xee6f3c848c9e5341?utm_source=mstt_1

which in 1-2 sec changed (redirected to) by "full expanded" URL with lat/lng coordinates like:

https://www.google.com/maps/place/Siddique+Trade+Center/@31.5313297,74.3504459,17z/data=!3m1!4b1!4m5!3m4!1s0x391904e4af9b1e35:0xee6f3c848c9e5341!8m2!3d31.5313297!4d74.3526346.

So you can use WebView to do the same and get "full expanded" from it (e.g. in public void onPageFinished(WebView view, String url) of WebViewClient). NB: it's necessary to skip first "partially expanded" URL.

The other issue: WebView converts shortened URL like https://maps.app.goo.gl/eEhh3 into Intent for Google Maps Application and "partially expanded" URL https://www.google.com/maps/place//data=!4m2!3m1!1s0x391904e4af9b1e35:0xee6f3c848c9e5341?utm_source=mstt_1 never be loaded. Actually it's enough if you need just show marker. But if you need coordinates this issue can be solved if you open shortened URL https://maps.app.goo.gl/eEhh3 by HttpUrlConnection and get redirected "partially expanded" URL via HttpUrlConnection.getURL() or via Location Header field after connection opened and HttpUrlConnection.getInputStream() called. Actually, if you load all response from HttpUrlConnection input stream as String - you can find desired lat/lng coordinates within it by https://www.google.com/maps/preview/place tag. Something like:

... [[[1,42]\n]\n,0,null,0,47]\n]\n,null,\"Suit 706 Siddiq Trade Center, Main Blvd Gulberg, Block H Gulberg III, Lahore, Punjab, Pakistan\",null,null,\"https://www.google.com/maps/preview/place/Siddique+Trade+Center,+Suit+706+Siddiq+Trade+Center,+Main+Blvd+Gulberg,+Block+H+Gulberg+III,+Lahore,+Punjab,+Pakistan/@31.5313297,74.3526346,3401a,13.1y/data\\u003d!4m2!3m1!1s0x391904e4af9b1e35:0xee6f3c848c9e5341\",1,null,null,null,null,null, ... for your shortened URL opened via HttpUrlConnection. IMHO better (but slightly slower) way is to pass "partially expanded" URL received from HttpUrlConnection.getURL() into WebView and get "full expanded" URL from its address line. So, with full source code:

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mGoogleMap;
    private MapFragment mMapFragment;
    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // configure WebView
        System.setProperty("http.agent", "");   // reset default User-Agent
        mWebView = (WebView) findViewById(R.id.web_view);
        mWebView.setVisibility(View.GONE);
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                // skip non-"ful expanded" urls
                if (isUrlFullExpanded(url)) {
                    // extract lat/lng coordinates from "full expanded" URL String
                    LatLng latLng = getLatLngFromExpandedUrl(url);
                    // just show marker with extracted coordinates for test
                    onLatLngReceived(latLng);
                }
            }
        });
        mWebView.getSettings().setJavaScriptEnabled(true);

        mMapFragment = (MapFragment) getFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mMapFragment.getMapAsync(this);

        // start get LatLng from URL coordinates task    
        new GetLocationURL().execute(new String[] {"https://maps.app.goo.gl/eEhh3"});
    }


    private LatLng getLatLngFromExpandedUrl(String url) {
        final String beginMarker = "/@";
        final String endMarker = "/";
        final int ixCoordsStart = url.indexOf(beginMarker) + beginMarker.length();
        final int ixCoordsEnd = url.indexOf(endMarker, ixCoordsStart);
        String coordinatesString = url.substring(ixCoordsStart, ixCoordsEnd);

        LatLng latLng = null;
        if (!TextUtils.isEmpty(coordinatesString)) {
            String[] coords = coordinatesString.split(",");
            if (coords.length >= 2) {
                latLng = new LatLng(Float.parseFloat(coords[0]), Float.parseFloat(coords[1]));
            }
        }
        return latLng;
    }


    private boolean isUrlFullExpanded(String url) {
        return url.indexOf("place/") > -1 && url.indexOf("place//") == -1 && url.indexOf("/@") > -1;
    }


    private void onLatLngReceived(LatLng latLng) {
        if (mGoogleMap != null && latLng != null) {
            mGoogleMap.addMarker(new MarkerOptions().position(latLng));
            mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16));
        }
    }


    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
    }

    private class GetLocationURL extends AsyncTask<String, Void, String> {

        protected void onPreExecute() {
            super.onPreExecute();
        }

        protected String doInBackground(String... params) {

        String locationUrl = null;
        HttpURLConnection connection = null;
        BufferedReader reader = null;

        try {
            URL url = new URL(params[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();

            // you can analyze response code
            //int responseCode = connection.getResponseCode();

            InputStream stream = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(stream));
            StringBuilder responseStringBuilder = new StringBuilder();

            String line = "";
            while ((line = reader.readLine()) != null) {
                responseStringBuilder.append(line);
            }

            // use commented code below if you want to get coordinates directly from HttpURLConnection response
            /*
            LatLng latLng = null;
            String responseString = responseStringBuilder.toString();
            String pattern = "\\\"https://www.google.com/maps/preview/place";
            int ixPlaceStart = responseString.indexOf(pattern);

            if (ixPlaceStart > -1) {
                int ixCoordsStart = responseString.indexOf("@", ixPlaceStart) + 1;
                int ixCoordsEnd = responseString.indexOf("/", ixCoordsStart);
                String coordinatesString = responseString.substring(ixCoordsStart, ixCoordsEnd);
                String[] coords = coordinatesString.split(",");
                // latLng - coordinates from URL
                latLng = new LatLng(Float.parseFloat(coords[0]), Float.parseFloat(coords[1]));
            }
            */

            locationUrl = connection.getURL().toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return locationUrl;
    }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            // pass redirected "partially expandeded" URL to WebView
            mWebView.loadUrl(result);
        }
    }
}

and activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="<YOUR_PACKAGE>.MainActivity">

    <fragment
        android:id="@+id/map_fragment"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

you can get something like this:

NB! Described behavior can be changed by Google at any time.