Microsoft Band の着せ替え機能で壁紙を取得してみます
ソースコードの一式は下記にあります!
細かい実装などはこちらを参照ください
※ 順次改修していく予定なので、この記事の内容が現時点のソースより古い可能性があります
問題となる BandImage を扱うことになるので、まずは変換クラスを作ります
/// <summary> /// iOS 用画像コンバーター /// </summary> public static class NativeBandImageConvert { /// <summary> /// 画像の変換 /// </summary> /// <param name="image">画像情報</param> /// <returns>画像ソース</returns> public static StreamImageSource FromNative(Native.Personalization.BandImage image) { return (StreamImageSource)ImageSource.FromStream(image.UIImage.AsPNG().AsStream); } /// <summary> /// 画像の変換 /// </summary> /// <param name="source">画像ソース</param> /// <returns>画像情報</returns> public static async Task<Native.Personalization.BandImage> ToNative(StreamImageSource source) { var stream = await source.Stream.Invoke(new CancellationToken()); var image = await Task.Run(() => { using (var data = NSData.FromStream(stream)) { return UIImage.LoadFromData(data); } }); return new Native.Personalization.BandImage(image); } }
これが iOS で
/// <summary> /// Android 用画像コンバーター /// </summary> public static class NativeBandImageConvert { /// <summary> /// 画像の変換 /// </summary> /// <param name="image">画像情報</param> /// <returns>画像ソース</returns> public static StreamImageSource FromNative(Bitmap image) { return (StreamImageSource)ImageSource.FromStream(() => { var stream = new MemoryStream(); image.Compress(Bitmap.CompressFormat.Png, 100, stream); stream.Seek(0L, SeekOrigin.Begin); return stream; }); } /// <summary> /// 画像の変換 /// </summary> /// <param name="source">画像ソース</param> /// <returns>画像情報</returns> public static async Task<Bitmap> ToNative(StreamImageSource source) { var stream = await source.Stream.Invoke(new CancellationToken()); return await BitmapFactory.DecodeStreamAsync(stream); } }
これが Android
/// <summary> /// Windows 用画像コンバーター /// </summary> public static class NativeBandImageConvert { /// <summary> /// 画像の変換 /// </summary> /// <param name="image">画像情報</param> /// <returns>画像ソース</returns> public static StreamImageSource FromNative(BandImage image) { return (StreamImageSource)ImageSource.FromStream(() => image.ToWriteableBitmap().PixelBuffer.AsStream()); } /// <summary> /// 画像の変換 /// </summary> /// <param name="source">画像ソース</param> /// <returns>画像情報</returns> public static async Task<BandImage> ToNative(StreamImageSource source) { var stream = await source.Stream.Invoke(new CancellationToken()); using (var ras = stream.AsRandomAccessStream()) { var bitmap = new WriteableBitmap(310, 102); await bitmap.SetSourceAsync(ras); return bitmap.ToBandImage(); } } }
そして Windows Phone・・・画像の取り扱いは面倒ですね
この変換クラスを利用して NativePersonalizationManager を改修
/// <summary> /// iOS 用着せ替え管理クラス /// </summary> public class NativeBandPersonalizationManager : IBandPersonalizationImageManager { ~ 中略 ~ /// <summary> /// 壁紙の取得 /// </summary> /// <returns>壁紙画像のソース</returns> public async Task<StreamImageSource> GetMeTileImageSourceAsync() { return NativeBandImageConvert.FromNative( await Native.Personalization.BandPersonalizationManagerExtensions.GetMeTileImageTaskAsync(this.manager)); } }
Android や Windows Phone もほぼ同じです
これに合わせて ViewModel も変更
/// <summary> /// 着せ替え設定 ViewModel /// </summary> public class PersonalizeViewModel : BindableBase { #region MeTileImage /// <summary> /// 壁紙画像ソース /// </summary> private ImageSource meTileImageSource = ImageSource.FromResource(@"XamarinBandSample.Assets.me-tile.png"); /// <summary> /// 壁紙画像ソース /// </summary> public ImageSource MeTileImageSource { get { return this.meTileImageSource; } set { this.SetProperty<ImageSource>(ref this.meTileImageSource, value); } } #endregion //MeTileImage /// <summary> /// コンストラクタ /// </summary> /// <param name="client">接続クライアント</param> [InjectionConstructor] public PersonalizeViewModel(IBandClient client, IBandPersonalizationImageManager manager) { this.IsBusy = true; this.client = client; this.manager = manager; this.PullCommand = DelegateCommand.FromAsyncHandler(this.Pull); this.ApplyCommand = DelegateCommand.FromAsyncHandler(this.Apply); this.BaseColor.SelecedIndex = 1; this.HighContrastColor.Color = "#FF9966ff"; this.HighlightColor.Color = "#FF9966ff"; this.LowlightColor.Color = "#FF6633cc"; this.MutedColor.Color = "#FF663399"; this.SecondaryTextColor.SelecedIndex = 5; this.baseColor.PropertyChanged += this.OnBaseColorChanged; this.IsBusy = false; } /// <summary> /// 設定状況取得 /// </summary> /// <returns>Task</returns> private async Task Pull() { this.IsBusy = true; var theme = await this.manager.GetThemeAsync(); this.BaseColor.Color = ColorToString(theme.Base); this.BaseColor.SelecedIndex = -1; this.HighContrastColor.Color = ColorToString(theme.HighContrast); this.HighlightColor.Color = ColorToString(theme.Highlight); this.LowlightColor.Color = ColorToString(theme.Lowlight); this.MutedColor.Color = ColorToString(theme.Muted); this.SecondaryTextColor.Color = ColorToString(theme.SecondaryText); this.SecondaryTextColor.SelecedIndex = -1; var source = await this.manager.GetMeTileImageSourceAsync(); this.MeTileImageSource = source; this.IsBusy = false; } ~ 中略 ~ }
MeTileImageSource というプロパティに壁紙画像の ImageSource を保持するようにし、初期値は適当な画像(既定サイズ 310 x 102 px)を用意して設定しています
最後に 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" xmlns:cv="clr-namespace:XamarinBandSample.Converters;assembly=XamarinBandSample" xmlns:c="clr-namespace:XamarinBandSample.Controls;assembly=XamarinBandSample" xmlns:t="clr-namespace:XamarinBandSample.Triggers;assembly=XamarinBandSample" xmlns:prismmvvm="clr-namespace:Prism.Mvvm;assembly=XamarinBandSample" prismmvvm:ViewModelLocator.AutoWireViewModel="true" x:Class="XamarinBandSample.Views.TopPage"> <ContentPage.Resources> <ResourceDictionary> <cv:NegativeConverter x:Key="NegativeConverter"/> <cv:ColorConverter x:Key="ColorConverter"/> </ResourceDictionary> </ContentPage.Resources> <Grid> ~ 中略 ~ <!-- Persomalize Info Pain--> <ScrollView IsVisible="{Binding ShowPersonalize}" Orientation="Vertical"> <StackLayout Orientation="Vertical" BindingContext="{Binding Personalize}" Padding="10" Spacing="10" VerticalOptions="StartAndExpand"> <StackLayout Orientation="Horizontal" BindingContext="{Binding BaseColor}" Spacing="10"> <Label Text="Base" WidthRequest="100" FontSize="Small"/> <BoxView WidthRequest="30" HeightRequest="30" BackgroundColor="{Binding Color, Converter={StaticResource ColorConverter}}"/> <c:BindablePicker ItemsSource="{Binding ColorLabelSelection}" IsEnabled="{Binding IsBusy, Converter={StaticResource NegativeConverter}}" SelectedIndex="{Binding SelecedIndex, Mode=TwoWay}"/> </StackLayout> <StackLayout Orientation="Horizontal" BindingContext="{Binding HighContrastColor}" Spacing="10"> <Label Text="HighContrast" WidthRequest="100" FontSize="Small"/> <BoxView WidthRequest="30" HeightRequest="30" BackgroundColor="{Binding Color, Converter={StaticResource ColorConverter}}"/> </StackLayout> <StackLayout Orientation="Horizontal" BindingContext="{Binding HighlightColor}" Spacing="10"> <Label Text="Highlight" WidthRequest="100" FontSize="Small"/> <BoxView WidthRequest="30" HeightRequest="30" BackgroundColor="{Binding Color, Converter={StaticResource ColorConverter}}"/> </StackLayout> <StackLayout Orientation="Horizontal" BindingContext="{Binding LowlightColor}" Spacing="10"> <Label Text="Lowlight" WidthRequest="100" FontSize="Small"/> <BoxView WidthRequest="30" HeightRequest="30" BackgroundColor="{Binding Color, Converter={StaticResource ColorConverter}}"/> </StackLayout> <StackLayout Orientation="Horizontal" BindingContext="{Binding MutedColor}" Spacing="10"> <Label Text="Muted" WidthRequest="100" FontSize="Small"/> <BoxView WidthRequest="30" HeightRequest="30" BackgroundColor="{Binding Color, Converter={StaticResource ColorConverter}}"/> </StackLayout> <StackLayout Orientation="Horizontal" BindingContext="{Binding SecondaryTextColor}" Spacing="10"> <Label Text="SecondaryText" WidthRequest="100" FontSize="Small"/> <BoxView WidthRequest="30" HeightRequest="30" BackgroundColor="{Binding Color, Converter={StaticResource ColorConverter}}"/> <c:BindablePicker ItemsSource="{Binding ColorLabelSelection}" IsEnabled="{Binding IsBusy, Converter={StaticResource NegativeConverter}}" SelectedIndex="{Binding SelecedIndex, Mode=TwoWay}"/> </StackLayout> <Label Text="Me Tile" FontSize="Small"/> <Image Source="{Binding MeTileImageSource}" WidthRequest="310"/> <StackLayout Orientation="Horizontal" Padding="10" Spacing="10" HorizontalOptions="End"> <Button Text="Pull" IsEnabled="{Binding IsBusy, Converter={StaticResource NegativeConverter}}" Command="{Binding PullCommand}" VerticalOptions="Center" FontSize="Medium"/> <Button Text=" Apply" IsEnabled="{Binding IsBusy, Converter={StaticResource NegativeConverter}}" Command="{Binding ApplyCommand}" VerticalOptions="Center" FontSize="Medium"/> </StackLayout> </StackLayout> </ScrollView> </Grid> </ContentPage>
Me Tile の表示領域を追加しています
さてお試し実行!
結構取得に時間がかかるのですが無事壁紙画像が取得できました