Skip to main content

Posts e consultas no twitter pelo windows phone 7 part 2 de 2

No artigo anterior (Posts e consultas no twitter pelo windows phone 7 part 1 de 2) no vimos como construir uma aplicação no windows phone 7 que faça consultas no twitter utilizando o api do twitter; Neste artigo vamos tentar construir nesta mesma aplicação algo que o usuário possa fazer o login no twitter, visualize seus posts e adicione novos.
No passo anterior no menu da aplicação nos deixamos um item chamado "login" que servira pra redirecionar para uma tela que o usuário possa efetuar o login no twiter;
Para que essa parte da aplicação funcione  precisamos registrar nossa aplicação no twitter; Acesse dev.twitter.com.


A aplicação deve ser to tipo Browser e a Callback URL informada, essa é uma das exigências do twitter, como nos vamos utilizar a URL do google( http://www.google.com ).
Apos o registro da aplicação  o twitter retorna as url's necessárias para as transações.


Para conseguirmos buscar e enviar informações no twitter vamos utilizar a api de autorizaçao oAuth .
Agora vamos construir nossas classes com estas informações.

TwitterSettings.cs

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace WindowsPhoneApplication1
{
    public class TwitterSettings
    {
        public static string RequestTokenUri = "https://api.twitter.com/oauth/request_token";
        public static string AuthorizeUri = "https://api.twitter.com/oauth/authorize";
        public static string AccessTokenUri = "https://api.twitter.com/oauth/access_token";

        public static string CallbackUri = "http://www.google.com";

        public static string StatusUpdateUrl { get { return "http://api.twitter.com"; } }

        //#error Adicione as respectivas cheves do Twitter aqui
        public static string consumerKey = "consumerKey";
        public static string consumerKeySecret = "consumerKeySecret";

        public static string oAuthVersion = "1.0a";
    }
}

pedido Token e secreto pedido token são conjunto temporário de credenciais que lhe permitem adquirir tokens de acesso OAuth. O token de acesso e secreto token de acesso são necessários para acessar os tweets de um usuário.


Agora vamos montar a classe de tratamento que utiliza as dll's Hammock.WindowsPhone e ICSharpCode.SharpZipLib.WindowsPhone que disponibilizei na primeira parte deste tutorial.

oAuthHelper.cs


using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Hammock.Authentication.OAuth;
using Hammock.Web;

namespace WindowsPhoneApplication1
{
    public class oAuthHelper
    {
        internal static OAuthWebQuery GetRequestTokenQuery()
        {
            var oauth = new OAuthWorkflow
            {
                ConsumerKey = TwitterSettings.consumerKey,
                ConsumerSecret = TwitterSettings.consumerKeySecret,
                SignatureMethod = OAuthSignatureMethod.HmacSha1,
                ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader,
                RequestTokenUrl = TwitterSettings.RequestTokenUri,
                Version = TwitterSettings.oAuthVersion,
                CallbackUrl = TwitterSettings.CallbackUri
            };

            var info = oauth.BuildRequestTokenInfo(WebMethod.Get);
            var objOAuthWebQuery = new OAuthWebQuery(info);
            objOAuthWebQuery.HasElevatedPermissions = true;
            objOAuthWebQuery.SilverlightUserAgentHeader = "Hammock";
            objOAuthWebQuery.SilverlightMethodHeader = "GET";
            return objOAuthWebQuery;
        }

        internal static OAuthWebQuery GetAccessTokenQuery(string requestToken, string RequestTokenSecret, string oAuthVerificationPin)
        {
            var oauth = new OAuthWorkflow
            {
                AccessTokenUrl = TwitterSettings.AccessTokenUri,
                ConsumerKey = TwitterSettings.consumerKey,
                ConsumerSecret = TwitterSettings.consumerKeySecret,
                ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader,
                SignatureMethod = OAuthSignatureMethod.HmacSha1,
                Token = requestToken,
                Verifier = oAuthVerificationPin,
                Version = TwitterSettings.oAuthVersion
            };

            var info = oauth.BuildAccessTokenInfo(WebMethod.Post);
            var objOAuthWebQuery = new OAuthWebQuery(info);
            objOAuthWebQuery.HasElevatedPermissions = true;
            objOAuthWebQuery.SilverlightUserAgentHeader = "Hammock";
            objOAuthWebQuery.SilverlightMethodHeader = "GET";
            return objOAuthWebQuery;
        }

    }
}

Ok, agora que temos nessas classes para trabalho vamos montar uma tela (InTwitter.axml);
A idéia é utilizar o componente browser do wp7 para acessar a pagina de login da nossa aplicação que o twitter nos retorna, assim que o usuário informar login, senha de clicar no botão "Allow", assim que autenticação for feita nos vamos ocultar o browser e exibir em um ListBox os post do usuário e também disponibilizar a visualização de um TextBox e um botão para novos posts que serão feitos, deixando a tela mais ou menos assim:


Vamos criar as seguintes variáveis publicas no nosso InTwitter.axml.cs

string OAuthTokenKey = string.Empty;
string tokenSecret = string.Empty;

string accessToken = string.Empty;
string accessTokenSecret = string.Empty;

string userID = string.Empty;
string userScreenName = string.Empty;

Abaixo do metodo InitializeComponent(); que fica no construtor da classe vamos resgatar as nossas chaves que o twitter nos forneceu e faremos um tratamento das mesmas se estiver tudo ok vamos registrar um evento no browser e no botão de posts:

accessToken = HelperMethods.GetKeyValue<string>("AccessToken");
            accessTokenSecret = HelperMethods.GetKeyValue<string>("AccessTokenSecret");
            userScreenName = HelperMethods.GetKeyValue<string>("ScreenName");


            if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(accessTokenSecret))
            {
                var requestTokenQuery = oAuthHelper.GetRequestTokenQuery();
                requestTokenQuery.RequestAsync(TwitterSettings.RequestTokenUri, null);
                requestTokenQuery.QueryResponse += new EventHandler<WebQueryResponseEventArgs>(requestTokenQuery_QueryResponse);
            }
            else
            {
                GetUserTimeLine(userScreenName);
                Dispatcher.BeginInvoke(() =>
                {

                    var tweetButton = (Microsoft.Phone.Shell.ApplicationBarIconButton)this.ApplicationBar.Buttons[0];
                    tweetButton.IsEnabled = true;
                    PageTitle.Visibility = Visibility.Visible;
                    listboxMyTimeline.Visibility = Visibility.Visible;
                    txtBoxNewTweet.Visibility = Visibility.Visible;
                    btnPostTweet.Visibility = Visibility.Visible;
                });
                
            }

            webBrowser1.Navigated += new EventHandler<System.Windows.Navigation.NavigationEventArgs>(webBrowser1_Navigated);
            webBrowser1.Navigating += new EventHandler<NavigatingEventArgs>(webBrowser1_Navigating);
            btnPostTweet.Click += new RoutedEventHandler(btnPostTweet_Click);
Nos evento requestTokenQuery_QueryResponse vamos tentar capturar autorização utilizando nossa chave OAuthTokenKey  e acionar nosso browser passando a url de autorização.

void requestTokenQuery_QueryResponse(object sender, WebQueryResponseEventArgs e)
        {
            try
            {
                var parameters = HelperMethods.GetQueryParameters(e.Response);
                OAuthTokenKey = parameters["oauth_token"];
                tokenSecret = parameters["oauth_token_secret"];
                var authorizeUrl = TwitterSettings.AuthorizeUri + "?oauth_token=" + OAuthTokenKey;

                Dispatcher.BeginInvoke(() =>
                {
                    this.webBrowser1.Navigate(new Uri(authorizeUrl));
                });
            }
            catch (Exception ex)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show(ex.Message);
                });
            }

        }
No evento  webBrowser1_Navigating  recebemos o resultado da autorização, armazenamos nossa web query na variavel AccessTokenQuery, registramos um enveto AccessTokenQuery_QueryResponse e utilizamos uma requisisão assincrona, disando o evento assim:

void webBrowser1_Navigating(object sender, NavigatingEventArgs e)
        {
            if (e.Uri.ToString().StartsWith(TwitterSettings.CallbackUri))
            {
                var AuthorizeResult = HelperMethods.GetQueryParameters(e.Uri.ToString());
                var VerifyPin = AuthorizeResult["oauth_verifier"];
                this.webBrowser1.Visibility = Visibility.Collapsed;

                var AccessTokenQuery = oAuthHelper.GetAccessTokenQuery(
                                                                         OAuthTokenKey,
                                                                         tokenSecret,
                                                                         VerifyPin
                                                                        );

                AccessTokenQuery.QueryResponse += new EventHandler<WebQueryResponseEventArgs>(AccessTokenQuery_QueryResponse);
                AccessTokenQuery.RequestAsync(TwitterSettings.AccessTokenUri, null);
            }
        }
No evento webBrowser1_Navigated alteramos a visualização do browser e removemos o evento para o usuário ver seus posts

void webBrowser1_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            this.webBrowser1.Visibility = Visibility.Visible;
            this.webBrowser1.Navigated -= webBrowser1_Navigated;
        }

No evento AccessTokenQuery_QueryResponse tentamos armazenar os parâmetros na variável parameters, capturar os valores traves destes parâmetros e habilitar o menu para o usuário fazer o logoff do twitter.

void AccessTokenQuery_QueryResponse(object sender, WebQueryResponseEventArgs e)
        {
            try
            {
                var parameters = HelperMethods.GetQueryParameters(e.Response);
                accessToken = parameters["oauth_token"];
                accessTokenSecret = parameters["oauth_token_secret"];
                userID = parameters["user_id"];
                userScreenName = parameters["screen_name"];


                HelperMethods.SetKeyValue<string>("AccessToken", accessToken);
                HelperMethods.SetKeyValue<string>("AccessTokenSecret", accessTokenSecret);
                HelperMethods.SetKeyValue<string>("ScreenName", userScreenName);

                Dispatcher.BeginInvoke(() =>
                {
                    var AtualizarMenuItem = (Microsoft.Phone.Shell.ApplicationBarMenuItem)this.ApplicationBar.MenuItems[1];
                    AtualizarMenuItem.IsEnabled = true;
                    
                });
                GetUserTimeLine(userScreenName);
            }
            catch (Exception ex)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show(ex.Message);
                });
            }
        }

No evento btnPostTweet_Click precisamos pegar todas as credenciais que foram preenchidas durante o processo dos outros eventos acima e enviar para o twitter e já receber os posts atualizados do usuário.

void btnPostTweet_Click(object sender, RoutedEventArgs e)
        {
            if (txtBoxNewTweet.Text.Trim().Length == 0) { return; }

            var credentials = new OAuthCredentials
            {
                Type = OAuthType.ProtectedResource,
                SignatureMethod = OAuthSignatureMethod.HmacSha1,
                ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader,
                ConsumerKey = TwitterSettings.consumerKey,
                ConsumerSecret = TwitterSettings.consumerKeySecret,
                Token = this.accessToken,
                TokenSecret = this.accessTokenSecret,
                Version = "1.0"
            };

            var restClient = new RestClient
            {
                Authority = TwitterSettings.StatusUpdateUrl,
                HasElevatedPermissions = true,
                Credentials = credentials,
                Method = WebMethod.Post
            };

            restClient.AddHeader("Content-Type", "application/x-www-form-urlencoded");

            var restRequest = new RestRequest
            {
                Path = "1/statuses/update.xml?status=" + txtBoxNewTweet.Text
            };

            var ByteData = Encoding.UTF8.GetBytes(txtBoxNewTweet.Text);
            restRequest.AddPostContent(ByteData);
            restClient.BeginRequest(restRequest, new RestCallback(PostTweetRequestCallback));
        }
No evento PostTweetRequestCallback atualizamos o post do usuário utilizando o método GetUserTimeLine(usuário_logado).

private void PostTweetRequestCallback(RestRequest request, Hammock.RestResponse response, object obj)
        {
            GetUserTimeLine(userScreenName);
        }

Podemos também criar um botão no menu do WP7 que atualize os post enviados pelo usuário e neste botão no invocamos o evento TweetButton_Click.

private void TweetButton_Click(object sender, EventArgs e)
        {
            GetUserTimeLine(userScreenName);
        }
No metodo GetUserTimeLine(usuario_logado) nos temos que registrar o evento wcTwitterTimeline_DownloadStringCompleted.
private void GetUserTimeLine(string userName)
        {
            
            WebClient wcTwitterTimeline = new WebClient();
            wcTwitterTimeline.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wcTwitterTimeline_DownloadStringCompleted);
            wcTwitterTimeline.DownloadStringAsync(new System.Uri("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=" + userName));
        }

No evento wcTwitterTimeline_DownloadStringCompleted nos atualizamos nosso listbox de acordo com com as informações retornadas da API do twiter, que retorna um XML com os posts do usuário que esta logado na nossa aplicação .

void wcTwitterTimeline_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            { return; }
            XElement Tweets = XElement.Parse(e.Result);
            listboxMyTimeline.ItemsSource = from tweet in Tweets.Descendants("status")
                                            select new TwitterItem
                                            {
                                                UserName = tweet.Element("user").Element("screen_name").Value,
                                                Tweet = tweet.Element("text").Value,
                                                ImageSource = tweet.Element("user").Element("profile_image_url").Value
                                            };
            Dispatcher.BeginInvoke(() =>
            {
                listboxMyTimeline.Visibility = Visibility.Visible;
                txtBoxNewTweet.Visibility = Visibility.Visible;
                btnPostTweet.Visibility = Visibility.Visible;
            });
        }

No menu da aplicação podemos invocar o vento MenuItemSignOut_Click que limpara os dados do usuário logado e efetuar o redirecionamento para a tela principal da aplicação.
private void MenuItemSignOut_Click(object sender, EventArgs e)
        {
            HelperMethods.SetKeyValue<string>("AccessToken", string.Empty);
            HelperMethods.SetKeyValue<string>("AccessTokenSecret", string.Empty);
           
            NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
        }

Se precisar entender melhor esta aplicação o download da mesma pode ser feito aqui lembrando que estou deixando esta aplicação preparada para para integração de outras redes sociais.

Comments

Horia said…
Hello, could you please tell me in what namespace do I find the HelperMethods class? I am trying to build an application using your tutorial.

Thank you!
Horia said…
Found it in the source code. Thank you again for this great example!
Unknown said…
Thank you again for this great example!!!

Popular posts from this blog

Verificar sequencia de caracteres iguais em uma string c#

Neste post vamos ver como explorar uma string e verificar se existe uma seqüencia de caracteres iguais dentro da string. Utilizaremos a tabela ASCII para verificar letras e números, se você precisar verificar mais caracteres basta consultar a tabela e colocar o número referente na condição. Neste exemplo vou verificar se existe na string uma seqüencia quatro(4) números iguais e o mesmo para uma seqüencia de três(3) letras, pois acho que em números de documentos ou nomes isto não pode acontecer. Tabela de decimal ASCII public static bool ValidaTexto(this string txt) { bool flag = true; if (txt.Length < 3) { flag = false; } else { int contLetras = 0; int contNumeros = 0; int tmp = (int)txt.ToCharArray()[0]; foreach (char c in txt.ToCharArray()) { if (((int)c < 127 && (int)c >= 65)) { if (tmp == (int)c) { contLetras++; } if (contLetras >= 3) { break; } tmp = (int)c; } } //inicia novamente o armazenador tmp =...

CRIANDO APLICATIVOS DO ZERO E FÁCIL!

O QUE VOCÊ VAI APRENDER? SÃO MAIS DE 10 HORAS DE CONTEÚDO PURO E MATERIAIS EXTRAS: CRIAR APLICATIVOS   Mesmo sendo um total iniciante vamos explicar para você como criar aplicativos profissionais. Utilizaremos a linguagem HTML, CSS, Javascript em união com Apache Cordova. MODELO DE NEGÓCIO  Vamos ensinar como ganhar dinheiro* fazendo aplicativos. Apresentamos os 4 pilares básicos para a monetização de um aplicativos e como fazer para ser bem-sucedido. ATENDIMENTO AO CLIENTE - Vamos dar atenção também a parte humana do processo. Como técnicas de atendimento e precificação, para você convencer seus futuros clientes a fechar negócio com você. Veja os módulos do curso aqui POR QUE FAZER ESTE CURSO? CERTIFICAÇÃO PROFISSIONAL A conclusão deste curso oferece certificação profissional válida em todo território nacional. Podendo portanto ser colocado no seu curriculum, com duração total de 10 horas. GARANTIA Se por algum motivo você achar que est...

Criando um filtro de busca customizável com JavaScript funcional

Tutoriais utilizando bibliotecas e frameworks para state management se tornaram comuns. Apesar disso, já que muita gente usa muitos frameworks diferentes, muitas vezes precisamos falar sobre a plataforma que permite isso tudo: a odiadíssima ferramenta que é o JavaScript, na sua forma mais pura — conforme descrito com documentações excelentes como a da MDN . Esse tutorial também pode ser útil para quem está iniciando em JavaScript e desenvolvimento em geral já começar com alguma ideia do que é programação funcional. O termo está se tornando popular e quem não subir nesse barco pode ficar para trás em pouco tempo. Não vamos adentrar nos detalhes do que é programação funcional neste artigo — isso é assunto para outras horas de conversa. Aqui, ficaremos no rápido e simples: alcançar nosso objetivo, evitando mutações dos dados e estado global. Iniciando o projeto Pelo bem da simplicidade, vamos manter tudo num único arquivo, que vai ter essa cara: <!DOCTYPE HTML> ...