【问题标题】:Unable to load Google Maps Properly in my Xamarin Cross-Platform App无法在我的 Xamarin 跨平台应用程序中正确加载 Google 地图
【发布时间】:2018-01-05 08:00:48
【问题描述】:

我有问题。我正在尝试在 Xamarin 跨平台应用程序上显示 Google 地图。

对于 Android,我的 API 密钥正确生成了以下代码:

MainActivity.cs:

using System;

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace PruebaMapas.Droid
{ 
[Activity(Label = "PruebaMapas", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(bundle);
        Xamarin.FormsMaps.Init(this, bundle);
        global::Xamarin.Forms.Forms.Init(this, bundle);
        LoadApplication(new App());
    }
}
}

然后,我的 AndroidManifest.xml 中有这些:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.PruebaMapas" android:installLocation="auto">
<uses-sdk android:minSdkVersion="13" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application android:label="PruebaMapas.Android">
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyD2bMPYdPUw_0Fd8-GkHle0_CiImTgtqX0" />
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
</application>
</manifest>

我已启用此权限:

然后,我创建一个名为“MapPage.xaml”的页面,代码如下:

MapPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="PruebaMapas.MapPage">
<ContentPage.Content>
    <StackLayout>
        <Label Text="Welcome to Xamarin.Forms!"
            VerticalOptions="CenterAndExpand" 
            HorizontalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage.Content>
</ContentPage>

MapPage.xaml.cs:

using System;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using System.Diagnostics;

namespace PruebaMapas
{
public partial class MapPage : ContentPage
{

    Map map;
    public MapPage()
    {
        map = new Map
        {
            IsShowingUser = true,
            HeightRequest = 100,
            WidthRequest = 960,
            VerticalOptions = LayoutOptions.FillAndExpand
        };
        // You can use MapSpan.FromCenterAndRadius   
        map.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37, -122), Distance.FromMiles(0.3)));
        // or create a new MapSpan object directly  
        //map.MoveToRegion(new MapSpan(new Position(0, 0), 360, 360));  
        // add the slider  
        var slider = new Slider(1, 18, 1);
        slider.ValueChanged += (sender, e) => {
            var zoomLevel = e.NewValue; // between 1 and 18  
            var latlongdegrees = 360 / (Math.Pow(2, zoomLevel));
            Debug.WriteLine(zoomLevel + " -> " + latlongdegrees);
            if (map.VisibleRegion != null) map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongdegrees, latlongdegrees));
        };
        // create map style buttons  
        var street = new Button
        {
            Text = "Street"
        };
        var hybrid = new Button
        {
            Text = "Hybrid"
        };
        var satellite = new Button
        {
            Text = "Satellite"
        };
        street.Clicked += HandleClicked;
        hybrid.Clicked += HandleClicked;
        satellite.Clicked += HandleClicked;
        var segments = new StackLayout
        {
            Spacing = 30,
            HorizontalOptions = LayoutOptions.CenterAndExpand,
            Orientation = StackOrientation.Horizontal,
            Children = {
                        street,
                        hybrid,
                        satellite
                    }
        };
        // put the page together  
        var stack = new StackLayout
        {
            Spacing = 0
        };
        stack.Children.Add(map);
        stack.Children.Add(slider);
        stack.Children.Add(segments);
        Content = stack;
        // for debugging output only  
        map.PropertyChanged += (sender, e) => {
            Debug.WriteLine(e.PropertyName + " just changed!");
            if (e.PropertyName == "VisibleRegion" && map.VisibleRegion != null) CalculateBoundingCoordinates(map.VisibleRegion);
        };
    }
    void HandleClicked(object sender, EventArgs e)
    {
        var b = sender as Button;
        switch (b.Text)
        {
            case "Street":
                map.MapType = MapType.Street;
                break;
            case "Hybrid":
                map.MapType = MapType.Hybrid;
                break;
            case "Satellite":
                map.MapType = MapType.Satellite;
                break;
        }
    }
    /// <summary>  
    /// In response to this forum question http://forums.xamarin.com/discussion/22493/maps-visibleregion-bounds  
    /// Useful if you need to send the bounds to a web service or otherwise calculate what  
    /// pins might need to be drawn inside the currently visible viewport.  
    /// </summary>  
    static void CalculateBoundingCoordinates(MapSpan region)
    {
        // WARNING: I haven't tested the correctness of this exhaustively!  
        var center = region.Center;
        var halfheightDegrees = region.LatitudeDegrees / 2;
        var halfwidthDegrees = region.LongitudeDegrees / 2;
        var left = center.Longitude - halfwidthDegrees;
        var right = center.Longitude + halfwidthDegrees;
        var top = center.Latitude + halfheightDegrees;
        var bottom = center.Latitude - halfheightDegrees;
        // Adjust for Internation Date Line (+/- 180 degrees longitude)  
        if (left < -180) left = 180 + (180 + left);
        if (right > 180) right = (right - 180) - 180;
        // I don't wrap around north or south; I don't think the map control allows this anyway  
        Debug.WriteLine("Bounding box:");
        Debug.WriteLine(" " + top);
        Debug.WriteLine(" " + left + " " + right);
        Debug.WriteLine(" " + bottom);
    }
}
}

最后,我运行应用程序时的屏幕截图:

输出窗口显示下一个:

[0:] Width just changed!
[0:] Height just changed!

01-05 08:50:33.704 D/Mono    ( 8860): Assembly Ref addref Xamarin.GooglePlayServices.Maps[0x9ebcb740] -> Xamarin.GooglePlayServices.Basement[0x9ebcb500]: 3
01-05 08:50:33.722 D/Mono    ( 8860): Assembly Ref addref Xamarin.Forms.Maps.Android[0x9ebcb140] -> System.Core[0x9ebcc160]: 7
01-05 08:50:33.730 D/Mono    ( 8860): DllImport searching in: '__Internal' ('(null)').
01-05 08:50:33.730 D/Mono    ( 8860): Searching for 'java_interop_jnienv_call_nonvirtual_float_method_a'.
01-05 08:50:33.730 D/Mono    ( 8860): Probing 'java_interop_jnienv_call_nonvirtual_float_method_a'.
01-05 08:50:33.730 D/Mono    ( 8860): Found as 'java_interop_jnienv_call_nonvirtual_float_method_a'.
01-05 08:50:33.736 D/Mono    ( 8860): Assembly Ref addref Mono.Android[0x9ebcb800] -> System.Xml[0x8af1bfc0]: 3
01-05 08:50:33.741 E/Google Maps Android API( 8860): Authorization failure.  Please see https://developers.google.com/maps/documentation/android-api/start for how to correctly set up the map.
01-05 08:50:33.741 E/Google Maps Android API( 8860): In the Google Developer Console (https://console.developers.google.com)
01-05 08:50:33.741 E/Google Maps Android API( 8860): Ensure that the "Google Maps Android API v2" is enabled.
01-05 08:50:33.741 E/Google Maps Android API( 8860): Ensure that the following Android Key exists:
01-05 08:50:33.741 E/Google Maps Android API( 8860):    API Key: AIzaSyD2bMPYdPUw_0Fd8-GkHle0_CiImTgtqX0
01-05 08:50:33.741 E/Google Maps Android API( 8860):    Android Application (<cert_fingerprint>;<package_name>): BF:45:E2:59:BF:E1:B0:77:66:E0:DC:13:9A:1F:E3:45:8D:F8:E1:41;com.companyname.PruebaMapas
01-05 08:50:33.756 D/        ( 8860): HostConnection::get() New Host Connection established 0xa5508b40, tid 8919
01-05 08:50:33.758 W/        ( 8860): Unrecognized GLES max version string in extensions: ANDROID_EMU_CHECKSUM_HELPER_v1 
01-05 08:50:33.758 W/        ( 8860): Process pipe failed
01-05 08:50:33.763 D/EGL_emulation( 8860): eglCreateContext: 0xa5506140: maj 1 min 0 rcv 1
01-05 08:50:33.767 D/        ( 8860): HostConnection::get() New Host Connection established 0x7ec86800, tid 8860
01-05 08:50:33.767 W/        ( 8860): Unrecognized GLES max version string in extensions: ANDROID_EMU_CHECKSUM_HELPER_v1 
01-05 08:50:33.816 D/EGL_emulation( 8860): eglMakeCurrent: 0xa5506140: ver 1 0 (tinfo 0x8acec820)
01-05 08:50:35.243 W/DynamiteModule( 8860): Local module descriptor class for com.google.android.gms.googlecertificates not found.
01-05 08:50:35.247 I/DynamiteModule( 8860): Considering local module com.google.android.gms.googlecertificates:0 and remote module com.google.android.gms.googlecertificates:0
01-05 08:50:35.247 E/GoogleCertificates( 8860): Failed to load com.google.android.gms.googlecertificates
01-05 08:50:35.247 E/GoogleCertificates( 8860): qq: No acceptable module found. Local version is 0 and remote version is 0.
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at com.google.android.gms.dynamite.DynamiteModule.a(:com.google.android.gms.DynamiteModulesB@11509470:11)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at in.a(:com.google.android.gms.DynamiteModulesB@11509470:12)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at in.a(:com.google.android.gms.DynamiteModulesB@11509470:31)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at in.b(:com.google.android.gms.DynamiteModulesB@11509470:30)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at iy.a(:com.google.android.gms.DynamiteModulesB@11509470:35)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at iy.a(:com.google.android.gms.DynamiteModulesB@11509470:20)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at com.google.maps.api.android.lib6.impl.ev.a(:com.google.android.gms.DynamiteModulesB@11509470:143)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at com.google.maps.api.android.lib6.impl.fb.run(:com.google.android.gms.DynamiteModulesB@11509470:28)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
01-05 08:50:35.247 E/GoogleCertificates( 8860):     at java.lang.Thread.run(Thread.java:761)
Thread finished: <Thread Pool> #4
Thread started: <Thread Pool> #8
El subproceso 0x4 terminó con código 0 (0x0).
Thread finished: <Thread Pool> #8
Thread started: <Thread Pool> #9
El subproceso 0x8 terminó con código 0 (0x0).

我在尝试查看 UWP 解决方案的结果时也遇到了问题,我有一个例外。我使用的代码在 MainPage.xaml.cs 中:

using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace PruebaMapas.UWP
{
public sealed partial class MainPage
{
    public MainPage()
    {
        this.InitializeComponent();
        Xamarin.FormsMaps.Init();
        LoadApplication(new PruebaMapas.App());
    }
}
}

我的错误就在这里:

        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }
        // Ensure the current window is active
        Window.Current.Activate();

#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
        UnhandledException += (sender, e) =>
        {
            if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
        };
#endif

为什么我看不到谷歌地图信息?任何人都可以帮助我吗?谢谢!

【问题讨论】:

  • 有什么异常?您是否尝试调试异常?
  • 我在 Android 应用上没有异常,它会加载谷歌地图但什么也没显示。
  • 引用上面的“我有一个例外”。现在你说,我没有例外....是哪一个?
  • 当我写“我有一个异常”时,我写在“关于 UWP 解决方案”之前,而不是在 Android 解决方案之前。所以,在 Android 应用程序上我没有例外。在 UWP 解决方案上,它在以下位置中断: if (rootFrame.Content == null) { // 当导航堆栈未恢复时,导航到第一页, // 通过将所需信息作为导航参数传递来配置新页面 // 参数rootFrame.Navigate(typeof(MainPage), e.Arguments); } Window.Current.Activate();
  • 我将错误行贴在问题上,以便看得更清楚

标签: c# android google-maps xaml xamarin


【解决方案1】:

如果您看到 Google 徽标但没有看到地图图块,这通常表明 Google Maps API 的授权出现问题。

你的输出也这么说:

01-05 08:50:33.741 E/Google Maps Android API (8860):授权失败。请参阅https://developers.google.com/maps/documentation/android-api/start 了解如何正确设置地图。

我在开发过程中经常看到的一个可能原因是在控制台或清单中设置 api 密钥时出错。如果应用程序随后部署到设备/模拟器,Android 会缓存错误的凭据。要解决这个问题,请删除应用程序,使用正确的密钥重建并重新部署。它现在应该可以按预期工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 2018-12-04
    相关资源
    最近更新 更多