📜 ⬆️ ⬇️

We connect VKontakte SDK for Xamarin.Forms

In the last article, we looked at the issue of connecting native SDKs from Facebook in your applications on Xamarin.Forms for easy user authorization. Today, as promised, we will consider connecting native SDKs for the social network VKontakte. The new SDK will connect to the project that we described in the last article .



Create an application in VKontakte


In general, the integration process of VK will strongly resemble work with Facebook, so feel free to go to the application management page .

Click "Create an application" and select "Standalone-application".
')


Next, go to Settings and enter information about the application. The "certificate fingerprint" is Key Hashes, which we received in the last article.



This preparatory part is completed.

We connect VKontakte SDK to iOS and Android projects


There are a lot of ready-made bindings available for Xamarin, however, a full-featured VKontakte SDK appeared quite recently. The library has been in the beta stage for some time and is now ready for use. Thanks a lot Matthew Leibowitz!



We connect in iOS


We make changes to Info.plist . CFBundleURLTypes values ​​for VKontakte:

 <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLName</key> <string>vk5874073</string> <key>CFBundleURLSchemes</key> <array> <string>fb1102463466549096</string> <string>vk5874073</string> </array> </dict> </array> 

Add new LSApplicationQueriesSchemes :

  <string>vk</string> <string>vk-share</string> <string>vkauthorize</string> 

And also the new domain in NSAppTransportSecurity :

 <key>vk.com</key> <dict> <key>NSExceptionRequiresForwardSecrecy</key> <false/> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> 

After that, we make changes to AppDelegate.cs .

  public override bool FinishedLaunching(UIApplication app, NSDictionary options) { Xamarin.Forms.Forms.Init(); LoadApplication(new App()); Facebook.CoreKit.Profile.EnableUpdatesOnAccessTokenChange(true); Facebook.CoreKit.ApplicationDelegate.SharedInstance.FinishedLaunching(app, options); VKSdk.Initialize("5874073"); return base.FinishedLaunching(app, options); } public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) { return VKSdk.ProcessOpenUrl(url, sourceApplication) || Facebook.CoreKit.ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication, annotation) || base.OpenUrl(application, url, sourceApplication, annotation); } 

This completes the initial initialization of iOS.

Connect to Android


But for Android, you will have to additionally override your Application class to correctly initialize the SDK.

  [Application] public class MainApplication : Application { public MainApplication(IntPtr handle, JniHandleOwnership transer) :base(handle, transer) { } public override void OnCreate() { base.OnCreate(); VKSdk.Initialize(this).WithPayments(); } } 

Now add the application ID to strings.xml :

  <integer name="com_vk_sdk_AppId">5874073</integer> <string name="vk_data_theme">vk5874073</string> 


Add some code to AndroidManifest.xml between <application ..> … :

  <activity android:name="com.binwell.login.MainActivity" android:exported="true"> <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:scheme="@string/vk_data_theme" /> </intent-filter> </activity> 

And complete the extension MainActivity :

 protected override async void OnActivityResult(int requestCode, Result resultCode, Intent data) { bool vkResult; var task = VKSdk.OnActivityResultAsync(requestCode, resultCode, data, out vkResult); if (!vkResult) { base.OnActivityResult(requestCode, resultCode, data); AndroidFacebookService.Instance.OnActivityResult(requestCode, (int)resultCode, data); return; } try { var token = await task; // Get token } catch (Exception e) { // Handle exception } } 

Integrating with Xamarin.Forms


By analogy with Facebook, we will create our own interface in a PCL project to work with the new SDK.

  public interface IVkService { Task<LoginResult> Login(); void Logout(); } 

Implementation for iOS


For iOS, the implementation will look like this:

 [assembly: Dependency(typeof(AppleVkService))] namespace Login.iOS { public class AppleVkService : NSObject, IVkService, IVKSdkDelegate, IVKSdkUIDelegate { readonly string[] _permissions = { VKPermissions.Email, VKPermissions.Offline }; LoginResult _loginResult; TaskCompletionSource<LoginResult> _completionSource; public AppleVkService() { VKSdk.Instance.RegisterDelegate(this); VKSdk.Instance.UiDelegate = this; } public Task<LoginResult> Login() { _completionSource = new TaskCompletionSource<LoginResult>(); VKSdk.Authorize(_permissions); return _completionSource.Task; } public void Logout() { _loginResult = null; _completionSource = null; } [Export("vkSdkTokenHasExpired:")] public void TokenHasExpired(VKAccessToken expiredToken) { VKSdk.Authorize(_permissions); } public new void Dispose() { VKSdk.Instance.UnregisterDelegate(this); VKSdk.Instance.UiDelegate = null; SetCancelledResult(); } public void AccessAuthorizationFinished(VKAuthorizationResult result) { if (result?.Token == null) SetErrorResult(result?.Error?.LocalizedDescription ?? @"VK authorization unknown error"); else { _loginResult = new LoginResult { Token = result.Token.AccessToken, UserId = result.Token.UserId, Email = result.Token.Email, ExpireAt = Utils.FromMsDateTime(result.Token.ExpiresIn), }; Task.Run(GetUserInfo); } } async Task GetUserInfo() { var request = VKApi.Users.Get(NSDictionary.FromObjectAndKey((NSString)@"photo_400_orig", VKApiConst.Fields)); var response = await request.ExecuteAsync(); var users = response.ParsedModel as VKUsersArray; var account = users?.FirstObject as VKUser; if (account != null && _loginResult != null) { _loginResult.FirstName = account.first_name; _loginResult.LastName = account.last_name; _loginResult.ImageUrl = account.photo_400_orig; _loginResult.LoginState = LoginState.Success; SetResult(_loginResult); } else SetErrorResult(@"Unable to complete the request of user info"); } public void UserAuthorizationFailed() { SetErrorResult(@"VK authorization unknown error"); } public void ShouldPresentViewController(UIViewController controller) { Device.BeginInvokeOnMainThread(() => Utils.GetCurrentViewController().PresentViewController(controller, true, null)); } public void NeedCaptchaEnter(VKError captchaError) { Device.BeginInvokeOnMainThread(() => VKCaptchaViewController.Create(csaptchaError).PresentIn(Utils.GetCurrentViewController())); } void SetCancelledResult() { SetResult(new LoginResult { LoginState = LoginState.Canceled }); } void SetErrorResult(string errorString) { SetResult(new LoginResult { LoginState = LoginState.Failed, ErrorString = errorString }); } void SetResult(LoginResult result) { _completionSource?.TrySetResult(result); _loginResult = null; _completionSource = null; } } 

Implementation for android


For Android, too, nothing unusual.

 [assembly: Dependency(typeof(AndroidVkService))] namespace Login.Droid { public class AndroidVkService : Java.Lang.Object, IVkService { public static AndroidVkService Instance => DependencyService.Get<IVkService>() as AndroidVkService; readonly string[] _permissions = { VKScope.Email, VKScope.Offline }; TaskCompletionSource<LoginResult> _completionSource; LoginResult _loginResult; public Task<LoginResult> Login() { _completionSource = new TaskCompletionSource<LoginResult>(); VKSdk.Login(Forms.Context as Activity, _permissions); return _completionSource.Task; } public void Logout() { _loginResult = null; _completionSource = null; VKSdk.Logout(); } public void SetUserToken(VKAccessToken token) { _loginResult = new LoginResult { Email = token.Email, Token = token.AccessToken, UserId = token.UserId, ExpireAt = Utils.FromMsDateTime(token.ExpiresIn) }; Task.Run(GetUserInfo); } async Task GetUserInfo() { var request = VKApi.Users.Get(VKParameters.From(VKApiConst.Fields, @"photo_400_orig,")); var response = await request.ExecuteAsync(); var jsonArray = response.Json.OptJSONArray(@"response"); var account = jsonArray?.GetJSONObject(0); if (account != null && _loginResult != null) { _loginResult.FirstName = account.OptString(@"first_name"); _loginResult.LastName = account.OptString(@"last_name"); _loginResult.ImageUrl = account.OptString(@"photo_400_orig"); _loginResult.LoginState = LoginState.Success; SetResult(_loginResult); } else SetErrorResult(@"Unable to complete the request of user info"); } public void SetErrorResult(string errorMessage) { SetResult(new LoginResult { LoginState = LoginState.Failed, ErrorString = errorMessage }); } public void SetCanceledResult() { SetResult(new LoginResult { LoginState = LoginState.Canceled }); } void SetResult(LoginResult result) { _completionSource?.TrySetResult(result); _loginResult = null; _completionSource = null; } } } 

We connect to Xanarin.Forms


Everything. VKontakte works!



We remind you that for the publication of applications (so that someone other than you can log in), you must perform additional actions for each social network.

We use


Today we learned how to authorize users using native VKontakte SDK. If you need more functionality to work with this social network, we recommend that you study the examples of Matthew himself .

The full code of the project with the connected native SDK for Facebook and VKontakte can be found at .

In the next article, we will look at universal ways to authorize users through OAuth in Xamarin.Forms applications. Stay in touch, ask your questions in the comments and join the Xamarin Developers group in Telegram .

about the author


Vyacheslav Chernikov - head of development at Binwell . In the past, he was one of the Nokia Champion and Qt Certified Specialists, currently he is the Xamarin and Azure platform specialist. He came to the sphere of mobile in 2005, since 2008 he has been developing mobile applications: he started with Symbian, Maemo, Meego, Windows Mobile, then switched to iOS, Android and Windows Phone.

Articles Vyacheslav you can also read the blog on Medium .

Other articles by the author:


Xamarin Meetup: Complex Interfaces in Xamarin.Forms


If you want to talk with the Xamarin Developers community, as well as personally with Vyacheslav, on March 9 in Moscow there will be a meeting on the topic “Complex interfaces in Xamarin Forms”.

Program mitap:

18:00 - 18:30 Registration
18:30 - 19:30 Vyacheslav Chernikov // Connecting RecyclerView / UICollectionView for layout of complex interfaces
19:30 - 19:40 Coffee break
19:40 - 20:40 Yury Nevalenyy // Collections and lists on Xamarin Forms, virtualization patterns and fast cells (Android, iOS, Windows)

Participation is free, registration is required .

Source: https://habr.com/ru/post/323296/


All Articles