Android上DependencyService的NullReferenceException

时间:2018-06-26 04:37:27

标签: xamarin.forms xamarin.android

我正在尝试获取有关Xamarin项目的电话服务信息。

当我致电var carrierHelper = DependencyService.Get<ICarrierHelper>();时,我得到一个System.NullReferenceException: Object reference is not set to an instance of an object.

ICarrierHelper.cs

using System;
namespace MyProject
{
    public interface ICarrierHelper
    {
        string GetPhoneCarrier();
    }
}

MyProject.Droid / Helpers / CarrierHelper.cs

using MyProject.Droid;
using Android.Content;
using Android.Telephony;
using Xamarin.Forms;

[assembly: Dependency(typeof(CarrierHelper))]
namespace MyProject.Droid
{
    public class CarrierHelper : ICarrierHelper
    {
        public string GetPhoneCarrier()
        {
            Console.WriteLine("****************************** MAIN ACTIVITY " + MainActivity.Current.ToString());

            TelephonyManager mgr = MainActivity.Current.GetSystemService(Context.TelephonyService) as TelephonyManager;

            Console.WriteLine("****************************** TELEPHONY MANAGER " + mgr.ToString());

            return mgr.NetworkOperatorName;

            //return mgr.SimOperatorName;
        }
    }
}

我在Droid CarrierHelper.cs中有一个断点,永远不会捕获。因此,我只能假设DependencyService根本找不到我的文件。

更新(添加更多信息和控制台日志。)

MyDevice.cs

using System;
using Plugin.DeviceInfo;
using Xamarin.Forms;

namespace MyProject
{
public class MyDevice
{
    private static MyDevice current;
    public static MyDevice Current
    {
        get
        {
            if (current == null)
                current = new MyDevice();

            return current;
        }
    }

    public string platform { get; set; }
    public string manufacturer { get; set; }
    public string model { get; set; }
    public string name { get; set; }
    public string os_version { get; set; }
    public string carrier { get; set; }
    public string app_version { get; set; }
    public string app_build { get; set; }

    public MyDevice()
    {
        switch (Device.RuntimePlatform)
        {
            case Device.iOS:
                platform = "iOS";
                break;
            case Device.Android:
                platform = "Android";
                break;
            default:
                platform = "UNKNOWN";
                break;
        }

        manufacturer = CrossDeviceInfo.Current.Manufacturer;
        model = CrossDeviceInfo.Current.Model;
        name = CrossDeviceInfo.Current.DeviceName;
        os_version = CrossDeviceInfo.Current.Version;
        app_version = CrossDeviceInfo.Current.AppVersion;
        app_build = CrossDeviceInfo.Current.AppBuild;

        var carrierHelper = DependencyService.Get<ICarrierHelper>();

        Console.WriteLine("----- CARRIER HELPER " + carrierHelper);

        carrier = DependencyService.Get<ICarrierHelper>().GetPhoneCarrier();

        Console.WriteLine("----- CARRIER: " + carrier);
    }
}
}

以下控制台日志打印:

  

-----运营商帮助MyProject.Droid.CarrierHelper

更新(添加堆栈跟踪和信息。)

这是堆栈跟踪:

  

在/MyProject/Helpers/CarrierHelper.cs:14中的MyProject.Droid.CarrierHelper.GetPhoneCarrier()[0x00001]     在/MyProject.Core/Models/MyDevice.cs:57中的MyProject.MyDevice..ctor()[0x000d2]     在/MyProject.Core/Models/MyDevice.cs中的MyProject.MyDevice.get_Current()[0x0000d]:15     在/MyProject.Core/Services/UserDataStore.cs:197

中的MyProject.UserDataStore + d__16.MoveNext()[0x00057]

UserDataStore.cs

public async Task UpdateLocation(double lat, double lng)
    {
        try
        {
            if (!CrossConnectivity.Current.IsConnected)
                throw new Exception("Not currently connected to the internet.");

            var model = new
            {
                access_token = $"{Settings.AuthToken}",
                latitude = lat,
                longitude = lng,
                device = MyDevice.Current,
                format = "json"
            };

            var json = JsonConvert.SerializeObject(model);

            var location_content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");

            var response = await client.PostAsync(users_url + location_url, location_content);

            if (!response.IsSuccessStatusCode)
                throw new Exception(response.StatusCode.ToString() + " " + response.ReasonPhrase);
        }
        catch (Exception e)
        {
            Console.WriteLine("ERROR: " + e.Message); // this is where the stack trace is generated

            await LocationDatabase.Connection.SaveLocationAsync(new Location(lat, lng));

            await AppEventDatabase.Connection.SaveEventAsync(new AppEvent("location", e.Message, lat, lng));
        }
    }

这是上面文件中的错误消息:

  

错误:对象引用未设置为对象的实例。

1 个答案:

答案 0 :(得分:0)

您遇到22分的情况。 GetPhoneCarrier()要求MyDevice.Current,这是通过MyDevice的延迟加载构造函数实现的。该构造函数解析ICarrierHelper并调用GetPhoneCarrier(),这需要MyDevice.Current ...

我假设该解决方案表明它已经尝试解决该问题,但尚未完成,因此它返回null。

我建议您在MyDevice构造函数中减少操作。避免解决该依赖关系,直到您真正需要它为止。这样,构造函数就可以完成操作,避免了catch 22的问题。

还请注意,延迟加载的方法不是线程安全的。考虑使用Lazy<T>,它很好地封装了双重检查的线程安全锁定。