Twitter Login (Fabric), Firebase Android - Parte 7

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /Twitter Login (Fabric), Firebase Android - Parte 7

Twitter Login (Fabric), Firebase Android - Parte 7

Vinícius Thiengo
(3524)
Go-ahead
"O método consciente de tentativa e erro é mais bem-sucedido que o planejamento de um gênio isolado."
Peter Skillman
Prototipagem Android
Capa do curso Prototipagem Profissional de Aplicativos
TítuloAndroid: Prototipagem Profissional de Aplicativos
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
Acessar Curso
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Lendo
TítuloManual de DevOps: como obter agilidade, confiabilidade e segurança em organizações tecnológicas
CategoriaEngenharia de Software
Autor(es)Gene Kim, Jez Humble, John Willis, Patrick Debois
EditoraAlta Books
Edição1ª
Ano2018
Páginas464
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

Opa, blz?

Nesse post continuamos com a série sobre o Firebase no Android, dessa vez abordando o login social com o Twitter Login. Junto ao Fabric Plugin o Twitter Login acaba sendo tarefa fácil no momento da integração.

Note que para continuar com esse conteúdo, Twitter Login, é necessário que você tenha uma conta de usuário no Twitter e em sua conta de usuário, deve ter seu telefone celular vinculado (vá em Configuração => Celular). Pois com essa configuração você será capaz de criar um Twitter APP.

Para acessar o projeto por completo acesse o GitHub: https://github.com/viniciusthiengo/nosso-chate

Antes de prosseguir, abaixo listo os posts já disponíveis dessa série:

Google SignIn API, Firebase Android - Parte 6

Facebook Login, Firebase Android - Parte 5

Remoção de Conta e Dados de Login, Firebase Android - Parte 4

Atualização de Dados, Firebase Android - Parte 3

Eventos de Leitura e Firebase UI Android - Parte 2

Persistência Com Firebase Android - Parte 1

Agora seguindo com o projeto.

Nosso primeiro passo é criar nossa Twitter APP no site do Twitter APPs: https://apps.twitter.com/

Clique em "Criar new APP", logo depois preencha o formulário, até mesmo o campo "Callback URL":

Nos campos que pedem URL, coloque de preferência URLs de websites aos quais você é o administrador, caso não seja de nenhum, coloque URLs de suas contas socias, de preferência a mesma em ambos os campos.

Importante: O campo "Callback URL" mesmo sendo opcional deve ser preenchido, pois caso o campo fique em branco e o usuário de sua APP, por algum motivo, tenha conta no Twitter, porém a APP do Twitter não esteja instalada no device dele, quando ele clicar no Twitter Login Button nada vai acontecer, nem mesmo o WebView que deveria ser aberto aparecerá. Logo, fornecer um conteúdo para esse campo, em nosso caso de APP mobile, é fundamental.

No final desse formulário de criação de Twitter APP marque o check "Yes, I agree" e clique em "Create your Twitter application".

Você será encaminhado para a página de sua Twitter APP recém criada. Nessa página clique na aba "Keys and access tokens" e então você terá acesso as chaves API Key e API Secret que serão necessárias em configurações posteriores nesse post:

Nosso próximo passo é no Firebase dashboard. Acesse sua conta e em seguida sua base no Firebase. No menu esquerdo clique em "Login & Auth", logo depois clique na aba "Twitter". Então marque o check "Enable Twitter Authentication" e preencha ambos os campos "Twitter API Key" e "Twitter API Secret" com as respectivas chaves na página de sua Twitter APP: "API Key" e "API Secret":

Feito isso precisamos agora iniciar a configuração do Twitter Android SDK, para essa tarefa vamos utilizar o plugin Fabric.

O Fabric na verdade é uma ferramenta que nos permite vincular várias SDKs as nossas APPs sem que tenhamos que criar "n" configurações e acessar "n" documentações para isso. Ou seja, o objetivo dele é facilitar ainda mais as coisas para nós developers.

Nosso primeiro passo com o Fabric é acessar o site dele: https://get.fabric.io/ clicar em "Get Started with Fabric" então criar uma conta preechendo o formulário de sign-up:

Depois do cadastro você receberá um email de confirmação, acesse seu email e clique no link de confirmação.

Nosso próximo passo com o Fabric é instalar o plugin dele em nosso IDE AndroidStudio (AS). Acesse seu projeto no AS e logo depois clique em "Preferences":

Em seguida clique em "Plugin", logo depois em "Browse repositories..." e então na box que será aberta, no campo de busca digite "Fabric":

Na imagem acima, devido a estarmos utilizando uma instalação do AS que já tem o plugin Fabric configurado, não foi apresentado o botão de instalação, mas com você terá um, logo abaixo do nome do plugin, com o label "Install". Clique nele.

Depois de realizado o download vai aparecer a opção para reiniciar o AS, essa opção vai vir no lugar do botão "Install". Clique nesse botão de reinicio e então o plugin estará disponível em sua instalação do AS:

Nosso próximo passo é logar no Fabric plugin no AS, caso necessário. No AS, nas abas laterais direitas, click em Fabric, logo depois, se aparecer o button com o simbolo que indica "Ligar", clique nesse símbolo:

Caso apareça uma área como a imagem abaixo, clique em "Next":

E então nosso primeiro alvo é apresentado, a área de possíveis SDKs a serem vinculadas ao nosso projeto via Fabric plugin. Em nosso caso queremos somente a SDK do Twitter:

Clique na linha do Twitter e então devemos ir para a área indicada pela imagem abaixo, nessa área clique em "Install":

Em seguida marque o check informando que você está de acordo com os "Twitter Kit Agreement" e "Developer Agreement" e então clique em "I already have a Twitter account".

Na área seguinte coloque as chaves de sua Twitter APP como fez no dashboard do Firebase, primeiro a API Key depois a API Secret, então clique em "Next":

Na tela seguinte apenas clique em "Apply" e aguarde a configuração ser colocada por completo em sua APP:

Finalizado o processo seu projeto deve ter tido algumas entidades atualizadas (AndroidManifest.xml, build.gradle (app level) e sua sub-classe de Application). A tela que volta a aparecer é a que tem a opção "Log In with Twitter". Você poderia nessa tela escolher alguma funcionalidade do Twitter disponivel para então seguir a dica de código deles para implementar, mas aqui, seguindo os objetivos da série, vou lhe guiar no código que deve ser colocado em nosso projeto de Chat.

No arquivo content_login.xml, logo abaixo do XML do Google Login Button coloque o XML de nosso Twitter Login Button customizado:

...
<Button
android:onClick="sendLoginTwitterData"
android:id="@+id/email_sign_in_twitter_button"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/action_sign_in_twitter"
android:textStyle="bold" />
...

 

Em nosso /res/values/strings.xml adcionamos a seguinte tag xml:

<resources>
...
<string name="action_sign_in_twitter">Sign in com Twitter</string>
...
</resources>

 

Em nossa LoginActivity vamos criar uma variável de instância do tipo TwitterAuthClient e logo depois inicializá-la no onCreate(), logo abaixo das configurações da variável de instância mGoogleApiClient:

public class LoginActivity extends CommonActivity
implements GoogleApiClient.OnConnectionFailedListener {
...
private TwitterAuthClient twitterAuthClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
...
/* TWITTER */
twitterAuthClient = new TwitterAuthClient();

firebase = LibraryClass.getFirebase();
initViews();
verifyUserLogged();
}
...
}

 

Nosso próximo passo é atualizar nosso método onActivityResult() para que seja possível obter do Twitter screen a resposta do usuário quanto ao login (aceito ou não):

...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if( requestCode == RC_SIGN_IN_GOOGLE
&& resultCode == RESULT_OK ){

GoogleSignInResult googleSignInResult = Auth.GoogleSignInApi.getSignInResultFromIntent( data );
GoogleSignInAccount account = googleSignInResult.getSignInAccount();
syncGoogleSignInToken( account );
}
else{
twitterAuthClient.onActivityResult( requestCode, resultCode, data );
callbackManager.onActivityResult( requestCode, resultCode, data );
}
}
...

 

No código acima optei por deixá-lo por completo, pois a configuração é essa mesmo, tanto o cliente Facebook (callbackManager) quanto o cliente Twitter (twitterAuthClient) têm métodos onActivityResult() que não disparam exceptions caso não seja a SDK de um ou de outro em uso.

Recapitulando posts anteriores da série, temos os métodos accessFacebookLoginData() e accessGoogleLoginData() que nos permitem, de forma simples, acessar o método accessLoginData() que tem a vinculação desses métodos de login com o Firebase.

De forma simples? Sim, pois ambos apenas precisam fornecer o provider e a string de token. Porém com o Twitter temos de prover além do provider e token os dados token secret e id do usuário no Twitter, ou seja, a chamada a accessLoginData() para o Twitter login deverá ter quatro argumentos.

Como resolvemos isso sem modificar as chamadas ao método accessLoginData() já sendo realizadas nos méotodos accessFacebookLoginData() e accessGoogleLoginData()?

Vamos utilizar uma sintaxe de array em Java chamada "varargs" que nos permite fornecer zero ou vários dados como argumento de nossos métodos que têm essa sintaxe de array como parâmetro. Note que esse parâmetro sempre tem que estar por último na lista de parâmetros do método.

Para um estudo mais detalhado sobre o varargs acesse o link a seguir: http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html#varargs

Sabendo disso, temos que modificar nosso accessLoginData() para receber, em nosso caso, uma ou três strings como sendo os últimos argumentos da chamada a esse método:

...
private void accessLoginData( String provider, String... tokens ){
if( tokens != null ){

firebase.authWithOAuthToken(
provider,
tokens[0],
new Firebase.AuthResultHandler() {
@Override
public void onAuthenticated(AuthData authData) {
user.saveTokenSP( LoginActivity.this, authData.getToken() );
user.saveIdSP( LoginActivity.this, authData.getUid() );
user.setId( authData.getUid() );
user.setName( authData.getProviderData().get("displayName").toString() );
user.setEmail( authData.getProviderData().get("email").toString() );
user.saveDB();

callMainActivity();
}

@Override
public void onAuthenticationError(FirebaseError firebaseError) {
showSnackbar( firebaseError.getMessage() );
}
}
);
}
else{
firebase.unauth();
}
}
...

 

E agora podemos definir nosso método accessTwitterLoginData():

...
private void accessTwitterLoginData(String token, String secret, String id){
accessLoginData(
"twitter",
token,
secret,
id
);
}
...

Esse método, accessTwitterLoginData(), deverá ser invocado dentro do método sendLoginTwitterData() que já setamos como callback do listener de clique do Twitter Login Button, lembra? No content_login.xml. Posteriormente vamos chegar a definição desse método.

Antes temos um grande problema a ser resolvido.

O método do Firebase authWithOAuthToken() é utilizado pelos logins do Facebook e Google com a versão (ou sobrecarga) que aceita um token (String) como sendo o segundo argumento. O Twitter precisa utilizar a versão que tem um options (Map<String, String>) como segundo argumento.

Vamos começar isolando partes que não vão ser modificadas e que se forem encapsuladas não danificarão o código (e assim vamos evitar código repetido). O código que não muda e podemos encapsular sem problemas é a instância anônima "new Firebase.AuthResultHandler()" que é o terceiro parâmetro nas duas versões do método discutido anteriormente. Logo temos o novo método:

...
private Firebase.AuthResultHandler getFirebaseAuthResultHandler(){
Firebase.AuthResultHandler callback = new Firebase.AuthResultHandler() {
@Override
public void onAuthenticated(AuthData authData) {
user.saveTokenSP( LoginActivity.this, authData.getToken() );
user.saveIdSP( LoginActivity.this, authData.getUid() );
user.setId( authData.getUid() );
user.setName( authData.getProviderData().get("displayName").toString() );
user.setEmail( authData.getProviderData().get("email").toString() );
user.saveDB();

callMainActivity();
}

@Override
public void onAuthenticationError(FirebaseError firebaseError) {
showSnackbar( firebaseError.getMessage() );
}
};

return( callback );
}
...

 

O retorno é a instância que precisamos como terceiro argumento. Agora precisamos identificar quando chamar a versão de authWithOAuthToken() que requer um token String como segundo argumento e quando chamar a outra versão que requer um Map<String, String>.

Note que quando for uma invocação vinda de accessGoogleLoginData() ou accessFacebookLoginData() teremos apenas uma String (que pode ser null) sendo fornecida como parte do parâmetro varargs, no caso do accessTwitterLoginData() serão sempre três strings nesse parâmetro.

Logo podemos utilizar o tamanho do array como validador de qual versão do método authWithOAuthToken() invocar. Vamos aproveitar e já atualizar o condicional que nos permite acessar ou não o método authWithOAuthToken() indepedente da versão:

...
private void accessLoginData( String provider, String... tokens ){
if( tokens != null
&& tokens.length > 0
&& tokens[1] != null ){

if( tokens.length == 1 ){
firebase.authWithOAuthToken(
provider,
tokens[0],
getFirebaseAuthResultHandler()
);
}
else{
Map<String, String> options = new HashMap<>();
options.put("oauth_token", tokens[0]);
options.put("oauth_token_secret", tokens[1]);
options.put("user_id", tokens[2]);

firebase.authWithOAuthToken(
provider,
options,
getFirebaseAuthResultHandler()
);
}
}
else{
firebase.unauth();
}
}
...

 

Definida a nova versão de accessLoginData() podemos seguir para a definição de sendLoginTwitterData():

...
public void sendLoginTwitterData( View view ){

twitterAuthClient.authorize(
this,
new Callback<TwitterSession>() {
@Override
public void success(Result<TwitterSession> result) {

TwitterSession session = result.data;

accessTwitterLoginData(
session.getAuthToken().token,
session.getAuthToken().secret,
String.valueOf( session.getUserId() )
);
}
@Override
public void failure(TwitterException exception) {
showSnackbar( exception.getMessage() );
}
}
);
}
...

 

Antes de realizar o primeiro teste, quero lhe informar que se seu objetivo era apenas obter o login do Twitter em sua APP, apenas remova a chamada ao método accessTwitterLoginData() e você enfim conseguiu atingi-lo.

Para você que está seguindo a série, ainda temos algumas coisas para atualizar. Lembra que quando utilizando login social temos uma versão personalizada de menu, uma versão com somente a opção de Logout?!

Pois bem, essa verificação em MainActivity já está pronta, como acompanhado em posts anteriores da série, mas para atender também ao Twitter Login (login social) temos de acrescentar a verificação ao "twitter", prefixo de id, no método isSocialNetworkLogged() da classe User:

public class User {
...
public boolean isSocialNetworkLogged( Context context ){
retrieveIdSP( context );
return(
this.id.contains("facebook")
|| this.id.contains("google")
|| this.id.contains("twitter")
);
}
...
}

 

Agora vamos corrigir um bug que até o post anterior estava sendo tratado como solução. Isso mesmo!

Os algoritmos para logout além do algoritmo de logout do Firebase. Esses algoritmos extras (Facebook e Google) que estão na MainActivity, podem ser seguramente removidos, os métodos que tinham eles agora ficam:

public class MainActivity extends AppCompatActivity
implements GoogleApiClient.OnConnectionFailedListener {
...

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

authStateListener = new Firebase.AuthStateListener() {
@Override
public void onAuthStateChanged(AuthData authData) {
if( authData == null ){
Intent intent = new Intent( MainActivity.this, LoginActivity.class );
startActivity( intent );
finish();
}
}
};

firebase = LibraryClass.getFirebase().child("users");
firebase.addAuthStateListener( authStateListener );
}

...

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();

if(id == R.id.action_update){
startActivity(new Intent(this, UpdateActivity.class));
}
else if(id == R.id.action_update_login){
startActivity(new Intent(this, UpdateLoginActivity.class));
}
else if(id == R.id.action_update_password){
startActivity(new Intent(this, UpdatePasswordActivity.class));
}
else if(id == R.id.action_remove_user){
startActivity(new Intent(this, RemoveUserActivity.class));
}
else if(id == R.id.action_logout){
firebase.unauth();
finish();
}
return super.onOptionsItemSelected(item);
}
...
}

 

Por que essa remoção? Porque o firebase.unauth() foi também construído para lidar com essa funcionalidade de logout dos logins sociais.

Para finalizar vamos atualizar o arquivo XML activity_login.xml. Por que? Devido a quantidade de views em content_login.xml temos de permitir que a tela tenha um scroll (ScrollView):

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoginActivity"
android:fillViewport="true">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/logo"
android:layout_marginTop="160dp"
android:layout_marginBottom="30dp"
android:gravity="center"
android:scaleType="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/firebase_chat"/>

<include
layout="@layout/content_login" />

</RelativeLayout>
</ScrollView>

 

Agora podemos rodar a APP no AVD, obtendo o seguinte resultado na LoginActivity:

Quando clicando em "SIGN IN COM TWITTER" temos:

Note que minha conta de usuário no Twitter já estava autorizada, com a sua provavelmente terá de informar email e senha.

Autorizada a conexão via Twitter, nosso Firebase dashboard agora tem a versão Twitter de login salva e sendo apresentada:

Com isso finalizamos o login com Twitter no APP de Chat, junto ao Firebase. Para acessar o projeto por completo entre na página dele no GitHub: https://github.com/viniciusthiengo/nosso-chate

O vídeo abaixo está com o conteúdo acima implementado passo a passo:

Fontes:

Firebase: Twitter Authentication

Fabric IO

Twitter Developer APPs

Vlw

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

100 Graus100 GrausLivros
Refatoração de Código: Mover Acumulação Para Parâmetro ColetorRefatoração de Código: Mover Acumulação Para Parâmetro ColetorAndroid
Design ThinkingDesign ThinkingLivros
Refatoração de Código: Limitar Instanciação Com SingletonRefatoração de Código: Limitar Instanciação Com SingletonAndroid

Compartilhar

Comentários Facebook

Comentários Blog

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...