Olá povo,
Nunca me interessei em testar APIs para redes sociais por dois motivos: não gosto muito dessa febre; e pensava que era bem trivial ao ponto de ter milhões de tutoriais por aí. Grande engano. Quando fui adicionar suporte ao Twitter em uma aplicação que estou trabalhando, notei que existem algumas etapas 'chatinhas' para realizar essa integração. Não sei se a forma que estou utilizando aqui é a melhor, inclusive, se vocês tiverem sugestões, deixem seus comentários :)
Sem mais "delongas", vamos começar! Nesse post, vou mostrar como realizar o processo de autenticação no Twitter e 'twitar' uma mensagem. Para começar, obviamente você deve ter uma conta comum no Twitter. Para ter acesso aos recursos da API, você (como desenvolvedor) deverá cadastrar sua aplicação no site
https://dev.twitter.com. Esse cadastro servirá para a equipe do Twitter saber qual aplicação (e consequentemente o login) responsável pelo cliente que está acessando o Twitter. Isso é similar ao que é feito quando utilizamos a API de Mapas do Google, onde você deve usar sua conta do Google para obter uma chave, para então utilizar o serviço.
O cadastro é bem simples, basta informar: o nome da aplicação, descrição da mesma, URL para contato e uma URL de callback. Este último é mais importante para aplicações web, onde após efetuar o login, a chave de acesso será direcionada.
Uma vez cadastrada, serão geradas alguma informações que serão utilizadas para integração da nossa aplicação com o Twitter. Nós precisaremos da "Consumer Key" e "Consumer Secret".
Como funciona a autenticação no Twitter?
Até meados do segundo semestre de 2010, o acesso ao twitter funcionava basicamente passando o login e a senha em texto plano. Por motivos óbvios de segurança, essa forma foi descontinuada, e passou-se a utilizar a forma de autenticação
OAuth. Esse processo é ilustrado na figura abaixo:
Não vou entrar em muitos detalhes sobre esse protocolo, mas basicamente o cliente envia um solicitação de acesso utilizando a consumerKey e consumerSecret para o servidor, o servidor então retorna uma URL para que o usuário se autentique. Nesse momento o usuário insere seu usuário e senha do Twitter. Uma vez passadas essas informações, o servidor valida esses dados e gera um token de acesso, que será usada para toda a comunicação com o Twitter. Esse tone deve ser salvo no cliente para que ele possa se comunicar com o servidor sem ter passar o login e a senha a cada transacção.
Mãos à obra!
De posse do conceito sobre a autenticação do Twitter, vamos implementar nosso exemplo. Ele constará de apenas uma tela, onde o usuário poderá fazer o login/logout no Twitter e atualizar o seu status a partir da mesma. A tela da aplicação é exibida abaixo:
Você pode implementar a comunicação com o Twitter do zero, utilizando JSON. Mas existem algumas APIs prontas que facilitam nosso trabalho. A que utilizarei aqui é a
Twitter4J. Baixe a última versão estável, descompacte em algum local do seu HD. Crie um novo projeto Android, e copie o arquivo twitter4j-core-android-X.X.X.jar que está na pasta lib do Twitter4J para a pasta lib do seu projeto Android (essa pasta não é criada por padrão, então crie na raiz do seu projeto). Em seguida, adicione esse JAR no Build-Path do Eclipe clicando com o botão direito sobre o arquivo, e depois selecionando Build Path > Add to Build path. Seu projeto deve ficar como na figura abaixo.
Vamos ao código :) Vou começar pelo AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="ngvl.android.twitter"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<activity
android:name=".ExemploTwitterActivity"
android:label="@string/app_name"
android:noHistory="true">
<intent-filter>
<action
android:name="android.intent.action.MAIN"/>
<category
android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<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="nglauber-android"/>
</intent-filter>
</activity>
</application>
</manifest>
Aqui nesse arquivo temos algumas coisas muito importantes:
- A tag
uses-permission para nossa aplicação poder acessar internet;
- Foi adicionada a propriedade
andróide:noHistory à tag activity, para que quando o Browser seja aberto para o usuário fazer o login, ao voltar, ele não crie outra instância dessa activity.
- Essa activity tem dois intent-filter. O primeiro é pra execução normal da aplicação e o segundo é usado pela página do Twitter. Após a autenticação, ele redirecionará para o endereço
nglauber-android://?oauthverifier=sua_chave. Estamos informando que essa atividade trata esse "protocolo", dessa forma nossa activity será re-executada.
Agora vamos ver o código da Activity.
package ngvl.android.twitter;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class ExemploTwitterActivity extends Activity {
private final String
consumerKey = "SUA CONSUMER KEY";
private final String
consumerSecret = "SUA CONSUMER SECRET";
private final String
CALLBACKURL = "nglauber-android:///";
private Twitter twitter;
No código acima, as constantes cosumerKey e consumerSecret devem ser preenchidas com as informações do cadastro da sua aplicação no site do Twitter. Já a constante CALLBACKURL deve estar igual a que foi declarada no AndroidManifest.xml.
O atributo twitter proverá acesso ao processo de login e de atualização do status.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(
consumerKey, consumerSecret);
}
No onCreate apenas inicializamos o layout da tela, obtemos a instância do Twitter através da classe TwitterFactory e setamos a consumer key e secret.
public void clickLogin(View v) {
try {
AccessToken accessToken = loadAccessToken();
if (accessToken == null) {
twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(
consumerKey, consumerSecret);
RequestToken requestToken =
twitter.getOAuthRequestToken(CALLBACKURL);
String url = requestToken.getAuthenticationURL();
Intent it = new Intent(
Intent.ACTION_VIEW, Uri.parse(url));
it.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(it);
saveRequestData(requestToken.getToken(),
requestToken.getTokenSecret());
} else {
twitter.setOAuthAccessToken(accessToken);
}
} catch (Exception e) {
e.printStackTrace();
showToast(e.getMessage());
}
}
O método acima, iniciará o processo de login e será chamado ao clicar no botão de login. Através do método loadAccessToken (definido mais adiante), ele tenta obter um objeto AccessToken salvo anteriormente. Caso não exista, o processo de login inicia com a obtenção da url para fazermos o login no Twitter. Notem que é passada a constante CALLBACKURL como parâmetro, isso indica qual endereço será chamado quando o login for concluído. Essa é uma URL "fake" que será chamada quando o login for efetuado. Neste momento, o browser redireciona a chave para
nglauber-android://?oauthverifier=sua_chave, e o "protocolo" nglauber-android está sendo tratado por nossa atividade, como definido no AndroidManifest.xml.
A flag FLAG_ACTIVITY_NO_HISTORY evita que, ao pressionar back após o login, o browser seja exibido novamente. Após chamar o browser para o login, o token e o token secret da requisição são salvos pelo método saveRequestData (veremos esse método mais adiante).
Ao clicar no botão de login, será exibida a tela de autenticação do Twitter. Aqui é solicitado autorização para que a aplicação que cadastramos no começo desse post tenha acesso a sua conta do Twitter. Digite seu login e senha e clique em "Sign In".
Após realizar o login, a página do Twitter envia a chave para nossa Activity. Tratamos o recebimento dessa chave no método onResume conforme abaixo:
@Override
protected void onResume() {
super.onResume();
Uri uri = getIntent().getData();
if (uri != null) {
String oauthVerifier =
uri.getQueryParameter("oauth_verifier");
try {
RequestToken requestToken = loadRequestToken();
AccessToken at = twitter.getOAuthAccessToken(
requestToken, oauthVerifier);
saveAccessToken(
at.getToken(), at.getTokenSecret());
} catch (TwitterException e) {
e.printStackTrace();
showToast(e.getMessage());
}
}
}
Quando a atividade é chamada pela página do twitter, uma chave de verificação da requisição de acesso é retornada. Com a requisição e a chave de verificação podemos criar um objeto AccessToken para acessar os recursos do Twitter. O token e o token secret do objeto AccessToken são salvos no método saveAccessToken (definido mais adiante) e, como vimos anteriormente podem ser recuperados quando clicamos no botão de login.
Abaixo temos o método que é chamado ao clicar no botão Tweet.
public void clickTweet(View v) {
try {
if (loadAccessToken() != null){
EditText edt =
(EditText) findViewById(R.id.editText1);
String tweet = edt.getText().toString();
twitter.updateStatus(tweet);
showToast("Status atualizado com sucesso!");
} else {
showToast("Faça o login antes de Twittar");
}
} catch (TwitterException e) {
e.printStackTrace();
showToast(e.getMessage());
}
}
Nada de mais aqui. Apenas pega o conteúdo da caixa de texto e manda alterar o status do objeto Twitter.
Abaixo temos método auxiliares que utilizamos no nosso código. O primeiro exibe um Toast na tela.
private void showToast(String s){
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
Os métodos que salvam e recuperam as chaves de solicitação (RequestToken) e de acesso (AccessToken) estão definidos abaixo. Para ambos são utilizados SharedPreferences.
private RequestToken loadRequestToken(){
SharedPreferences prefs = PreferenceManager.
getDefaultSharedPreferences(this);
String reqToken =
prefs.getString("request_token", null);
String reqTokenSecret =
prefs.getString("request_tokensecret", null);
return new RequestToken(reqToken, reqTokenSecret);
}
private void saveRequestData(
String requestToken, String requestTokenSecret){
SharedPreferences prefs = PreferenceManager.
getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(
"request_token", requestToken);
editor.putString(
"request_tokensecret", requestTokenSecret);
editor.commit();
}
private AccessToken loadAccessToken() {
SharedPreferences prefs = PreferenceManager.
getDefaultSharedPreferences(this);
String acToken =
prefs.getString("access_token", null);
String acTokenSecret =
prefs.getString("access_tokensecret", null);
if (acToken != null || acTokenSecret != null){
return new AccessToken(acToken, acTokenSecret);
}
return null;
}
private void saveAccessToken(
String accessToken, String accessTokenSecret) {
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(
"access_token", accessToken);
editor.putString(
"access_tokensecret", accessTokenSecret);
editor.commit();
}
Por fim, o método que faz o logout, limpa os valores da sharedpreference de AccessToken, o que vai forçar a realização de um novo login.
public void clickLogout(View v) {
saveAccessToken(null, null);
}
É isso pessoal, qualquer dúvida, deixem seus comentários.
4br4ç05,
nglauber