做网站怎么去文化局备案,做海报找素材的网站,网站的费用,闵行区最新消息1. 功能简介1.1. 读取手机基本信息主要使用Xamarin.Essentials库获取设备基本信息#xff0c;Xam.Plugin.DeviceInfo插件获取App Id#xff0c;其实该插件也能获取设备基本信息。1.2. 读取手机联系人信息Android和iOS工程具体实现联系人读取服务#xff0c;使用到Dependency… 1. 功能简介1.1. 读取手机基本信息主要使用Xamarin.Essentials库获取设备基本信息Xam.Plugin.DeviceInfo插件获取App Id其实该插件也能获取设备基本信息。1.2. 读取手机联系人信息Android和iOS工程具体实现联系人读取服务使用到DependencyService获取服务功能。1.3. 应用本地化使用资源文件实现本地化目前只做了中、英文。2. 详细功能说明2.1. 读取手机基本信息Xamarin.Essentials库用于获取手机基本信息比如手机厂商、型号、名称、类型、版本等Xam.Plugin.DeviceInfo插件获取App Id用于唯一标识不同手机获取信息见下图代码结构如下图ClientInfoViewModel.csusing Plugin.DeviceInfo;using System;using Xamarin.Essentials;namespace TerminalMACS.Clients.App.ViewModels{ /// summary /// Client base information page ViewModel /// /summary public class ClientInfoViewModel : BaseViewModel { /// summary /// Gets or sets the id of the application. /// /summary public string AppId { get; set; } CrossDeviceInfo.Current.GenerateAppId(); /// summary /// Gets or sets the model of the device. /// /summary public string Model { get; private set; } DeviceInfo.Model; /// summary /// Gets or sets the manufacturer of the device. /// /summary public string Manufacturer { get; private set; } DeviceInfo.Manufacturer; /// summary /// Gets or sets the name of the device. /// /summary public string Name { get; private set; } DeviceInfo.Name; /// summary /// Gets or sets the version of the operating system. /// /summary public string VersionString { get; private set; } DeviceInfo.VersionString; /// summary /// Gets or sets the version of the operating system. /// /summary public Version Version { get; private set; } DeviceInfo.Version; /// summary /// Gets or sets the platform or operating system of the device. /// /summary public DevicePlatform Platform { get; private set; } DeviceInfo.Platform; /// summary /// Gets or sets the idiom of the device. /// /summary public DeviceIdiom Idiom { get; private set; } DeviceInfo.Idiom; /// summary /// Gets or sets the type of device the application is running on. /// /summary public DeviceType DeviceType { get; private set; } DeviceInfo.DeviceType; }}ClientInfoPage.xaml?xml version1.0 encodingutf-8 ?ContentPage xmlnshttp://xamarin.com/schemas/2014/forms xmlns:xhttp://schemas.microsoft.com/winfx/2009/xaml xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006 xmlns:dhttp://xamarin.com/schemas/2014/forms/design xmlns:resourcesclr-namespace:TerminalMACS.Clients.App.Resx xmlns:vmclr-namespace:TerminalMACS.Clients.App.ViewModels mc:Ignorabled x:ClassTerminalMACS.Clients.App.Views.ClientInfoPage Title{x:Static resources:AppResource.Title_ClientInfoPage} ContentPage.BindingContext vm:ClientInfoViewModel/ /ContentPage.BindingContext ContentPage.Content StackLayout Label Text{x:Static resources:AppResource.AppId}/ Label Text{Binding AppId} FontAttributesBold Margin10,0,0,10/ Label Text{x:Static resources:AppResource.DeviceModel}/ Label Text{Binding Model} FontAttributesBold Margin10,0,0,10/ Label Text{x:Static resources:AppResource.DeviceManufacturer}/ Label Text{Binding Manufacturer} FontAttributesBold Margin10,0,0,10/ Label Text{x:Static resources:AppResource.DeviceName}/ Label Text{Binding Name} FontAttributesBold Margin10,0,0,10/ Label Text{x:Static resources:AppResource.DeviceVersionString}/ Label Text{Binding VersionString} FontAttributesBold Margin10,0,0,10/ Label Text{x:Static resources:AppResource.DevicePlatform}/ Label Text{Binding Platform} FontAttributesBold Margin10,0,0,10/ Label Text{x:Static resources:AppResource.DeviceIdiom}/ Label Text{Binding Idiom} FontAttributesBold Margin10,0,0,10/ Label Text{x:Static resources:AppResource.DeviceType}/ Label Text{Binding DeviceType} FontAttributesBold Margin10,0,0,10/ /StackLayout /ContentPage.Content/ContentPage2.2. 读取手机联系人信息Android和iOS工程具体实现联系人读取服务使用到DependencyService获取服务功能功能截图如下2.2.1. TerminalMACS.Clients.App代码结构如下图2.2.1.1. 联系人实体类Contacts.cs目前只获取联系人名称、图片、电子邮件可能多个、电话号码可能多个更多可以扩展。namespace TerminalMACS.Clients.App.Models{ /// summary /// Contact information entity. /// /summary public class Contact { /// summary /// Gets or sets the name /// /summary public string Name { get; set; } /// summary /// Gets or sets the image /// /summary public string Image { get; set; } /// summary /// Gets or sets the emails /// /summary public string[] Emails { get; set; } /// summary /// Gets or sets the phone numbers /// /summary public string[] PhoneNumbers { get; set; } }}2.2.1.2. 联系人服务接口IContactsService.cs包括一个联系人获取请求接口RetrieveContactsAsync一个读取一条联系人结果通知事件OnContactLoaded该接口由具体平台(Android和iOS)实现。using System;using System.Collections.Generic;using System.Threading;using System.Threading.Tasks;using TerminalMACS.Clients.App.Models;namespace TerminalMACS.Clients.App.Services{ /// summary /// Read a contact record notification event parameter. /// /summary public class ContactEventArgs:EventArgs { public Contact Contact { get; } public ContactEventArgs(Contact contact) { Contact contact; } } /// summary /// Contact service interface, which is required for Android and iOS terminal specific /// contact acquisition service needs to implement this interface. /// /summary public interface IContactsService { /// summary /// Read a contact record and notify the shared library through this event. /// /summary event EventHandlerContactEventArgs OnContactLoaded; /// summary /// Loading or not /// /summary bool IsLoading { get; } /// summary /// Try to get all contact information /// /summary /// param nametoken/param /// returns/returns TaskIListContact RetrieveContactsAsync(CancellationToken? token null); }}2.2.1.3. 联系人VMContactViewModel.csVM提供下面两个功能全部联系人加载。联系人关键字查询。using System;using System.Collections;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Linq;using System.Threading.Tasks;using System.Windows.Input;using TerminalMACS.Clients.App.Models;using TerminalMACS.Clients.App.Resx;using TerminalMACS.Clients.App.Services;using Xamarin.Forms;namespace TerminalMACS.Clients.App.ViewModels{ /// summary /// Contact page ViewModel /// /summary public class ContactViewModel : BaseViewModel { /// summary /// Contact service interface /// /summary IContactsService _contactService; private string _SearchText; /// summary /// Gets or sets the search text of the contact list. /// /summary public string SearchText { get { return _SearchText; } set { SetProperty(ref _SearchText, value); } } /// summary /// The search contact command. /// /summary public ICommand RaiseSearchCommand { get; } /// summary /// The contact list. /// /summary public ObservableCollectionContact Contacts { get; set; } private ListContact _FilteredContacts; /// summary /// Contact filter list. /// /summary public ListContact FilteredContacts { get { return _FilteredContacts; } set { SetProperty(ref _FilteredContacts, value); } } public ContactViewModel() { _contactService DependencyService.GetIContactsService(); Contacts new ObservableCollectionContact(); Xamarin.Forms.BindingBase.EnableCollectionSynchronization(Contacts, null, ObservableCollectionCallback); _contactService.OnContactLoaded OnContactLoaded; LoadContacts(); RaiseSearchCommand new Command(RaiseSearchHandle); } /// summary /// Filter contact list /// /summary void RaiseSearchHandle() { if (string.IsNullOrEmpty(SearchText)) { FilteredContacts Contacts.ToList(); return; } FuncContact, bool checkContact (s) { if (!string.IsNullOrWhiteSpace(s.Name) s.Name.ToLower().Contains(SearchText.ToLower())) { return true; } else if (s.PhoneNumbers.Length 0 s.PhoneNumbers.ToList().Exists(cu cu.ToString().Contains(SearchText))) { return true; } return false; }; FilteredContacts Contacts.ToList().Where(checkContact).ToList(); } /// summary /// BindingBase.EnableCollectionSynchronization /// Enable cross thread updates for collections /// /summary /// param namecollection/param /// param namecontext/param /// param nameaccessMethod/param /// param namewriteAccess/param void ObservableCollectionCallback(IEnumerable collection, object context, Action accessMethod, bool writeAccess) { // lock ensures that only one thread access the collection at a time lock (collection) { accessMethod?.Invoke(); } } /// summary /// Received a event notification that a contact information was successfully read. /// /summary /// param namesender/param /// param namee/param private void OnContactLoaded(object sender, ContactEventArgs e) { Contacts.Add(e.Contact); RaiseSearchHandle(); } /// summary /// Read contact information asynchronously /// /summary /// returns/returns async Task LoadContacts() { try { await _contactService.RetrieveContactsAsync(); } catch (TaskCanceledException) { Console.WriteLine(AppResource.TaskCancelled); } } }}2.2.1.4. 联系人展示页面ContactPage.xaml简单的布局一个StackLayout布局容器竖直排列一个SearchBar提供关键字搜索功能。?xml version1.0 encodingutf-8 ?ContentPage xmlnshttp://xamarin.com/schemas/2014/forms xmlns:xhttp://schemas.microsoft.com/winfx/2009/xaml xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006 xmlns:dhttp://xamarin.com/schemas/2014/forms/design xmlns:resourcesclr-namespace:TerminalMACS.Clients.App.Resx xmlns:vmclr-namespace:TerminalMACS.Clients.App.ViewModels xmlns:iosclr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assemblyXamarin.Forms.Core mc:Ignorabled Title{x:Static resources:AppResource.Title_ContactPage} x:ClassTerminalMACS.Clients.App.Views.ContactPage ios:Page.UseSafeAreatrue ContentPage.BindingContext vm:ContactViewModel/ /ContentPage.BindingContext ContentPage.Content StackLayout SearchBar x:NamefilterText HeightRequest40 Text{Binding SearchText} SearchCommand{Binding RaiseSearchCommand}/ ListView ItemsSource{Binding FilteredContacts} HasUnevenRowsTrue ListView.ItemTemplate DataTemplate ViewCell StackLayout Padding10 OrientationHorizontal Image Source{Binding Image} VerticalOptionsCenter x:Nameimage AspectAspectFit HeightRequest60/ StackLayout VerticalOptionsCenter Label Text{Binding Name} FontAttributesBold/ Label Text{Binding PhoneNumbers[0]}/ Label Text{Binding Emails[0]}/ /StackLayout /StackLayout /ViewCell /DataTemplate /ListView.ItemTemplate /ListView /StackLayout /ContentPage.Content/ContentPage2.2.2. Android代码结构如下图AndroidManifest.xml写入读、写联系人权限请求。ContactsService.cs具体的联系人权限请求、数据读取操作。MainActivity.cs接收权限请求结果MainApplicaion.cs此类未添加任务关键代码但必不可少否则无法正确弹出权限请求窗口。PermissionUtil.cs权限请求结果判断2.2.2.1. AndroidManifest.xml添加权限只添加下面这一行即可uses-permission android:nameandroid.permission.READ_CONTACTS /2.2.2.2. ContactsService.csAndroid联系人获取实现服务实现IContactsService。注意命名空间上的特性代码必须添加上这个特性后在前面的联系人VM中才能使用DependencyService.Get()获取此服务实例默认服务是单例的[assembly: Xamarin.Forms.Dependency(typeof(TerminalMACS.Clients.App.iOS.Services.ContactsService))]using Contacts;using Foundation;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Threading;using System.Threading.Tasks;using TerminalMACS.Clients.App.Models;using TerminalMACS.Clients.App.Services;[assembly: Xamarin.Forms.Dependency(typeof(TerminalMACS.Clients.App.iOS.Services.ContactsService))]namespace TerminalMACS.Clients.App.iOS.Services{ /// summary /// Contact service. /// /summary public class ContactsService : NSObject, IContactsService { const string ThumbnailPrefix thumb; bool requestStop false; public event EventHandlerContactEventArgs OnContactLoaded; bool _isLoading false; public bool IsLoading _isLoading; /// summary /// Asynchronous request permission /// /summary /// returns/returns public async Taskbool RequestPermissionAsync() { var status CNContactStore.GetAuthorizationStatus(CNEntityType.Contacts); Tuplebool, NSError authotization new Tuplebool, NSError(status CNAuthorizationStatus.Authorized, null); if (status CNAuthorizationStatus.NotDetermined) { using (var store new CNContactStore()) { authotization await store.RequestAccessAsync(CNEntityType.Contacts); } } return authotization.Item1; } /// summary /// Request contact asynchronously. This method is called by the interface. /// /summary /// param namecancelToken/param /// returns/returns public async TaskIListContact RetrieveContactsAsync(CancellationToken? cancelToken null) { requestStop false; if (!cancelToken.HasValue) cancelToken CancellationToken.None; // We create a TaskCompletionSource of decimal var taskCompletionSource new TaskCompletionSourceIListContact(); // Registering a lambda into the cancellationToken cancelToken.Value.Register(() { // We received a cancellation message, cancel the TaskCompletionSource.Task requestStop true; taskCompletionSource.TrySetCanceled(); }); _isLoading true; var task LoadContactsAsync(); // Wait for the first task to finish among the two var completedTask await Task.WhenAny(task, taskCompletionSource.Task); _isLoading false; return await completedTask; } /// summary /// Load contacts asynchronously, fact reading method of address book. /// /summary /// returns/returns async TaskIListContact LoadContactsAsync() { IListContact contacts new ListContact(); var hasPermission await RequestPermissionAsync(); if (hasPermission) { NSError error null; var keysToFetch new[] { CNContactKey.PhoneNumbers, CNContactKey.GivenName, CNContactKey.FamilyName, CNContactKey.EmailAddresses, CNContactKey.ImageDataAvailable, CNContactKey.ThumbnailImageData }; var request new CNContactFetchRequest(keysToFetch: keysToFetch); request.SortOrder CNContactSortOrder.GivenName; using (var store new CNContactStore()) { var result store.EnumerateContacts(request, out error, new CNContactStoreListContactsHandler((CNContact c, ref bool stop) { string path null; if (c.ImageDataAvailable) { path path Path.Combine(Path.GetTempPath(), ${ThumbnailPrefix}-{Guid.NewGuid()}); if (!File.Exists(path)) { var imageData c.ThumbnailImageData; imageData?.Save(path, true); } } var contact new Contact() { Name string.IsNullOrEmpty(c.FamilyName) ? c.GivenName : ${c.GivenName} {c.FamilyName}, Image path, PhoneNumbers c.PhoneNumbers?.Select(p p?.Value?.StringValue).ToArray(), Emails c.EmailAddresses?.Select(p p?.Value?.ToString()).ToArray(), }; if (!string.IsNullOrWhiteSpace(contact.Name)) { OnContactLoaded?.Invoke(this, new ContactEventArgs(contact)); contacts.Add(contact); } stop requestStop; })); } } return contacts; } }}2.2.2.3. MainActivity.cs代码简单只在OnRequestPermissionsResult方法中接收权限请求结果// The contact service processes the result of the permission request.ContactsService.OnRequestPermissionsResult(requestCode, permissions, grantResults);2.2.3. iOS代码结构如下图ContactsService.cs具体的联系人权限请求、数据读取操作。Info.plist权限请求时描述文件2.2.3.1. ContactsService.csiOS具体的联系人读取服务实现IContactsService接口原理同Android联系人服务类似本人无调试环境iOS此功能未测试。using Contacts;using Foundation;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Threading;using System.Threading.Tasks;using TerminalMACS.Clients.App.Models;using TerminalMACS.Clients.App.Services;[assembly: Xamarin.Forms.Dependency(typeof(TerminalMACS.Clients.App.iOS.Services.ContactsService))]namespace TerminalMACS.Clients.App.iOS.Services{ /// summary /// Contact service. /// /summary public class ContactsService : NSObject, IContactsService { const string ThumbnailPrefix thumb; bool requestStop false; public event EventHandlerContactEventArgs OnContactLoaded; bool _isLoading false; public bool IsLoading _isLoading; /// summary /// Asynchronous request permission /// /summary /// returns/returns public async Taskbool RequestPermissionAsync() { var status CNContactStore.GetAuthorizationStatus(CNEntityType.Contacts); Tuplebool, NSError authotization new Tuplebool, NSError(status CNAuthorizationStatus.Authorized, null); if (status CNAuthorizationStatus.NotDetermined) { using (var store new CNContactStore()) { authotization await store.RequestAccessAsync(CNEntityType.Contacts); } } return authotization.Item1; } /// summary /// Request contact asynchronously. This method is called by the interface. /// /summary /// param namecancelToken/param /// returns/returns public async TaskIListContact RetrieveContactsAsync(CancellationToken? cancelToken null) { requestStop false; if (!cancelToken.HasValue) cancelToken CancellationToken.None; // We create a TaskCompletionSource of decimal var taskCompletionSource new TaskCompletionSourceIListContact(); // Registering a lambda into the cancellationToken cancelToken.Value.Register(() { // We received a cancellation message, cancel the TaskCompletionSource.Task requestStop true; taskCompletionSource.TrySetCanceled(); }); _isLoading true; var task LoadContactsAsync(); // Wait for the first task to finish among the two var completedTask await Task.WhenAny(task, taskCompletionSource.Task); _isLoading false; return await completedTask; } /// summary /// Load contacts asynchronously, fact reading method of address book. /// /summary /// returns/returns async TaskIListContact LoadContactsAsync() { IListContact contacts new ListContact(); var hasPermission await RequestPermissionAsync(); if (hasPermission) { NSError error null; var keysToFetch new[] { CNContactKey.PhoneNumbers, CNContactKey.GivenName, CNContactKey.FamilyName, CNContactKey.EmailAddresses, CNContactKey.ImageDataAvailable, CNContactKey.ThumbnailImageData }; var request new CNContactFetchRequest(keysToFetch: keysToFetch); request.SortOrder CNContactSortOrder.GivenName; using (var store new CNContactStore()) { var result store.EnumerateContacts(request, out error, new CNContactStoreListContactsHandler((CNContact c, ref bool stop) { string path null; if (c.ImageDataAvailable) { path path Path.Combine(Path.GetTempPath(), ${ThumbnailPrefix}-{Guid.NewGuid()}); if (!File.Exists(path)) { var imageData c.ThumbnailImageData; imageData?.Save(path, true); } } var contact new Contact() { Name string.IsNullOrEmpty(c.FamilyName) ? c.GivenName : ${c.GivenName} {c.FamilyName}, Image path, PhoneNumbers c.PhoneNumbers?.Select(p p?.Value?.StringValue).ToArray(), Emails c.EmailAddresses?.Select(p p?.Value?.ToString()).ToArray(), }; if (!string.IsNullOrWhiteSpace(contact.Name)) { OnContactLoaded?.Invoke(this, new ContactEventArgs(contact)); contacts.Add(contact); } stop requestStop; })); } } return contacts; } }}2.2.3.2. Info.plist联系人权限请求说明 2.3. 应用本地化使用资源文件实现本地化目前只做了中、英文。资源文件如下指定默认区域性要使资源文件可正常使用应用程序必须指定 NeutralResourcesLanguage。在共享项目中应自定义 AssemblyInfo.cs 文件以指定默认区域性 。以下代码演示如何在 AssemblyInfo.cs 文件中将 NeutralResourcesLanguage 设置为 zh-CN (摘自官方文档https://docs.microsoft.com/zh-cn/samples/xamarin/xamarin-forms-samples/usingresxlocalization/后经测试注释下面这段代码也能正常本地化)[assembly: NeutralResourcesLanguage(zh-Hans)]XAML中使用引入资源文件命名空间xmlns:resourcesclr-namespace:TerminalMACS.Clients.App.Resx具体使用如Label Text{x:Static resources:AppResource.ClientName_AboutPage} FontAttributesBold/3. 关于TerminalMACS及本客户端3.1. TermainMACS多终端资源管理与检测系统包含多个子进程模块目前只开发了Xamarin.Forms客户端下一步开发服务端使用 .NET 5 Web API开发基于Abp vNext搭建。3.2. Xamarin.Forms客户端作为TerminalMACS系统的一个子进程模块目前只开发了手机基本信息获取、联系人信息获取、本地化功能后续开发服务端时会配合添加通信功能比如连接服务端验证、主动推送已获取资源等。3.3. 关于项目开源开源项目地址https://github.com/dotnet9/TerminalMACS除非注明文章均由 TerminalMACS 整理发布欢迎转载。转载请注明本文地址https://terminalmacs.com/890.html