如何扩展谷歌地图共享位置URL?

5
我正在尝试从谷歌地图共享位置链接中获取位置,因此我正在使用Google缩短URL API来扩展URL,但是当我从Android设备的Google地图应用程序共享URL时,它会给我这种URL:https://maps.app.goo.gl/eEhh3。 它没有给我实际扩展的URL以提供位置信息。
如何扩展这个链接: https://maps.app.goo.gl/eEhh3 在这个链接中:
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

这里是我用来扩展的API URL

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

但是,它没有返回上述位置信息URL,而是返回了这个长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

请帮我通过Google API获取上述位置信息URL,以便从任何设备(IOS、WebAPP、特别是Android)通过Google地图共享位置URL获取位置(纬度,经度)


这段代码还能用吗?我研究了WebView的行为,Google已经通过参数添加了重定向到https://consent.google.com/mcontinue=https://www.google.com/maps/place/... - Reijo Korhonen
@ReijoKorhonen 不知道兄弟,但它是最通用的,所以我认为应该可以工作。 - Tanveer Munir
1个回答

5

看起来现在(2019年)谷歌地图没有单独的API或服务用于扩展共享位置URL,但您可以使用基于以下技巧的解决方法:通过谷歌地图Web界面,谷歌服务器可以执行此操作。

简而言之:

您不需要扩展API。例如,如果

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

在PC上(例如FireFox)输入网页浏览器中的URL,然后该URL会被展开并显示标记。在此过程中,您可以在地址栏中看到“部分展开”的URL:

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

在1-2秒内,它会被“完全展开”的URL重定向,并带有类似于lat/lng坐标的信息:

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.

因此,您可以使用WebView执行相同操作,并从中获取“完全展开”(例如,在WebViewClientpublic void onPageFinished(WebView view, String url)中)。注意:需要跳过第一个“部分展开”的URL。

另一个问题是: WebView 会将类似 https://maps.app.goo.gl/eEhh3 的缩短 URL 转换为 Google Maps 应用程序的 Intent,并且 "部分展开" 的 URL https://www.google.com/maps/place//data=!4m2!3m1!1s0x391904e4af9b1e35:0xee6f3c848c9e5341?utm_source=mstt_1 永远不会被加载。实际上,如果你只需要显示标记,这已经足够了。但如果你需要坐标,则可以通过 HttpUrlConnection 打开缩短的 URL https://maps.app.goo.gl/eEhh3 并在打开连接后通过 HttpUrlConnection.getURL()Location Header 字段获取重定向的 "部分展开" URL,然后调用 HttpUrlConnection.getInputStream()。实际上,如果你将从 HttpUrlConnection 输入流中加载的所有响应作为 String 加载,你可以通过 https://www.google.com/maps/preview/place 标签在其中找到所需的纬度/经度坐标。例如:

... [[[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, ... 是您通过HttpUrlConnection打开的缩短URL。在我看来,更好的方法(但稍微慢一些)是将从{{link1:HttpUrlConnection.getURL()}}接收到的“部分展开”的URL传递到WebView中,并从其地址行中获取“完全展开”的URL。因此,附带完整源代码:

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

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>

你可以得到类似这样的东西:

Marker from expanded URL

注意!Google 可能随时更改所述行为。


谢谢,我会查看您的答案。 - Tanveer Munir
1
我收到的是这个URL https://play.google.com/store/apps/details?id=com.google.android.apps.maps&pcampaignid=fdl_short&url=https://www.google.com/maps/place//data%3D!4m2!3m1!1s0x15c3d01fb1137e59:0xe059579737b118db?utm_source%3Dmstt_1 而不是通过 'HttpUrlConnection' 获取位置URL,我认为谷歌方案已经改变了。 - Tanveer Munir
当我在webView中访问此URL时,它总是返回相同的URL。 - Tanveer Munir
@TanveerMunir 那个案例的短链接是什么? - Andrii Omelchenko
2
@TanveerMunir 请检查 WebViewhttp.agent (System.setProperty("http.agent", "");) 设置。在我的端上,您的URL转换为 https://www.google.com/maps/place/Jeddah+Saudi+Arabia/@21.4498898,38.9309561,10z/data=!3m1!4b1!4m5!3m4!1s0x15c3d01fb1137e59:0xe059579737b118db!8m2!3d21.485811!4d39.1925048 - Andrii Omelchenko
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接