You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级VS2017后System.Device.Location.Portable与monoandroid81不兼容问题

解决System.Device.Location.Portable与MonoAndroid81不兼容的问题

这个问题我之前帮不少开发者解决过,本质是你用的System.Device.Location.Portable是个比较老旧的移植包,完全没适配新版Xamarin.Android对应的Android 8.1(也就是报错里的monoandroid81),所以NuGet会直接抛出兼容性错误。下面给你一套完整的替代方案,比继续用旧包靠谱多了:

第一步:卸载旧的NuGet包

先把出问题的System.Device.Location.Portable从项目里彻底移除:

  • 在VS的解决方案资源管理器里,右键你的Xamarin.Forms项目 → 管理NuGet程序包
  • 切换到“已安装”标签,找到System.Device.Location.Portable,点击卸载,确认移除所有相关引用

第二步:替换为官方维护的位置API

新版Xamarin生态已经有官方的跨平台位置解决方案了,推荐用下面两个选项之一:

选项1:使用Xamarin.Essentials(最推荐)

这是微软官方推出的跨平台工具包,专门封装了位置、传感器等常用原生功能,比旧第三方包稳定得多:

  1. 安装Xamarin.Essentials NuGet包:在NuGet管理器里搜索Xamarin.Essentials,安装适配你当前Xamarin版本的稳定版
  2. 用Geolocation类获取位置的示例代码:
using Xamarin.Essentials;

public async Task<Location> GetCurrentLocation()
{
    try
    {
        // 配置位置请求的精度和超时时间
        var locationRequest = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
        var currentLocation = await Geolocation.GetLocationAsync(locationRequest);

        if (currentLocation != null)
        {
            Console.WriteLine($"纬度: {currentLocation.Latitude}, 经度: {currentLocation.Longitude}, 海拔: {currentLocation.Altitude}");
        }
        return currentLocation;
    }
    catch (FeatureNotSupportedException)
    {
        // 处理设备不支持位置服务的情况
    }
    catch (FeatureNotEnabledException)
    {
        // 提示用户开启位置服务
    }
    catch (PermissionException)
    {
        // 提示用户授予位置权限
    }
    catch (Exception ex)
    {
        // 处理其他未知错误
    }
    return null;
}

选项2:用DependencyService调用原生API(适合自定义需求多的场景)

如果你需要更定制化的位置逻辑,可以用Xamarin.Forms的DependencyService来分别调用Android和iOS的原生位置API:

  1. 先在共享项目里定义一个位置服务接口:
public interface ILocationService
{
    Task<(double Latitude, double Longitude)> GetCurrentLocation();
}
  1. 在Android项目里实现这个接口(记得处理权限):
[assembly: Dependency(typeof(AndroidLocationService))]
namespace YourAppName.Droid
{
    public class AndroidLocationService : ILocationService
    {
        public async Task<(double Latitude, double Longitude)> GetCurrentLocation()
        {
            // 先检查动态权限(Android 6.0+需要)
            if (await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>() != PermissionStatus.Granted)
            {
                var status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
                if (status != PermissionStatus.Granted)
                {
                    throw new PermissionException("位置权限未授予");
                }
            }

            var locationManager = (LocationManager)Android.App.Application.Context.GetSystemService(Context.LocationService);
            var lastKnownLocation = await locationManager.GetLastKnownLocationAsync(LocationManager.GpsProvider);
            
            if (lastKnownLocation == null)
            {
                // 可以添加逻辑等待位置更新,这里简化处理
                throw new Exception("无法获取当前位置");
            }

            return (lastKnownLocation.Latitude, lastKnownLocation.Longitude);
        }
    }
}
  1. 在iOS项目里实现对应的原生逻辑(同样要配置权限描述)

第三步:配置必要的权限

不管用哪个方案,都得给平台配置位置权限:

  • Android:在AndroidManifest.xml里添加权限声明:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  • iOS:在Info.plist里添加权限描述(告诉用户为什么需要位置权限):
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要访问您的位置来提供相关服务</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>需要始终访问您的位置来提供相关服务</string>

为什么旧包会报错?

System.Device.Location.Portable是很早的一个第三方移植包,只适配了早期的Xamarin版本和低版本Android API。当你升级到Xamarin.Android 8.3.0.18后,项目默认的目标框架是Android 8.1(对应monoandroid81),这个旧包完全没有针对这个API级别做适配,所以NuGet的兼容性检测直接就报错了,根本没法安装。

内容的提问来源于stack exchange,提问作者Shambhavi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:49:40