Sharing to Social Networks Using Xamarin.Social and Xamarin.Auth Programatically
I had a requirement in an app to send tweets programmatically without displaying the ui. Xamarin.Social seemed to be exactly what I needed once I found the ShareAsync Method.
twitter.ShareItemAsync (item, e.Account);
The only thing I needed to was to specify the Twitter account to use. So, using Xamarin.Social I called the TwitterService to get the Twitter account installed on the device.
var twitter = new TwitterService { ConsumerKey ="123", ConsumerSecret ="145" }; var accounts = AccountStore.Create(this).FindAccountsForService("Twitter"); var acc = accounts.ToList ().FirstOrDefault(); var item = new Item { Text = "Xamarin.Social is the bomb.com." }; item.Links.Add (new Uri ("http://github.com/xamarin/xamarin.social")); try { await twitter.ShareItemAsync (item, acc); } catch (Exception ex) { Console.WriteLine(ex.Message); }
But for some reason accounts kept coming back null. Modifying the code to the following also didn't work.
var twitter = new TwitterService { ConsumerKey ="123", ConsumerSecret ="145" }; var accounts = await twitter.GetAccountsAsync(); var acc = accounts.ToList ().FirstOrDefault(); var item = new Item { Text = "Xamarin.Social is the bomb.com." }; item.Links.Add (new Uri ("http://github.com/xamarin/xamarin.social")); try { await twitter.ShareItemAsync (item, acc); } catch (Exception ex) { Console.WriteLine(ex.Message); }
I couldn't figure it out. It seemed so simple. I'm telling the code to pull the already configured Twitter account on the device. But why was it null??? Here's why. The following two lines of codes wasn't doing what I thought
var accounts = AccountStore.Create(this).FindAccountsForService("Twitter"); var accounts = await twitter.GetAccountsAsync();
Neither of these lines pulled the devices accounts. Instead, the fix was to use Xamarin.Auth to authenticate the Twitter account then store it to be used later. Here's the code
var auth = new OAuth1Authenticator ( consumerKey: App.Instance.OAuth1Settings.ConsumerKey, consumerSecret : App.Instance.OAuth1Settings.ConsumerSecret, requestTokenUrl: new Uri (App.Instance.OAuth1Settings.RequestTokenUrl), authorizeUrl: new Uri (App.Instance.OAuth1Settings.AuthorizeUrl), accessTokenUrl: new Uri (App.Instance.OAuth1Settings.AccessTokenUrl), callbackUrl: new Uri (App.Instance.OAuth1Settings.CallbackUrl)); auth.Completed += async (s, e) => { if (e.IsAuthenticated) { // Use eventArgs.Account to do wonderful things AccountStore.Create().Save(e.Account,"MyApp-Twitter"); var twitter = new TwitterService { ConsumerKey ="App.Instance.OAuth1Settings.ConsumerKey", ConsumerSecret =App.Instance.OAuth1Settings.ConsumerSecret }; var item = new Item { Text = "Xamarin.Social is the bomb.com." }; item.Links.Add (new Uri ("http://github.com/xamarin/xamarin.social")); try { await twitter.ShareItemAsync (item, e.Account); } catch (Exception ex) { Console.WriteLine(ex.Message); } } else { // The user cancelled } }; PresentViewController (auth.GetUI (), true, null);
The magic is this line
AccountStore.Create().Save(e.Account,"MyApp-Twitter");
where I saved the authenticated account to the Account Store using a unique ServiceID(my app name and twitter). Then I passed e.Account to the ShareItemAsync method.
Later in my app I can simply use
var accounts = AccountStore.Create(this).FindAccountsForService("MyApp-Twitter");
to pull the account again to pass back to the share method. The take away is the ShareItemAsync needs you to specify an account and most importantly this is an account you have auth'ed and saved NOT the Twitter account in your iOS settings or the Android Twitter app. Hope this saves someone else the time figuring it out!









