在 Xamarin.Forms 中编写设备平台特定代码

Posted

技术标签:

【中文标题】在 Xamarin.Forms 中编写设备平台特定代码【英文标题】:Write device platform specific code in Xamarin.Forms 【发布时间】:2014-06-16 19:43:09 【问题描述】:

我有以下Xamarin.Forms.ContentPage 类结构

public class MyPage : ContentPage

    public MyPage()
    
        //do work to initialize MyPage 
    

    public void LogIn(object sender, EventArgs eventArgs)
    
        bool isAuthenticated = false;
        string accessToken = string.Empty;

        //do work to use authentication API to validate users

        if(isAuthenticated)
        
            //I would to write device specific code to write to the access token to the device
            //Example of saving the access token to ios device
            NSUserDefaults.StandardUserDefaults.SetString(accessToken, "AccessToken");

            //Example of saving the access token to android device
            var prefs = Application.Context.GetSharedPreferences("MySharedPrefs", FileCreationMode.Private);
            var prefsEditor = prefs.Edit();

            prefEditor.PutString("AccessToken", accessToken);
            prefEditor.Commit();
        
    

我想在 MyPage LogIn 方法中编写特定于平台的代码,以根据他们在哪个设备操作系统上使用我的应用程序来保存访问令牌。

当用户在他们的设备上使用我的应用程序时,我如何只运行设备特定的代码?

【问题讨论】:

【参考方案1】:

这是一个很容易通过依赖注入解决的场景。

在您的共享代码或 PCL 代码上具有所需方法的接口,例如:

public interface IUserPreferences 

    void SetString(string key, string value);
    string GetString(string key);

在该接口的 App 类上有一个属性:

public class App 

    public static IUserPreferences UserPreferences  get; private set; 

    public static void Init(IUserPreferences userPreferencesImpl) 
    
        App.UserPreferences = userPreferencesImpl;
    

    (...)

在您的目标项目上创建特定于平台的实现:

iOS:

public class iOSUserPreferences : IUserPreferences 

    public void SetString(string key, string value)
    
        NSUserDefaults.StandardUserDefaults.SetString(key, value);
    

    public string GetString(string key)
    
        (...)
    

安卓:

public class AndroidUserPreferences : IUserPreferences

    public void SetString(string key, string value)
    
        var prefs = Application.Context.GetSharedPreferences("MySharedPrefs", FileCreationMode.Private);
        var prefsEditor = prefs.Edit();

        prefEditor.PutString(key, value);
        prefEditor.Commit();
    

    public string GetString(string key)
    
        (...)
    

然后在每个特定于平台的项目上创建IUserPreferences 的实现,并使用App.Init(new iOSUserPrefernces())App.Init(new AndroidUserPrefernces()) 方法进行设置。

最后,您可以将代码更改为:

public class MyPage : ContentPage

    public MyPage()
    
        //do work to initialize MyPage 
    

    public void LogIn(object sender, EventArgs eventArgs)
    
        bool isAuthenticated = false;
        string accessToken = string.Empty;

        //do work to use authentication API to validate users

        if(isAuthenticated)
        
            App.UserPreferences.SetString("AccessToken", accessToken);
        
    

【讨论】:

App 类代码 sn-p 上,我在尝试编写代码时收到“方法必须有返回类型”。它的返回类型是否应该为void init 方法可能应该有一个void 返回类型。 这是一个非常好的解决方案,可以将代码组织到每个平台特定的项目中。谢谢。 感谢 Michael 和 valdetero 指出并修复它。很高兴这个答案适合您,我将这种方法用于我需要访问的几个不同平台特定的功能。也值得一看 DependencyService Stephane Delcroix 提到的。【参考方案2】:

Xamarin.Forms 2.3.4 为此引入了一种新方法:

if (Device.RuntimePlatform == Device.Android)

    // Android specific code

else if (Device.RuntimePlatform == Device.iOS)

    // iOS specific code

else if (Device.RuntimePlatform == Device.UWP)

    // UWP specific code

还有其他平台可供选择,您可以在 Visual Studio 中输入Device.,它会显示选项。

【讨论】:

【参考方案3】:

有多种答案,具体取决于您想要实现的目标以及您拥有的项目类型:

在不同平台上执行不同的Xamarin.Forms代码。 使用这个例如如果您想在不同平台上使用不同的字体大小:

label.Font = Device.OnPlatform<int> (12, 14, 14);

在共享 (PCL) 项目中执行特定于平台的代码 常见的模式是为此使用 DI(依赖注入)。 Xamarin.Forms 为此提供了一个简单的DependencyService,但你可以随意使用。

在共享(共享资产项目)项目中执行平台特定代码 由于代码是按平台编译的,因此您可以将特定于平台的代码包装在 #if __PLATFORM__ #endif 中,并将所有代码放在同一个文件中。平台项目应定义__IOS____ANDROID____WINDOWS_PHONE__。请注意,包含Xaml 和代码的共享资产项目不适用于Xamarin.Studio 上的iOS,并且具有编译器指令会使您的代码更难阅读和测试。

【讨论】:

我目前正在使用带有__IOS____ANDROID__ 语法的选项3“在分片(共享资产项目)项目中执行平台特定代码”,但Android 特定代码未显示在Intellisense 中. iOS 特定代码显示在 Intellisense 中 @MichaelKniskern:将您的构建目标更改为 android,使其具有智能感知功能。并确保(在您的项目首选项中)该符号已导出。顺便说一句,我觉得你使用这个答案并接受另一个答案很有趣:) 我决定选择不依赖于 Xamarin 功能的答案,因为我在空白应用程序(Xamarin.Forms Shared)项目类型方面遇到了其他问题。此外,如果您想使用特定于平台的代码,每次都必须切换启动项目也不理想。【参考方案4】:

Xamarin.Forms 有一个内置的依赖注入器,如果您查看他们网站开发人员区域中的指南 (http://developer.xamarin.com/guides/cross-platform/xamarin-forms/dependency-service/)

您还可以从 NuGet/Github (https://github.com/aritchie/acr-xamarin-forms) 中提取一个很棒的库,它可以处理您正在寻找的存储需求...看看那里的设置服务,它甚至可以处理更多的序列化复杂的对象。

【讨论】:

【参考方案5】:

这似乎不是关于Xamarin.Forms 而是更多关于在 PCL 中使用默认值。查看 James Montemagno's github repo 进行跨平台默认设置。

然后只需调用他的静态方法进行设置/检索。 nuget 包是Xam.Plugins.Settings

可以这样使用:

using Refractored.Xam.Settings;

...

CrossSettings.Current.AddOrUpdateValue("AccessToken", accessToken);
var value = CrossSettings.Current.GetValueOrDefault<string>("AccessToken");

【讨论】:

以上是关于在 Xamarin.Forms 中编写设备平台特定代码的主要内容,如果未能解决你的问题,请参考以下文章

将 Xamarin.Forms.Color 转换为平台特定颜色

Xamarin Forms - TabbedPage 平台特定的 xaml 代码到代码隐藏

如何使用 xamarin.forms 在移动设备中选择多个音频和/或视频文件?

Xamarin.Forms:与平台无关的应用程序菜单

Xamarin Forms:在 Android 设备的内部存储中写入文件

[Xamarin]在Entry中读取键盘按键事件