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

CategoriasAndroid, Design, Protótipo
AutorVinÃcius Thiengo
VÃdeo aulas186
Tempo15 horas
ExercÃciosSim
CertificadoSim

CategoriaEngenharia de Software
Autor(es)Eric Evans
EditoraAlta Books
Edição3ª
Ano2016
Páginas528
Opa, blz?
Nesse post seguimos com a série Firebase no Android, mais precisamente com nossa APP de chat.
Dessa vez vamos abordar as funcionalidades padrões que ainda não colocamos na APP, são elas: atualização de email de login (UpdateLoginActivity), atualização de senha (UpdatePasswordActivity) e remoção de conta de usuário (RemoveUserActivity).
Todas as funcionalidades descritas são simples, porém cada uma tem seus próprios passos para execução, não há um meio de executá-las em uma só chamada a algum método do Firebase, logo foi escolhido manter cada funcionalidade em sua própria Activity.
Antes de iniciar, abaixo seguem os posts anteriores dessa série:
Atualização de Dados, Firebase Android - Parte 3
Eventos de Leitura e Firebase UI Android - Parte 2
Persistência Com Firebase Android - Parte 1
No decorrer do post vamos construindo o conteúdo da APP para que tenhamos as funcionalidades descritas anteriormente. Note que o projeto completo se encontra no GitHub: https://github.com/viniciusthiengo/nosso-chate
Nosso primeiro passo é definir todas as novas activities em nosso AndroidManifest.xml, segue código:
<?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">
<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=".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"/>
</application>
</manifest>
Agora vamos para os códigos das novas activities, começando pela activity UpdateLoginActivity:
package br.com.thiengo.thiengocalopsitafbexample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.Toast;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import br.com.thiengo.thiengocalopsitafbexample.domain.User;
import br.com.thiengo.thiengocalopsitafbexample.domain.util.LibraryClass;
public class UpdateLoginActivity extends AppCompatActivity implements ValueEventListener {
private Toolbar toolbar;
private User user;
private AutoCompleteTextView newEmail;
private EditText password;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_login);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
@Override
protected void onResume() {
super.onResume();
init();
}
private void init(){
toolbar.setTitle( getResources().getString(R.string.update_login) );
newEmail = (AutoCompleteTextView) findViewById(R.id.email);
password = (EditText) findViewById(R.id.password);
user = new User();
user.contextDataDB( this );
}
public void update( View view ){
user.setPassword( password.getText().toString() );
user.generateCryptPassword();
Firebase firebase = LibraryClass.getFirebase();
firebase.changeEmail(
user.getEmail(),
user.getPassword(),
newEmail.getText().toString(),
new Firebase.ResultHandler() {
@Override
public void onSuccess() {
user.setEmail( newEmail.getText().toString() );
user.updateDB();
Toast.makeText(
UpdateLoginActivity.this,
"Email de login atualizado com sucesso",
Toast.LENGTH_SHORT
).show();
}
@Override
public void onError(FirebaseError firebaseError) {
Toast.makeText(
UpdateLoginActivity.this,
firebaseError.getMessage(),
Toast.LENGTH_SHORT
).show();
}
});
}
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User u = dataSnapshot.getValue( User.class );
newEmail.setText( u.getEmail() );
user.setEmail( u.getEmail() );
}
@Override
public void onCancelled(FirebaseError firebaseError) {}
}
Note que o código é bem similar ao código da activity do post anterior, a UpdateActivity. A diferença fica com a view que estamos utilizando, agora é newEmail e não name. A EditText de password, pois devido ser a atualização de um dado crítico é necessário informar a senha também. Além de o método de atualização ser o changeEmail() ao invés de updateChildren().
Note que em onDataChange() estamos acessando o email e o colocando também em user.setEmail(), caminho diferente da lógica utilizada na activity UpdateActivity, onde não colocamos o conteúdo name em user.setName(). Por que isso? Porque no método changeEmail() temos de entrar com: email atual, senha atual, novo email e callback de resposta. Dessa forma o que nos resta é acessar diretamente em newEmail o conteúdo do novo email.
Fique atento ao código dentro de onSuccess() em changeEmail(), pois temos também de atualizar o nodo do usuário atual, digo, o nodo no Firebase, alterar o email para ficar idêntico ao de login. Veja que antes de realizar a chamada a user.updateDB() colocamos o novo email em user e não há necessidade de chamar o método user.retrieveIdSP(), pois na chamada user.contextDataDB() em init() esse id já é recuperado.
Feito isso agora temos os layouts referentes a UpdateLoginActivity. São layouts eles: activity_update_login.xml e content_update_login.xml. Começamos pelo activity_update_login.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.UpdateLoginActivity">
<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_update_login" />
</android.support.design.widget.CoordinatorLayout>
Agora prosseguimos com o layout de conteúdo, content_update_login.xml:
<?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.UpdateLoginActivity"
tools:showIn="@layout/activity_update_login">
<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>
<View
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:id="@+id/v_line"
android:layout_below="@+id/til_email"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#999"/>
<TextView
android:padding="5dp"
android:background="#ffc"
android:layout_marginRight="4dp"
android:layout_marginLeft="4dp"
android:id="@+id/tv_info"
android:layout_below="@+id/v_line"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/password_info"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/til_password"
android:layout_below="@+id/tv_info"
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/sign_up"
android:imeActionLabel="@string/action_sign_up_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/bt_logout"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:onClick="update"
android:gravity="center"
android:text="@string/update_login"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
</ScrollView>
Note que já estamos com o ScrollView, na content_update.xml da Activity UpdateActivity também realizamos essa atualização. Por que? Para evitarmos problemas de rolagem de tela quando o device estiver em modo landscape.
Quando chegar a hora de rodar a APP essas definições de layout terão um resultado similar a imagem abaixo:
Nosso próximo passo é a activity UpdatePasswordActivity, segue código:
package br.com.thiengo.thiengocalopsitafbexample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import br.com.thiengo.thiengocalopsitafbexample.domain.User;
import br.com.thiengo.thiengocalopsitafbexample.domain.util.LibraryClass;
public class UpdatePasswordActivity extends AppCompatActivity implements ValueEventListener {
private Toolbar toolbar;
private User user;
private EditText newPassword;
private EditText password;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_password);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
@Override
protected void onResume() {
super.onResume();
init();
}
private void init(){
toolbar.setTitle( getResources().getString(R.string.update_password) );
newPassword = (EditText) findViewById(R.id.new_password);
password = (EditText) findViewById(R.id.password);
user = new User();
user.contextDataDB( this );
}
public void update( View view ){
user.setNewPassword( newPassword.getText().toString() );
user.generateCryptNewPassword();
user.setPassword( password.getText().toString() );
user.generateCryptPassword();
Firebase firebase = LibraryClass.getFirebase();
firebase.changePassword(
user.getEmail(),
user.getPassword(),
user.getNewPassword(),
new Firebase.ResultHandler() {
@Override
public void onSuccess() {
Toast.makeText(
UpdatePasswordActivity.this,
"Senha atualizada com sucesso",
Toast.LENGTH_SHORT
).show();
}
@Override
public void onError(FirebaseError firebaseError) {
Toast.makeText(
UpdatePasswordActivity.this,
firebaseError.getMessage(),
Toast.LENGTH_SHORT
).show();
}
}
);
}
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User u = dataSnapshot.getValue( User.class );
user.setEmail( u.getEmail() );
}
@Override
public void onCancelled(FirebaseError firebaseError) {}
}
Código muito similar ao anterior, tendo agora o acesso ao EditText newPassword ao invés do AutoCompleteTextView newEmail de UpdateloginActivity. Note que ainda em onDataChange() estamos obtendo o email atual de cadastrado, pois o método changePassword() precisa que o email de login também seja fornecido.
O resultado, quando positivo, aqui é bem mais simples, pois não precisamos atualizar nada na base Firebase utilizando o método updateDB() de user.
A classe User agora tem os mesmos métodos de password replicados para newPassword:
@JsonIgnoreProperties({"id", "password", "newPassword"})
public class User {
...
private String newPassword;
...
public String getNewPassword() {
return newPassword;
}
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
public void generateCryptNewPassword() {
newPassword = CryptWithMD5.cryptWithMD5(newPassword);
}
...
}
Note que em @JsonIgnoreProperties() adicionamos newPassword para que o parse Firebase não gere uma Exception.
Agora seguimos com os layouts de UpdatePasswordActivity, activity_update_password.xml e content_update_password.xml. Começando pelo activity_update_password.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.UpdatePasswordActivity">
<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_update_password" />
</android.support.design.widget.CoordinatorLayout>
E então o código xml de content_update_password.xml:
<?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.UpdatePasswordActivity"
tools:showIn="@layout/activity_update_password">
<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_new_password"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/new_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_new_password"
android:imeActionId="@+id/sign_up"
android:imeActionLabel="@string/action_sign_up_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<View
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:id="@+id/v_line"
android:layout_below="@+id/til_new_password"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#999"/>
<TextView
android:padding="5dp"
android:background="#ffc"
android:layout_marginRight="4dp"
android:layout_marginLeft="4dp"
android:id="@+id/tv_info"
android:layout_below="@+id/v_line"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/password_info"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/til_password"
android:layout_below="@+id/tv_info"
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/sign_up"
android:imeActionLabel="@string/action_sign_up_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/bt_logout"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:onClick="update"
android:gravity="center"
android:text="@string/update_password"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
</ScrollView>
No momento de rodar a APP essas definições de layout para UpdatePasswordActivity terão um resultado similar a:
Agora podemos seguir com o código de RemoveUserActivity:
package br.com.thiengo.thiengocalopsitafbexample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import br.com.thiengo.thiengocalopsitafbexample.domain.User;
import br.com.thiengo.thiengocalopsitafbexample.domain.util.LibraryClass;
public class RemoveUserActivity extends AppCompatActivity implements ValueEventListener {
private Toolbar toolbar;
private User user;
private EditText password;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_remove_user);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
@Override
protected void onResume() {
super.onResume();
init();
}
private void init(){
toolbar.setTitle( getResources().getString(R.string.remove_user) );
password = (EditText) findViewById(R.id.password);
user = new User();
user.contextDataDB( this );
}
public void update( View view ){
user.setPassword( password.getText().toString() );
user.generateCryptPassword();
Firebase firebase = LibraryClass.getFirebase();
firebase.removeUser(
user.getEmail(),
user.getPassword(),
new Firebase.ResultHandler() {
@Override
public void onSuccess() {
user.retrieveIdSP( RemoveUserActivity.this );
user.removeDB();
Toast.makeText(
RemoveUserActivity.this,
"Conta removida com sucesso",
Toast.LENGTH_SHORT
).show();
finish();
}
@Override
public void onError(FirebaseError firebaseError) {
Toast.makeText(
RemoveUserActivity.this,
firebaseError.getMessage(),
Toast.LENGTH_SHORT
).show();
}
}
);
}
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User u = dataSnapshot.getValue( User.class );
user.setEmail( u.getEmail() );
}
@Override
public void onCancelled(FirebaseError firebaseError) {}
}
Note que ainda mantemos o código user.setEmail( u.getEmail() ) em onDataChange(), pois o método removeUser() precisa dos dados de login.
A chamada a user.removeDB() é necessária, pois o que o método removeUser() vai fazer é apenas remover os dados de autenticação do usuário, na base Firebase ainda vai permanecer os dados dele, logo o método removeDB() remove o restante. Abaixo o código de removeDB() em User:
public class User {
...
public void removeDB(){
Firebase firebase = LibraryClass.getFirebase().child("users").child( getId() );
firebase.setValue(null);
}
...
}
Agora podemos seguir com os layouts de RemoveUserActivity, activity_remove_user.xml e content_remove_user.xml. Começando por activity_remove_user.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.RemoveUserActivity">
<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_remove_user" />
</android.support.design.widget.CoordinatorLayout>
E então content_remove_user.xml:
<?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.RemoveUserActivity"
tools:showIn="@layout/activity_remove_user">
<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">
<TextView
android:padding="5dp"
android:background="#ffc"
android:layout_marginRight="4dp"
android:layout_marginLeft="4dp"
android:id="@+id/tv_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/password_info"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/til_password"
android:layout_below="@+id/tv_info"
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/sign_up"
android:imeActionLabel="@string/action_sign_up_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/bt_logout"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:onClick="update"
android:gravity="center"
android:text="@string/remove_user"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
</ScrollView>
Na execução da APP teremos como resultado das definições de layout de RemoveUserLayout algo similar a imagem abaixo:
Os próximos passos envolvem a MainActivity e o arquivo res/var/strings.xml. Começando pelo strings.xml, adicione as seguintes tags:
<resources>
...
<string name="prompt_new_password">Nova senha</string>
<string name="update_profile">Atualizar profile</string>
<string name="update_login">Atualizar login</string>
<string name="update_password">Atualizar senha</string>
<string name="remove_user">Remover conta</string>
<string name="title_activity_update_login">UpdateLoginActivity</string>
<string name="title_activity_update_password">UpdatePasswordActivity</string>
<string name="title_activity_remove_user">RemoveUserActivity</string>
<string name="password_info">Para prosseguir com a atualização informe abaixo sua senha.</string>
</resources>
Agora em res/menu/menu.xml em MainActivity temos o seguinte xml:
<?xml version="1.0" encoding="utf-8"?>
<menu 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"
tools:context=".MainActivity">
<item
android:id="@+id/action_update"
android:orderInCategory="100"
android:title="@string/update_profile"
app:showAsAction="never" />
<item
android:id="@+id/action_update_login"
android:orderInCategory="100"
android:title="@string/update_login"
app:showAsAction="never" />
<item
android:id="@+id/action_update_password"
android:orderInCategory="100"
android:title="@string/update_password"
app:showAsAction="never" />
<item
android:id="@+id/action_remove_user"
android:orderInCategory="100"
android:title="@string/remove_user"
app:showAsAction="never" />
<item
android:id="@+id/action_logout"
android:orderInCategory="100"
android:title="@string/logout"
app:showAsAction="never" />
</menu>
Com isso podemos iniciar as atualizações na MainActivity, começando pelo método onOptionsItemSelected() onde teremos alguns outros condicionais para nossas novas activities:
public class MainActivity extends AppCompatActivity {
...
@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();
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
finish();
}
return super.onOptionsItemSelected(item);
}
}
Com isso temos o seguinte menu em MainActivity:
Note que em RemoveUserActivity, mais precisamente no método removeUser(), o único finish() não é o suficiente para voltar o usuário para a tela de login caso ele remova a conta, ainda precisamos saber no código se ele permanece ou não conectado para que seja possível envia-lo ou não a tela de login (LoginActivity).
O que devemos fazer é adicionar uma instancia de uma classe que implemente a interface AuthStateListener, logo podemos utilizar Firebase.AuthStateListener. Segue código da MainActivity atualizado:
public class MainActivity extends AppCompatActivity {
...
private Firebase.AuthStateListener authStateListener;
@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
protected void onDestroy() {
super.onDestroy();
adapter.cleanup();
firebase.removeAuthStateListener( authStateListener );
}
...
}
Se em onAuthStateChanged() o valor de authData for igual a null podemos seguramente enviar o usuário para a tela de login, pois ele não mais está conectado.
Com isso terminamos a atualização para termos as funcionalidades de: atualização de email de login, de password e remoção de conta.
O projeto completo pode ser encontrado no GitHub: https://github.com/viniciusthiengo/nosso-chate
O vídeo abaixo tem a implementação completa do código acima, passo a passo.
Fonte:
Email & Password Authentication
Vlw
Comentários Facebook