Recuperação de Senha, Firebase Atualizado - Parte 8

Receba em primeira mão, e com prioridade, os conteúdos Android exclusivos do Blog. Você receberá um email de confirmação. Somente depois de confirma-lo é que poderei lhe enviar os conteúdos exclusivos.

Email inválido.
Blog /Android /Recuperação de Senha, Firebase Atualizado - Parte 8

Recuperação de Senha, Firebase Atualizado - Parte 8

Vinícius Thiengo
(3325) (7)
Go-ahead
"Você tem sonhos, então a vida bate em você para saber: 'você realmente quer isso?'"
Eric Thomas
Kotlin Android
Capa do livro Desenvolvedor Kotlin Android - Bibliotecas para o dia a dia
TítuloDesenvolvedor Kotlin Android - Bibliotecas para o dia a dia
CategoriasAndroid, Kotlin
AutorVinícius Thiengo
Edição
Capítulos19
Páginas1035
Acessar Livro
Treinamento Oficial
Android: Prototipagem Profissional de Aplicativos
CursoAndroid: Prototipagem Profissional de Aplicativos
CategoriaAndroid
InstrutorVinícius Thiengo
NívelTodos os níveis
Vídeo aulas186
PlataformaUdemy
Acessar Curso
Receitas Android
Capa do livro Receitas Para Desenvolvedores Android
TítuloReceitas Para Desenvolvedores Android
CategoriaDesenvolvimento Android
AutorVinícius Thiengo
Edição
Ano2017
Capítulos20
Páginas936
Acessar Livro
Código Limpo
Capa do livro Refatorando Para Programas Limpos
TítuloRefatorando Para Programas Limpos
CategoriaEngenharia de Software
AutorVinícius Thiengo
Edição
Ano2017
Capítulos46
Páginas599
Acessar Livro
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Conteúdo Exclusivo
Receba em primeira mão, e com prioridade, os conteúdos Android exclusivos do Blog.
Email inválido

Opa, blz?

Nesse post continuamos com a série Firebase Android, porém já com a versão atualizada do Firebase, versão que foi anunciada no Google I/O 2016.

Nesse post falamos um pouco das vantagens de definitivamente utilizar o Firebase como parte de seu arsenal no dev Android (IOS e Web também) e para não deixar nosso código parado acrescentamos uma simples funcionalidade, recuperação de acesso, útil caso o usuário tenha utilizado o método convencional de acesso a área restrita, email e senha.

Antes de prosseguir, você tem acesso ao passo a passo de migração do Firebase acessando o link: Migração Firebase Android

Para acesso ao conteúdo de nosso APP da série, atualizado, entre no GitHub: https://github.com/viniciusthiengo/nosso-chate

Obs. : O vídeo com o conteúdo dessa postagem passo a passo está no final do post.

Agora um pouco da importância de passar a utilizar o Firebase no dev, principalmente Android (em nosso caso). Com aproximadamente 3 anos de blog e nele falando mais sobre Android, recebo muitas mensagens de contato sobre problemas e ideias.

O que percebo nas mensagens?

Muitos developers Android não têm habilidades no lado remoto da aplicação, ou seja, no backend Web. No Backend Web? Isso, para trabalhar com push message (GCM), banco de dados remoto (MySQL, por exemplo) e principalmente a linguagem de programação no backend (PH, Java, Python, ...).

Ok, mas qual a finalidade de falar sobre essa limitação de alguns developers Andrdoid?

Na verdade a finalidade está em incentivar o estudo e uso mais aprofundado do Firebase, pois ele acaba com essa dependência do developer Android quanto ao backend Web.

O backend remoto vai continuar existindo, porém tudo controlado diretamente da APP, sem necessidade de configuração de servidor Apache, banco de dados relacional (outro grande gargalo quando a APP começa a crescer), lógica de programação com linguagem backend, gastos extras com escalabilidade de servidores remotos, ...

Sem sombra de dúvidas com a atualização do Firebase cobrindo partes que ainda nos forçavam a utilizar um backend remoto configurado por nós, o número de APPs com maior qualidade e com funcionalidades vistas antes somente em grandes APPs tende a aumentar.

O conteúdo do Firebase é tranquilo, diferente da migração ListView => RecyclerView, o conteúdo é simples e o controle complexo (quando conectado ou não a Internet, upload de mídia, funcionamento também quando offline, ...) da APP fica todo com o Firebase.

Então como dica: estude-o o quanto antes e a fundo, suas ideias de APPs, Startups, projetos científicos, ... tendem a aumentar em número e qualidade.

E sobre as versões pagas?

Se for necessário o uso de um plano pago isso pode ser um bom sinal, indica que sua APP está crescendo em número de usuários, por exemplo.

Algo que vale ressaltar é a possibilidade de utilizar o File Storage também na versão gratuita para armazenar todo o conteúdo binário (imagens, vídeos, audios, arquivos em geral). Com um acesso mais simples a um servidor de conteúdo estático não precisamos quebrar a cabeça mesclando a configuração do Firebase junto a configuração de um AWS S3, por exemplo.

Segue link dos posts já liberados dessa série:

Twitter Login (Fabric), Firebase Android - Parte 7

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

 

Funcionalidade: Recuperação de Acesso

Agora podemos prosseguir com a adição da funcionalidade de recuperação de acesso.

Nosso primeiro passo é criar uma nova Activity, a ResetActivity:

public class ResetActivity extends AppCompatActivity {

private Toolbar toolbar;
private AutoCompleteTextView email;

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

toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}

@Override
protected void onResume() {
super.onResume();
init();
}

private void init(){
toolbar.setTitle( getResources().getString(R.string.reset) );
email = (AutoCompleteTextView) findViewById(R.id.email);
}

public void reset( View view ){

}
}

 

O método reset() fica vazio por enquanto, vamos seguir atualizando colocando layout e depois voltamos a ele.

Nosso próximo passo é acresentar um novo layout ao /res/layout de nosso projeto, mais precisamente o activity_reset.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="br.com.thiengo.thiengocalopsitafbexample.ResetActivity">

<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

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

</android.support.design.widget.CoordinatorLayout>

 

O layout de conteúdo, content_reset.xml (referenciado por activity_reset.xml), acrescentamos ao mesmo folder /res/layout:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="br.com.thiengo.thiengocalopsitafbexample.ResetActivity"
tools:showIn="@layout/activity_update">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">

<android.support.design.widget.TextInputLayout
android:id="@+id/til_email"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<AutoCompleteTextView
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_email"
android:inputType="textEmailAddress"
android:maxLines="1"
android:singleLine="true" />

</android.support.design.widget.TextInputLayout>

<Button
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:onClick="reset"
android:gravity="center"
android:text="@string/reset_bt_label"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
</ScrollView>

 

Veja que no button do layout acima temos o atributo android:onClick="reset", logo podemos voltar a ResetActivity para colocar o conteúdo desse método vinculado ao listener de click desse button.

Como variável de instância adicione a FirebaseAuth firebaseAuth, logo depois a inicialize no onCreate() da Activity:

public class ResetActivity extends AppCompatActivity {

private Toolbar toolbar;
private AutoCompleteTextView email;
private FirebaseAuth firebaseAuth;

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

toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

firebaseAuth = FirebaseAuth.getInstance();
}

...
}

 

Agora podemos colocar somente o código de inicio de recuperação de senha no método reset(), que para facilitar é todo nativo:

...
public void reset( View view ){
firebaseAuth
.sendPasswordResetEmail( email.getText().toString() )
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {

if( task.isSuccessful() ){
email.setText("");
Toast.makeText(
ResetActivity.this,
"Recuperação de acesso iniciada. Email enviado.",
Toast.LENGTH_SHORT
).show();
}
else{
Toast.makeText(
ResetActivity.this,
"Falhou! Tente novamente",
Toast.LENGTH_SHORT
).show();
}
}
});
}
...

 

No código acima poderíamos ter colocado um listener para caso o envio falhe, addOnFailureListener(), mas seguindo os exemplos da nova documentação do Firebase, vamos utilizar o resultado da variável task para isso. Apenas precisamos verificar se foi ou não enviado o e-mail com sucesso. De acordo com isso apresentar a mensagem correta.

Ainda temos de colocar a referência da ResetActivity no AndroidManifest.xml e colocar o código necessário em LoginActivity e content_login.xml para acesso a ela.

Abaixo a atualização do AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.thiengo.thiengocalopsitafbexample">

<uses-permission android:name="android.permission.INTERNET" />
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

<application
android:name=".CustomApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:label="@string/app_name" />

<activity
android:name=".LoginActivity"
android:label="@string/title_activity_login"
android:theme="@style/AppTheme.LoginActionbar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SignUpActivity"
android:label="@string/title_activity_sign_up"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ResetActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".MainActivity" />
<activity
android:name=".UpdateActivity"
android:label="@string/title_activity_update"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".UpdateLoginActivity"
android:label="@string/title_activity_update_login"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".UpdatePasswordActivity"
android:label="@string/title_activity_update_password"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".RemoveUserActivity"
android:label="@string/title_activity_remove_user"
android:theme="@style/AppTheme.NoActionBar"/>
<meta-data
android:name="io.fabric.ApiKey"
android:value="3dc6b3f7c9b49dc77c730868b0ee3ee4530d9966" />
</application>
</manifest>

 

Logo depois a atualização de content_login.xml, mais precisamente a adição de um TextView clicável logo abaixo do EditText de senha (@+id/password) desse layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:layout_below="@+id/logo"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".LoginActivity"
tools:showIn="@layout/activity_login">

<!-- Login progress -->
<ProgressBar
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:id="@+id/login_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:visibility="gone" />

...

<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_password"
android:imeActionId="@+id/login"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />

</android.support.design.widget.TextInputLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="right"
android:onClick="callReset"
android:text="@string/action_reset_call"
android:textColor="#0000ff" />

...
</RelativeLayout>

Veja que nesse TextView com listener de clique temos a referência ao método callReset() que devemos então adicionar a LoginActivity, logo abaixo do método callSignUp():

public class LoginActivity extends CommonActivity implements GoogleApiClient.OnConnectionFailedListener {

...

public void callSignUp(View view){
Intent intent = new Intent( this, SignUpActivity.class );
startActivity(intent);
}

public void callReset(View view){
Intent intent = new Intent( this, ResetActivity.class );
startActivity(intent);
}

...
}

 

Com isso nossa funcionalidade de recuperação de senha já está configurada, como na imagem abaixo:

Clicando em "Recuperar acesso" temos:

 

Realizando o processo (fornecendo email e clicando no botão) recebemos um email similar a:

 

Clicando no link acessamos uma página simples que permite a redefinição de senha:

Por que similar o conteúdo do email?

Porque podemos fornecer nosso próprio conteúdo acessando o novo dashboard do Firebase em: https://console.firebase.google.com.

Clique no projeto e logo depois, na sessão "Develop", clique em "Auth", em seguida clique na aba "MODELOS DE E-MAIL" e então em "Redefinição de senha".

 

Clicando no ícone de lápis você poderá informar o conteúdo do email de recuperação de senha, somente não remova a palavra chave %LINK%, pois esse é o link de acesso a página de redefinição de senha:

 

Lembrando que para acessar o projeto completo, basta acessar o GitHub: https://github.com/viniciusthiengo/nosso-chate

Segue vídeo mostrando o passo a passo do conteúdo acima:

 

Para saber mais sobre as atualizações do Firebase acesse: The Firebase Blog e a Documentação Firebase

Até o próximo vídeo.

Vlw

Receba em primeira mão, e com prioridade, os conteúdos Android exclusivos do Blog.
Email inválido

Relacionado

100 Graus100 GrausLivros
Design ThinkingDesign ThinkingLivros
Refatoração de Código: Limitar Instanciação Com SingletonRefatoração de Código: Limitar Instanciação Com SingletonAndroid
Refatoração de Código: Unificar InterfacesRefatoração de Código: Unificar InterfacesAndroid

Compartilhar

Comentários Facebook

Comentários Blog (7)

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...
Weslly (2) (0)
04/10/2016
Thiengo blz?
Gostaria de saber se os planos pagos do firebase são vínculados a conta ou a cada APP, pois n achei essa informação no site do firebase
Responder
Vinícius Thiengo (0) (0)
05/10/2016
Weslly, blz aqui.
Para mim tb não ficou claro, mas provavelmente são somente vinculados ao cartão de crédito, ou seja, a sua conta no Google. Depois vc poderá utilizar quantas instâncias Firebase achar necessário, se passar do limite gratuito eles cobram de seu cartão.
Responder
Vinicius (1) (0)
25/05/2016
Thiengo, estou tendo problema com a atualização do Faribase. No gradle  quando coloco o compile 'com.google.firebase:firebase-database:9.0.0' e sincronizo ele da erro, olhei a documentação e o projeto do nosso-chate mas não deu muito certo. Como faço para resolver este problema?
Responder
Vinícius Thiengo (1) (0)
26/05/2016
Fala Vinicius, blz?
Qual a mensagem de erro? Se tiver o link de um print seria até melhor. Está utilizando o compile do google-play-service? Quando tive problemas foi com ele. Abraço
Responder
Vinicius (1) (0)
27/05/2016
Thiengo, enviei um e-mail com um print e o passo a passo que fiz para atualizar.
Responder
Vinicius (1) (0)
04/06/2016
Obrigado. Agora está funcionando perfeitamente.
Responder
Vinícius Thiengo (1) (0)
04/06/2016
Show de bola. Abraço
Responder