Home
%3CLINGO-SUB%20id%3D%22lingo-sub-565490%22%20slang%3D%22ja-JP%22%3EXamarin.Forms%20app%20Development%20using%20Visual%20Studio%20App%20Center%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-565490%22%20slang%3D%22ja-JP%22%3E%3CP%3EThe%20Visual%20Studio%20App%20Center%20has%20recently%20become%20MBaaS.%3C%2FP%3E%0A%3CP%3EI%20was%20wondering%20if%20Microsoft%20MBaaS%20is%20an%20Azure%20App%20Services%20Mobile%20App%2C%20but%20I%20thought%20it%20was%20not%20a%20recent%20update...%3C%2FP%3E%0A%3CP%3E%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FAzure%2Fazure-mobile-apps%23future-of-azure-mobile-apps%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3EFuture%20of%20Azure%20Mobile%20Apps%3C%2FA%3E%3C%2FP%3E%0A%3CPRE%3EMicrosoft%20is%20committed%20to%20fully%20supporting%20Azure%20Mobile%20Apps%2C%20including%20support%20for%20the%20%3CBR%20%2F%3Elatest%20OS%20release%2C%20bug%20fixes%2C%20documentation%20improvements%2C%20and%20community%20PR%20reviews.%20%3CBR%20%2F%3EPlease%20note%20that%20the%20product%20team%20is%20not%20currently%20investing%20in%20any%20new%20feature%20work%20for%20%3CBR%20%2F%3EAzure%20Mobile%20Apps.%20We%20highly%20appreciate%20community%20contributions%20to%20all%20areas%20of%20Azure%20Mobile%20Apps.%3C%2FPRE%3E%0A%3CP%3EIt%20was%20announced%20that%20it%20was%20not%20focusing%20on%20adding%20new%20features.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3EVisual%20Studio%20App%20Center%20as%20the%20destination%3C%2FSTRONG%3E%3C%2FP%3E%0A%3CP%3ESince%20the%20maintenance%20will%20be%2C%20but%20there%20is%20also%20a%20judgment%20that%20it%20stays%20for%20a%20while%20if%20you%20are%20satisfied%20functionally%2C%20the%20Visual%20Studio%20App%20Center%20is%20likely%20to%20be%20rising%20candidate%20as%20a%20destination%20in%20terms%20of%20MBaaS%20that%20has%20been%20added%20function.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIt%20is%20added%20in%20the%20preview%20to%20the%20Data%20function%20the%20other%20day%2C%20and%20it%20is%20a%20lineup%20of%20the%20following%20functions.%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3EBuild%3C%2FLI%3E%0A%3CLI%3ETest%3C%2FLI%3E%0A%3CLI%3EDistribute%3C%2FLI%3E%0A%3CLI%3EDiagnostics%3C%2FLI%3E%0A%3CLI%3EAnalytics%3C%2FLI%3E%0A%3CLI%3EAuth%3C%2FLI%3E%0A%3CLI%3EData%3C%2FLI%3E%0A%3CLI%3EPush%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3EThere%20is%20no%20API%20to%20put%20in%20any%20action%2C%20but%20when%20you%20need%20pin%2C%20will%20you%20be%20using%20Azure%20WebApp%20or%20the%20per%20Function%20App%3F%3C%2FP%3E%0A%3CP%3EI%20didn't%20check%20it%20for%20a%20while%2C%20but%20it%20seems%20to%20have%20been%20fulfilling%20a%20lot.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3ELet's%20try%20it.%3C%2FSTRONG%3E%3C%2FP%3E%0A%3CP%3ESo%2C%20I%20want%20to%20try%20from%20Xamarin.Forms.%3C%2FP%3E%0A%3CP%3ECreate%20an%20application%20for%20Xamarin.Forms%20in%20Visual%20Studio%202019The%20target%20was%20Android%20and%20iOS.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EBecause%20there%20is%20no%20macOS%20at%20hand%20this%20time%2C%20I%20think%20that%20I%20do%20only%20with%20Android%20to%20check%20operation.After%20you%20create%20the%20project%2C%20create%20a%20repository%20on%20GitHub%20and%20push%20it.Then%20create%20Android%20Xamarin%20app%20in%20Visual%20Studio%20App%20Center.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20265px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113216i42FB4BB3E06C5722%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22Comments%202019-05-14%20103911.jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20103911.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EOnce%20you%20have%20the%20app%20Center%2C%20configure%20the%20build.This%20is%20not%20required%20in%20terms%20of%20using%20various%20functions%2C%20but%20the%20sense%20of%20security%20increases%20when%20there%20is%20an%20automatic%20build%2C%20so%20people%20who%20do%20not%20have%20an%20automatic%20build%20environment%20in%20particular%20should%20consider%20adopting.You%20need%20to%20prepare%20a%20key%2C%20such%20as%20a%20build%20to%20sign%20with%20a%20certificate%2C%20but%20if%20not%2C%20simply%20select%20the%20repository%20and%20follow%20the%20wizard%20to%20complete%20it.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThen%2C%20from%20NuGet%20Package%20Manager%2C%20install%20the%20following%20packages%3AAnyway%2C%20I%20would%20like%20to%20activate%20Analytics%20and%20Diagnostics.%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3E%3CSPAN%3EMicrosoft.AppCenter.Analytics%3C%2FSPAN%3E%3C%2FLI%3E%0A%3CLI%3E%3CSPAN%3EMicrosoft.AppCenter.Crashes%3C%2FSPAN%3E%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3E%3CSPAN%3EAnd%2C%20I%20write%20the%20initialization%20code%2C%20but%20there%20is%20one%20problem.I%20don't%20want%20to%20put%20the%20AppID%20of%20the%20Visual%20Studio%20App%20Center%20into%20the%20repository....%3C%2FSPAN%3E%3CSPAN%3EIt%20adds%20a%20lot%20of%20effort.%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EAdd%20the.%20AppCenterConfiguration.cs%20file%20and%20add%20it%20to%20the.%20Geignore.AppCenterConfiguration.cs%20to%20the%20following%20content.%3C%2FP%3E%0A%3CPRE%3Eusing%20System%3B%0Ausing%20System.Collections.Generic%3B%0Ausing%20System.Text%3B%0A%0Anamespace%20AppCenterLab%0A%7B%0A%20%20%20%20public%20static%20class%20AppCenterConfiguration%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20public%20const%20string%20Android%20%3D%20%22%26lt%3Byour%20android%20app%20id%26gt%3B%22%3B%0A%20%20%20%20%20%20%20%20public%20const%20string%20iOS%20%3D%20%22%22%3B%0A%20%20%20%20%20%20%20%20public%20const%20string%20UWP%20%3D%20%22%22%3B%0A%20%20%20%20%7D%0A%7D%0A%3C%2FPRE%3E%0A%3CP%3EThen%20add%20the%20following%20code%20to%20the%20App.xaml.cs%20OnStart%20method%3A%3C%2FP%3E%0A%3CPRE%3EAppCenter.Start(%24%22android%3D%7BAppCenterConfiguration.Android%7D%3B%22%20%2B%0A%20%20%20%20%20%20%24%22ios%3D%7BAppCenterConfiguration.iOS%7D%22%2C%0A%20%20%20%20%20%20typeof(Analytics)%2C%20typeof(Crashes))%3B%3C%2FPRE%3E%0A%3CP%3EYou%20should%20now%20be%20able%20to%20use%20Analytics%20and%20Crashes.You%20can%20send%20logs%20to%20the%20server%20by%20writing%20the%20following%20code%20at%20the%20appropriate%20location%3A%3C%2FP%3E%0A%3CPRE%3EAnalytics.TrackEvent(%22Some%20message%22%2C%20new%20Dictionary%26lt%3Bstring%2C%20string%26gt%3B%0A%7B%0A%20%20%5B%22prop1%22%5D%20%3D%20%22value1%22%2C%0A%20%20%5B%22prop2%22%5D%20%3D%20%22value2%22%2C%0A%20%20%5B%22prop3%22%5D%20%3D%20%22value3%22%2C%0A%7D)%3B%3C%2FPRE%3E%0A%3CP%3E%3CSTRONG%3EAdd%20authentication%3C%2FSTRONG%3E%3C%2FP%3E%0A%3CP%3EYou%20can%20authenticate%20with%20Azure%20AD%20B2C.With%20Azure%20AD%20B2C%2C%20you%20can%20log%20in%20with%20your%20own%20users%2C%20Twitter%2C%20and%20other%20SNS.%3C%2FP%3E%0A%3CP%3ESo%2C%20create%20an%20Azure%20AD%20B2C%20container%20in%3CA%20href%3D%22https%3A%2F%2Fportal.azure.com%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ehttps%3A%2F%2Fportal.azure.com%3C%2FA%3E%20.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EDetails%20are%20listed%20here%20in%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fja-jp%2Fappcenter%2Fauth%2Fgetting-started%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3EGetting%20Started%3C%2FA%3E%20.%3C%2FP%3E%0A%3CP%3EFollow%20the%20instructions%20below%20to%20create%20the%20app.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20586px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113223i02F711877FCDCC3E%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22Comments%202019-05-14%20120756.jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20120756.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ELet's%20also%20add%20access%20%3CSTRONG%20class%3D%22%22%3Ethis%20app%20on%20behalf%20of%20the%20signed-in%20User%20(user_impersonation)%3C%2FSTRONG%3E%20%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3E%20to%20API%20access.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20720px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113224iE4E1894E19606A1F%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22Comments%202019-05-14%2012154jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20121154.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EAdd%20the%20IDENTITY%20provider%20as%20needed.You%20can%20sign%20in%20with%20your%20SNS%20account%20by%20adding%20Twitter%2C%20Facebook%2C%20and%20more.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EGo%20to%20App%20Center%20and%20select%20Auth%20Connect%20your%20Azure%20Subscription.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20360px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113225i5AD5A703250D9887%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22Comments%202019-05-14%20121834.jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20121834.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EChoose%20your%20Azure%20subscription.And%20since%20Azure%20AD%20B2C%20is%20said%20not%20to%20be%20found%2C%20click%20Create%20a%20new%20Azure%20AD%20B2C%20tenant%20to%20connect%20the%20Azure%20ad%20B2C%20you%20just%20created.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20909px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113226iA357B1364EFE9148%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22Comments%202019-05-14%20122304.jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20122304.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EOnce%20created%2C%20your%20Azure%20AD%20B2C%20tenant%20will%20be%20displayed.(Once%20you%20come%20back%20and%20you%20will%20see)%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20604px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113227i7C6B5758C1B8FCBA%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22Comments%202019-05-14%20122428.jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20122428.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3ESelect%20the%20application%20and%20also%20select%20Scope%20and%20press%20Next.The%20last%20Policy%20is%20that%20you%20can%20get%20it%20from%20the%20Azure%20AD%20B2C%20user%20flow%2C%20but%20it%20was%20empty%20for%20me%2C%20so%20sign%20in%20to%20Azure%20AD%20B2C%20and%20create%20a%20user%20flow%20for%20signing%20out.The%20name%20comes%20out%20when%20you%20create%20it%2C%20and%20you%20enter%20it%20in%20Policy.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EPress%20OK%20to%20jump%20to%20the%20page%20on%20how%20to%20activate%20Auth.Add%20the%20following%20NuGet%20accordingly.%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3E%3CSPAN%3EMicrosoft.AppCenter.Auth%3C%2FSPAN%3E%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3E%3CSPAN%3EThen%20change%20the%20App.xaml.cs%20OnStart%20method%20to%20activate%20Auth.%3C%2FSPAN%3E%3C%2FP%3E%0A%3CPRE%3EAppCenter.Start(%24%22android%3D%7BAppCenterConfiguration.Android%7D%3B%22%20%2B%0A%20%20%20%20%20%20%24%22ios%3D%7BAppCenterConfiguration.iOS%7D%22%2C%0A%20%20%20%20%20%20typeof(Analytics)%2C%20typeof(Crashes)%2C%20typeof(Auth))%3B%0A%3C%2FPRE%3E%0A%3CP%3E%3CSPAN%3EAdd%20the%20following%20definitions%20below%20the%20AndroidManifest.xml%20application%20tag%3A(Replace%20the%20part%20with%20the%20AppCenter's%20%3CYOUR%20android%3D%22%26quot%3B%26quot%3B%22%20app%3D%22%26quot%3B%26quot%3B%22%20id%3D%22%26quot%3B%26quot%3B%22%3EActual%20Appcenter)%3C%2FYOUR%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CPRE%3E%26lt%3Bactivity%20android%3Aname%3D%22com.microsoft.identity.client.BrowserTabActivity%22%26gt%3B%0A%20%20%26lt%3Bintent-filter%26gt%3B%0A%20%20%20%20%20%20%26lt%3Baction%20android%3Aname%3D%22android.intent.action.VIEW%22%20%2F%26gt%3B%0A%0A%20%20%20%20%20%20%26lt%3Bcategory%20android%3Aname%3D%22android.intent.category.DEFAULT%22%20%2F%26gt%3B%0A%20%20%20%20%20%20%26lt%3Bcategory%20android%3Aname%3D%22android.intent.category.BROWSABLE%22%20%2F%26gt%3B%0A%0A%20%20%20%20%20%20%26lt%3Bdata%0A%20%20%20%20%20%20%20%20%20%20android%3Ahost%3D%22auth%22%0A%20%20%20%20%20%20%20%20%20%20android%3Ascheme%3D%22msal%26lt%3Byour%20android%20app%20id%26gt%3B%22%20%2F%26gt%3B%0A%20%20%26lt%3B%2Fintent-filter%26gt%3B%0A%26lt%3B%2Factivity%26gt%3B%3C%2FPRE%3E%0A%3CP%3E%3CSPAN%3EIf%20you%20upload%20this%20to%20the%20repository%2C%20the%20app%20ID%20will%20be%20public....What%20if....I%20gave%20up%20because%20it%20is%20difficult%20for%20the%20time%20being.%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20this%20state%2C%20you%20can%20sign%20in%20by%20writing%20the%20following%20code%2C%20such%20as%20a%20button%20click%20event.%3C%2FP%3E%0A%3CPRE%3Eprivate%20async%20void%20Button_Clicked(object%20sender%2C%20EventArgs%20e)%0A%7B%0A%20%20%20%20try%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20var%20user%20%3D%20await%20Auth.SignInAsync()%3B%0A%20%20%20%20%20%20%20%20await%20DisplayAlert(%22User%22%2C%20%24%22%7Buser.AccountId%7D%22%2C%20%22Close%22)%3B%0A%20%20%20%20%7D%0A%20%20%20%20catch%20(Exception%20ex)%0A%20%20%20%20%7B%0A%20%20%20%20%7D%0A%7D%3C%2FPRE%3E%0A%3CP%3EThe%20login%20screen%20looks%20like%20this.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20202px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113228iE9E11F0CBD9BF991%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22Comments%202019-05-14%20130224.jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20130224.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EIf%20the%20login%20succeeds%2C%20you%20will%20see%20a%20dialog%20similar%20to%20the%20following.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20199px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113229i9709871C8D5BA4F3%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22Comments%202019-05-14%20131925.jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20131925.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3ELet's%20persist%20the%20data%3C%2FSTRONG%3E%3C%2FP%3E%0A%3CP%3EFinally%2C%20try%20to%20persist%20the%20data.Azure%20Cosmos%20DB%20is%20used%20as%20the%20backend.%3C%2FP%3E%0A%3CP%3ESelect%20Data%20in%20App%20Center%20and%20select%20New%20database.Add%20your%20subscription%2C%20name%20and%20performance.Then%2C%20it%20transitions%20to%20the%20page%20of%20the%20use%20of%20the%20SDK.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EFollow%20the%20guide%20to%20add%20the%20following%20NuGet%20packages%3A%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3E%3CSPAN%3EMicrosoft.AppCenter.Data%3C%2FSPAN%3E%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3E%3CSPAN%3EThen%20add%20Data%20to%20the%20App.xaml.cs%20OnStart%20method.%3C%2FSPAN%3E%3C%2FP%3E%0A%3CPRE%3Eprotected%20override%20void%20OnStart()%0A%7B%0A%20%20%20%20AppCenter.Start(%24%22android%3D%7BAppCenterConfiguration.Android%7D%3B%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%24%22ios%3D%7BAppCenterConfiguration.iOS%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20typeof(Analytics)%2C%20typeof(Crashes)%2C%20typeof(Auth)%2C%20typeof(Data))%3B%0A%7D%3C%2FPRE%3E%0A%3CP%3EDefine%20the%20data%20to%20save.This%20is%20a%20regular%20C%23%20class.%3C%2FP%3E%0A%3CPRE%3Eusing%20System%3B%0Ausing%20System.Collections.Generic%3B%0Ausing%20System.Text%3B%0A%0Anamespace%20AppCenterLab%0A%7B%0A%20%20%20%20public%20class%20Person%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20public%20Guid%20Id%20%7B%20get%3B%20set%3B%20%7D%20%3D%20Guid.NewGuid()%3B%0A%20%20%20%20%20%20%20%20public%20string%20Name%20%7B%20get%3B%20set%3B%20%7D%0A%20%20%20%20%20%20%20%20public%20DateTimeOffset%20Birthday%20%7B%20get%3B%20set%3B%20%7D%0A%20%20%20%20%7D%0A%7D%3C%2FPRE%3E%0A%3CP%3EThen%2C%20I'll%20write%20code%20for%20adding%20and%20loading%20data.%3C%2FP%3E%0A%3CPRE%3Eprivate%20async%20void%20AddButton_Clicked(object%20sender%2C%20EventArgs%20e)%0A%7B%0A%20%20%20%20var%20p%20%3D%20new%20Person%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20Name%20%3D%20%22sample%22%20%2B%20new%20Random().Next()%2C%0A%20%20%20%20%20%20%20%20Birthday%20%3D%20DateTimeOffset.Now%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20await%20Data.CreateAsync(p.Id.ToString()%2C%20p%2C%20DefaultPartitions.UserDocuments)%3B%0A%7D%0A%0Aprivate%20async%20void%20ReadButton_Clicked(object%20sender%2C%20EventArgs%20e)%0A%7B%0A%20%20%20%20var%20r%20%3D%20new%20List%26lt%3BPerson%26gt%3B()%3B%0A%20%20%20%20var%20result%20%3D%20await%20Data.ListAsync%26lt%3BPerson%26gt%3B(DefaultPartitions.UserDocuments)%3B%0A%20%20%20%20r.AddRange(result.CurrentPage.Items.Select(x%20%3D%26gt%3B%20x.DeserializedValue))%3B%0A%20%20%20%20while(result.HasNextPage)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20await%20result.GetNextPageAsync()%3B%0A%20%20%20%20%20%20%20%20r.AddRange(result.CurrentPage.Items.Select(x%20%3D%26gt%3B%20x.DeserializedValue))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20await%20DisplayAlert(%22Result%22%2C%20%24%22%7Br.Count%7D%20items%20found%2C%20%7Bstring.Join(%22%2C%20%22%2C%20r.Select(x%20%3D%26gt%3B%20x.Name))%7D%22%2C%20%22OK%22)%3B%0A%7D%3C%2FPRE%3E%0A%3CP%3EThe%20following%20results%20were%20made%20when%20the%20load%20was%20added%20four%20times.It%20seems%20to%20be%20going%20well%20because%20it%20found%20four.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20200px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F113232i9D5D5847313EC9E8%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22Comments%202019-05-14%20142750.jpg%22%20title%3D%22%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%202019-05-14%20142750.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EThere%20seems%20to%20be%20a%20function%20of%20obtaining%20all%20the%20search%20and%20paging%20function%20by%20the%20registration%2C%20the%20update%2C%20the%20deletion%2C%20and%20the%20ID%20at%20present.The%20search%20function%20seems%20not%20at%20the%20moment%2C%20so%20it%20may%20be%20a%20little%20early%20to%20be%20practical%20yet.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWhen%20I%20looked%20into%20Cosmos%20DB%2C%20I%20found%20the%20following%20JSON.%3C%2FP%3E%0A%3CPRE%3E%7B%0A%20%20%20%20%22document%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22Id%22%3A%20%22bacac454-14ee-47c3-b2ea-6607ca92f722%22%2C%0A%20%20%20%20%20%20%20%20%22Name%22%3A%20%22sample1767140010%22%2C%0A%20%20%20%20%20%20%20%20%22Birthday%22%3A%20%222019-05-14T05%3A25%3A55.152477%2B00%3A00%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22id%22%3A%20%22bacac454-14ee-47c3-b2ea-6607ca92f722%22%2C%0A%20%20%20%20%22PartitionKey%22%3A%20%22user-e839c173-73cf-4f7e-96bd-f3e3a3a9c55e%22%2C%0A%20%20%20%20%22_rid%22%3A%20%22TIp8AIK21DACAAAAAAAAAA%3D%3D%22%2C%0A%20%20%20%20%22_self%22%3A%20%22dbs%2FTIp8AA%3D%3D%2Fcolls%2FTIp8AIK21DA%3D%2Fdocs%2FTIp8AIK21DACAAAAAAAAAA%3D%3D%2F%22%2C%0A%20%20%20%20%22_etag%22%3A%20%22%5C%220300774a-0000-2400-0000-5cda51670000%5C%22%22%2C%0A%20%20%20%20%22_attachments%22%3A%20%22attachments%2F%22%2C%0A%20%20%20%20%22_ts%22%3A%201557811559%0A%7D%3C%2FPRE%3E%0A%3CP%3EYou%20have%20given%20PartitionKey%20to%20the%20user%2C%20so%20you%20can%20see%20that%20the%20user%20identifier%20is%20in%20PartitionKey.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3ESummary%3C%2FSTRONG%3E%3C%2FP%3E%0A%3CP%3EAzure%20Mobile%20Apps%20is%20supported%2C%20but%20the%20development%20of%20new%20features%20is%20the%20status%20of%20not%20being%20put%20resources%2C%20so%20look%20at%20the%20timing%20(after%20Data%20GAYou%20may%20also%20have%20to%20switch%20to%20the%20Visual%20Studio%20App%20Center.%3C%2FP%3E%3C%2FLINGO-BODY%3E
Microsoft

最近 Visual Studio App Center が本格的に MBaaS 化してきています。

Microsoft の MBaaS といえば Azure App Services の Mobile App かと思ってたのですが、最近アップデート無いなぁと思って確認してみると…

Future of Azure Mobile Apps

Microsoft is committed to fully supporting Azure Mobile Apps, including support for the 
latest OS release, bug fixes, documentation improvements, and community PR reviews.
Please note that the product team is not currently investing in any new feature work for
Azure Mobile Apps. We highly appreciate community contributions to all areas of Azure Mobile Apps.

新機能の追加には注力していないとアナウンスされていました。

 

移行先としての Visual Studio App Center

メンテナンスはされていくので、機能的に満足していればそのまま暫く居るという判断もありですが、機能追加がされている MBaaS という観点では Visual Studio App Center が移行先としては候補にあがりそうです。

 

先日 Data 機能までプレビューで追加されて、以下のような機能のラインナップになっています。

  • Build
  • Test
  • Distribute
  • Diagnostics
  • Analytics
  • Auth
  • Data
  • Push

任意の処理を入れる API はありませんが、そこらへんが必要になった時には Azure WebApp や Function App あたりを使う事になるのかな?

暫くチェックしていなかったのですが、色々充実してきているみたいです。

 

試してみよう

ということで、Xamarin.Forms から試してみたいと思います。

Visual Studio 2019 で Xamarin.Forms のアプリケーションを作成します。ターゲットは Android と iOS にしました。

 

今回は手元に macOS がないので、動作確認は Android のみでやろうと思います。プロジェクトを作成したら、GitHub にリポジトリーを作成して push します。そして、Visual Studio App Center で Android の Xamarin のアプリを作成します。

コメント 2019-05-14 103911.jpg

App Center にアプリが出来たらビルドの構成をしておきます。これは各種機能を使う上では必須ではないですが自動ビルドがあると安心感が増すので、特に自動ビルド環境がないという人は採用を検討してみるといいのではないでしょうか。証明書で署名するビルドだと鍵の準備などが必要ですが、そうでなければリポジトリーを選択してウィザードに従うだけで完了します。

 

次に、NuGet パッケージ マネージャーから、以下のパッケージをインストールします。とりあえずは、Analytics と Diagnostics を有効化したいと思います。

  • Microsoft.AppCenter.Analytics
  • Microsoft.AppCenter.Crashes

そして、初期化コードを書くのですが問題点が一つ。リポジトリーに Visual Studio App Center の AppID を入れたくない…。ということでひと手間加えます。

AppCenterConfiguration.cs ファイルを追加して .gitignore に追加しておきます。AppCenterConfiguration.cs は以下のような内容にします。

using System;
using System.Collections.Generic;
using System.Text;

namespace AppCenterLab
{
    public static class AppCenterConfiguration
    {
        public const string Android = "<your android app id>";
        public const string iOS = "";
        public const string UWP = "";
    }
}

そして、App.xaml.cs の OnStart メソッドに以下のコードを追加します。

AppCenter.Start($"android={AppCenterConfiguration.Android};" +
      $"ios={AppCenterConfiguration.iOS}",
      typeof(Analytics), typeof(Crashes));

これで、Analytics と Crashes が使えるようになります。適当な場所で以下のようなコードを書くことでサーバーにログを送れます。

Analytics.TrackEvent("Some message", new Dictionary<string, string>
{
  ["prop1"] = "value1",
  ["prop2"] = "value2",
  ["prop3"] = "value3",
});

認証の追加

Azure AD B2C による認証が出来ます。Azure AD B2C を使うと独自のユーザーや Twitter などの SNS を使ったログインが実現できます。

ということで、https://portal.azure.com で Azure AD B2C コンテナを作成します。

 

詳細はここの Getting Started に記載があります。

それに従い以下のようにアプリを作成します。

コメント 2019-05-14 120756.jpg

 

API アクセスに Access this app on behalf of the signed-in user (user_impersonation) も追加しましょう。

コメント 2019-05-14 121154.jpg

ID プロバイダーを必要に応じて追加します。ここに Twitter や Facebook などを追加することで SNS アカウントでログインができるようになります。

 

App Center に移動して Auth の Connect your Azure Subscription を選択します。

コメント 2019-05-14 121834.jpg

Azure のサブスクリプションを選びます。そして、Azure AD B2C がみつからないと言われるので Create a new Azure AD B2C tenant をクリックして、先ほど作成した Azure AD B2C を紐づけましょう。

コメント 2019-05-14 122304.jpg

作成が終わると Azure AD B2C のテナントが表示されるようになります。(一度 Back して戻ってくると表示されます)

コメント 2019-05-14 122428.jpg

アプリケーションも選択して Scope も選択して Next を押します。最後の Policy は、Azure AD B2C のユーザーフローから取得できるとあるのですが、私のところでは空っぽだったので Azure AD B2C に サインインサインアウトのユーザーフローを作成します。作成すると名前が出てくるので、それを Policy のところに入力します。

 

OK を押すと Auth を有効化する方法のページに飛びます。それに従って以下の NuGet を追加します。

  • Microsoft.AppCenter.Auth

そして、App.xaml.cs の OnStart メソッドを Auth を有効化するように変更します。

AppCenter.Start($"android={AppCenterConfiguration.Android};" +
      $"ios={AppCenterConfiguration.iOS}",
      typeof(Analytics), typeof(Crashes), typeof(Auth));

AndroidManifest.xml の application タグの下に以下の定義を追加します。(<your android app id>の部分は AppCenter の実際の AppID に置き換えてください)

<activity android:name="com.microsoft.identity.client.BrowserTabActivity">
  <intent-filter>
      <action android:name="android.intent.action.VIEW" />

      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />

      <data
          android:host="auth"
          android:scheme="msal<your android app id>" />
  </intent-filter>
</activity>

これをリポジトリーにアップすると app id がパブリックになりますね…。どうしよう…。とりあえず難しいので諦めました。

 

この状態で適当なボタンのクリックイベントなどに以下のコードを書くとサインインが実行できます。

private async void Button_Clicked(object sender, EventArgs e)
{
    try
    {
        var user = await Auth.SignInAsync();
        await DisplayAlert("User", $"{user.AccountId}", "Close");
    }
    catch (Exception ex)
    {
    }
}

このような感じの見た目のログイン画面が出てきました。

コメント 2019-05-14 130224.jpg

ログインが成功すると、以下のようなダイアログが出てきます。

コメント 2019-05-14 131925.jpg

データを永続化しよう

最後にデータの永続化を試してみます。バックエンドとしては Azure の Cosmos DB が使われます。

App Center で Data を選択して New database を選択します。サブスクリプションや名前や性能を入れていきます。そうすると、SDK の使い方のページに遷移します。

 

ガイドに従って以下の NuGet パッケージを追加します。

  • Microsoft.AppCenter.Data

そして、App.xaml.cs の OnStart メソッドに Data を追加します。

protected override void OnStart()
{
    AppCenter.Start($"android={AppCenterConfiguration.Android};" +
          $"ios={AppCenterConfiguration.iOS}",
          typeof(Analytics), typeof(Crashes), typeof(Auth), typeof(Data));
}

保存するデータを定義します。これは普通の C# のクラスです。

using System;
using System.Collections.Generic;
using System.Text;

namespace AppCenterLab
{
    public class Person
    {
        public Guid Id { get; set; } = Guid.NewGuid();
        public string Name { get; set; }
        public DateTimeOffset Birthday { get; set; }
    }
}

そして、データの追加と読み込みのコードを書いてみます。

private async void AddButton_Clicked(object sender, EventArgs e)
{
    var p = new Person
    {
        Name = "sample" + new Random().Next(),
        Birthday = DateTimeOffset.Now,
    };
    await Data.CreateAsync(p.Id.ToString(), p, DefaultPartitions.UserDocuments);
}

private async void ReadButton_Clicked(object sender, EventArgs e)
{
    var r = new List<Person>();
    var result = await Data.ListAsync<Person>(DefaultPartitions.UserDocuments);
    r.AddRange(result.CurrentPage.Items.Select(x => x.DeserializedValue));
    while(result.HasNextPage)
    {
        await result.GetNextPageAsync();
        r.AddRange(result.CurrentPage.Items.Select(x => x.DeserializedValue));
    }

    await DisplayAlert("Result", $"{r.Count} items found, {string.Join(", ", r.Select(x => x.Name))}", "OK");
}

追加を 4 回して読み込みをすると以下のような結果になりました。4 件みつかっているのでうまくいってるようです。

コメント 2019-05-14 142750.jpg

現時点では登録・更新・削除・IDによる検索・ページング機能付きの全件取得の機能があるようです。検索機能は現時点ではないみたいなので、まだ実用するにはちょっと早いのかもしれません。

 

Cosmos DB を覗いてみると以下のような感じの JSON が入っていました。

{
    "document": {
        "Id": "bacac454-14ee-47c3-b2ea-6607ca92f722",
        "Name": "sample1767140010",
        "Birthday": "2019-05-14T05:25:55.152477+00:00"
    },
    "id": "bacac454-14ee-47c3-b2ea-6607ca92f722",
    "PartitionKey": "user-e839c173-73cf-4f7e-96bd-f3e3a3a9c55e",
    "_rid": "TIp8AIK21DACAAAAAAAAAA==",
    "_self": "dbs/TIp8AA==/colls/TIp8AIK21DA=/docs/TIp8AIK21DACAAAAAAAAAA==/",
    "_etag": "\"0300774a-0000-2400-0000-5cda51670000\"",
    "_attachments": "attachments/",
    "_ts": 1557811559
}

PartitionKey をユーザーに指定していたので、ユーザーの識別子みたいなのが PartitionKey に入っていることがわかります。

 

まとめ

Azure Mobile Apps は、サポートはされるけど新機能の開発にはリソースは投入されないというステータスなのでタイミングを見て(Data が GA したあとあたり?) Visual Studio App Center に乗り換えるのもありかもしれません。