This is the Part 3 of “Build a Social Media App on Android Studio” tutorial, and we are going to cover the following functionalities in this article:
- We are going to edit our profile data like changing name, changing the password of the user, and changing profile pic.
- Changing password is a very important feature because it may happen that sometimes someone knows our password and in that case, we need to change our password.
- We change our profile pic using selecting an image from the gallery or clicking an image from the camera.
Step By Step Implementation
Step 1: Add dependency to build.gradle (Module: app)
Navigate to the Gradle Scripts > build. gradle(Module: app) and add the below dependency in the dependencies section.
implementation "androidx.recyclerview:recyclerview:1.1.0" implementation 'de.hdodenhof:circleimageview:3.1.0' implementation 'com.github.bumptech.glide:glide:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
Now sync the project from the top right corner option of Sync now.
Step 2: Add read, write and camera permission in the AndroidManifest.xml file
Navigate to the AndroidManifest.xml file and add the below permission for getting read, write and camera permission in the app.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" />
Step 3: Create a new empty activity and name the activity as EditProfilePage
Working with the activity_edit_profile_page.xml file. On this page will be changing the email, name, and profile picture of the user. Navigate to the app > res > layout > activity_edit_profile_page.xml and add the below code to that file. Below is the code for the activity_edit_profile_page.xml file.
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "vertical"
tools:context = ".EditProfilePage" >
< TextView
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_marginTop = "50dp"
android:text = "Edit Profile Data"
android:textAlignment = "center"
android:textColor = "@android:color/black"
android:textSize = "26sp" />
< de.hdodenhof.circleimageview.CircleImageView
android:id = "@+id/setting_profile_image"
android:layout_width = "130dp"
android:layout_height = "130dp"
android:layout_marginStart = "140dp"
android:layout_marginTop = "40dp"
android:src = "@drawable/ic_users" />
< TextView
android:id = "@+id/profilepic"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_marginTop = "20dp"
android:text = "Update Profile Pic"
android:textAlignment = "center"
android:textColor = "@android:color/black"
android:textSize = "20sp" />
< TextView
android:id = "@+id/editname"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_marginTop = "20dp"
android:text = "Update Name"
android:textAlignment = "center"
android:textColor = "@android:color/black"
android:textSize = "20sp" />
< TextView
android:id = "@+id/changepassword"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_marginTop = "20dp"
android:text = "Change Password "
android:textAlignment = "center"
android:textColor = "@android:color/black"
android:textSize = "20sp" />
</ LinearLayout >
|
Step 4: Create a new layout resource file
Go to the app > res > layout > New > Layout Resource File and name the file as dialog_update_password. Navigate to the app > res > layout > dialog_update_password.xml and add the below code to that file. Below is the code for the dialog_update_password.xml file.
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:orientation = "vertical"
android:padding = "20dp" >
< TextView
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:text = "Update Password"
android:textAlignment = "center"
android:textColor = "@color/colorBlack"
android:textSize = "16sp"
android:textStyle = "bold" />
< com.google.android.material.textfield.TextInputLayout
android:id = "@+id/oldpass"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_centerHorizontal = "true"
android:layout_centerVertical = "true"
app:passwordToggleEnabled = "true" >
< EditText
android:id = "@+id/oldpasslog"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:hint = "Old Password"
android:inputType = "textPassword" />
</ com.google.android.material.textfield.TextInputLayout >
< com.google.android.material.textfield.TextInputLayout
android:id = "@+id/newpass"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_below = "@id/oldpasslog"
android:layout_centerHorizontal = "true"
android:layout_centerVertical = "true"
app:passwordToggleEnabled = "true" >
< EditText
android:id = "@+id/newpasslog"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:hint = "New Password"
android:inputType = "textPassword" />
</ com.google.android.material.textfield.TextInputLayout >
< Button
android:id = "@+id/updatepass"
style = "@style/Widget.AppCompat.Button.Colored"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_gravity = "center_horizontal"
android:text = "Update Password" />
</ LinearLayout >
|
Step 5: Working with the EditProfilePage.java file
Go to the EditProfilePage.java file and refer to the following code. Below is the code for the EditProfilePage.java file. Comments are added inside the code to understand the code in more detail.
package com.example.socialmediaapp;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.EmailAuthProvider;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import java.util.HashMap;
public class EditProfilePage extends AppCompatActivity {
private FirebaseAuth firebaseAuth;
FirebaseUser firebaseUser;
FirebaseDatabase firebaseDatabase;
DatabaseReference databaseReference;
StorageReference storageReference;
String storagepath = "Users_Profile_Cover_image/" ;
String uid;
ImageView set;
TextView profilepic, editname, editpassword;
ProgressDialog pd;
private static final int CAMERA_REQUEST = 100 ;
private static final int STORAGE_REQUEST = 200 ;
private static final int IMAGEPICK_GALLERY_REQUEST = 300 ;
private static final int IMAGE_PICKCAMERA_REQUEST = 400 ;
String cameraPermission[];
String storagePermission[];
Uri imageuri;
String profileOrCoverPhoto;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_profile_page);
profilepic = findViewById(R.id.profilepic);
editname = findViewById(R.id.editname);
set = findViewById(R.id.setting_profile_image);
pd = new ProgressDialog( this );
pd.setCanceledOnTouchOutside( false );
editpassword = findViewById(R.id.changepassword);
firebaseAuth = FirebaseAuth.getInstance();
firebaseUser = firebaseAuth.getCurrentUser();
firebaseDatabase = FirebaseDatabase.getInstance();
storageReference = FirebaseStorage.getInstance().getReference();
databaseReference = firebaseDatabase.getReference( "Users" );
cameraPermission = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
storagePermission = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
Query query = databaseReference.orderByChild( "email" ).equalTo(firebaseUser.getEmail());
query.addValueEventListener( new ValueEventListener() {
@Override
public void onDataChange( @NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
String image = "" + dataSnapshot1.child( "image" ).getValue();
try {
Glide.with(EditProfilePage. this ).load(image).into(set);
} catch (Exception e) {
}
}
}
@Override
public void onCancelled( @NonNull DatabaseError databaseError) {
}
});
editpassword.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
pd.setMessage( "Changing Password" );
showPasswordChangeDailog();
}
});
profilepic.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
pd.setMessage( "Updating Profile Picture" );
profileOrCoverPhoto = "image" ;
showImagePicDialog();
}
});
editname.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
pd.setMessage( "Updating Name" );
showNamephoneupdate( "name" );
}
});
}
@Override
protected void onPause() {
super .onPause();
Query query = databaseReference.orderByChild( "email" ).equalTo(firebaseUser.getEmail());
query.addValueEventListener( new ValueEventListener() {
@Override
public void onDataChange( @NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
String image = "" + dataSnapshot1.child( "image" ).getValue();
try {
Glide.with(EditProfilePage. this ).load(image).into(set);
} catch (Exception e) {
}
}
}
@Override
public void onCancelled( @NonNull DatabaseError databaseError) {
}
});
editpassword.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
pd.setMessage( "Changing Password" );
showPasswordChangeDailog();
}
});
}
@Override
protected void onStart() {
super .onStart();
Query query = databaseReference.orderByChild( "email" ).equalTo(firebaseUser.getEmail());
query.addValueEventListener( new ValueEventListener() {
@Override
public void onDataChange( @NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
String image = "" + dataSnapshot1.child( "image" ).getValue();
try {
Glide.with(EditProfilePage. this ).load(image).into(set);
} catch (Exception e) {
}
}
}
@Override
public void onCancelled( @NonNull DatabaseError databaseError) {
}
});
editpassword.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
pd.setMessage( "Changing Password" );
showPasswordChangeDailog();
}
});
}
// checking storage permission ,if given then we can add something in our storage
private Boolean checkStoragePermission() {
boolean result = ContextCompat.checkSelfPermission( this , Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED);
return result;
}
// requesting for storage permission
private void requestStoragePermission() {
requestPermissions(storagePermission, STORAGE_REQUEST);
}
// checking camera permission ,if given then we can click image using our camera
private Boolean checkCameraPermission() {
boolean result = ContextCompat.checkSelfPermission( this , Manifest.permission.CAMERA) == (PackageManager.PERMISSION_GRANTED);
boolean result1 = ContextCompat.checkSelfPermission( this , Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED);
return result && result1;
}
// requesting for camera permission if not given
private void requestCameraPermission() {
requestPermissions(cameraPermission, CAMERA_REQUEST);
}
// We will show an alert box where we will write our old and new password
private void showPasswordChangeDailog() {
View view = LayoutInflater.from( this ).inflate(R.layout.dialog_update_password, null );
final EditText oldpass = view.findViewById(R.id.oldpasslog);
final EditText newpass = view.findViewById(R.id.newpasslog);
Button editpass = view.findViewById(R.id.updatepass);
AlertDialog.Builder builder = new AlertDialog.Builder( this );
builder.setView(view);
final AlertDialog dialog = builder.create();
dialog.show();
editpass.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
String oldp = oldpass.getText().toString().trim();
String newp = newpass.getText().toString().trim();
if (TextUtils.isEmpty(oldp)) {
Toast.makeText(EditProfilePage. this , "Current Password cant be empty" , Toast.LENGTH_LONG).show();
return ;
}
if (TextUtils.isEmpty(newp)) {
Toast.makeText(EditProfilePage. this , "New Password cant be empty" , Toast.LENGTH_LONG).show();
return ;
}
dialog.dismiss();
updatePassword(oldp, newp);
}
});
}
// Now we will check that if old password was authenticated
// correctly then we will update the new password
private void updatePassword(String oldp, final String newp) {
pd.show();
final FirebaseUser user = firebaseAuth.getCurrentUser();
AuthCredential authCredential = EmailAuthProvider.getCredential(user.getEmail(), oldp);
user.reauthenticate(authCredential)
.addOnSuccessListener( new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
user.updatePassword(newp)
.addOnSuccessListener( new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
pd.dismiss();
Toast.makeText(EditProfilePage. this , "Changed Password" , Toast.LENGTH_LONG).show();
}
}).addOnFailureListener( new OnFailureListener() {
@Override
public void onFailure( @NonNull Exception e) {
pd.dismiss();
Toast.makeText(EditProfilePage. this , "Failed" , Toast.LENGTH_LONG).show();
}
});
}
}).addOnFailureListener( new OnFailureListener() {
@Override
public void onFailure( @NonNull Exception e) {
pd.dismiss();
Toast.makeText(EditProfilePage. this , "Failed" , Toast.LENGTH_LONG).show();
}
});
}
// Updating name
private void showNamephoneupdate( final String key) {
AlertDialog.Builder builder = new AlertDialog.Builder( this );
builder.setTitle( "Update" + key);
// creating a layout to write the new name
LinearLayout layout = new LinearLayout( this );
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding( 10 , 10 , 10 , 10 );
final EditText editText = new EditText( this );
editText.setHint( "Enter" + key);
layout.addView(editText);
builder.setView(layout);
builder.setPositiveButton( "Update" , new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final String value = editText.getText().toString().trim();
if (!TextUtils.isEmpty(value)) {
pd.show();
// Here we are updating the new name
HashMap<String, Object> result = new HashMap<>();
result.put(key, value);
databaseReference.child(firebaseUser.getUid()).updateChildren(result).addOnSuccessListener( new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
pd.dismiss();
// after updated we will show updated
Toast.makeText(EditProfilePage. this , " updated " , Toast.LENGTH_LONG).show();
}
}).addOnFailureListener( new OnFailureListener() {
@Override
public void onFailure( @NonNull Exception e) {
pd.dismiss();
Toast.makeText(EditProfilePage. this , "Unable to update" , Toast.LENGTH_LONG).show();
}
});
if (key.equals( "name" )) {
final DatabaseReference databaser = FirebaseDatabase.getInstance().getReference( "Posts" );
Query query = databaser.orderByChild( "uid" ).equalTo(uid);
query.addValueEventListener( new ValueEventListener() {
@Override
public void onDataChange( @NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
String child = databaser.getKey();
dataSnapshot1.getRef().child( "uname" ).setValue(value);
}
}
@Override
public void onCancelled( @NonNull DatabaseError databaseError) {
}
});
}
} else {
Toast.makeText(EditProfilePage. this , "Unable to update" , Toast.LENGTH_LONG).show();
}
}
});
builder.setNegativeButton( "Cancel" , new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
pd.dismiss();
}
});
builder.create().show();
}
// Here we are showing image pic dialog where we will select
// and image either from camera or gallery
private void showImagePicDialog() {
String options[] = { "Camera" , "Gallery" };
AlertDialog.Builder builder = new AlertDialog.Builder( this );
builder.setTitle( "Pick Image From" );
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// if access is not given then we will request for permission
if (which == 0 ) {
if (!checkCameraPermission()) {
requestCameraPermission();
} else {
pickFromCamera();
}
} else if (which == 1 ) {
if (!checkStoragePermission()) {
requestStoragePermission();
} else {
pickFromGallery();
}
}
}
});
builder.create().show();
}
@Override
public void onActivityResult( int requestCode, int resultCode, @Nullable Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == IMAGEPICK_GALLERY_REQUEST) {
imageuri = data.getData();
uploadProfileCoverPhoto(imageuri);
}
if (requestCode == IMAGE_PICKCAMERA_REQUEST) {
uploadProfileCoverPhoto(imageuri);
}
}
super .onActivityResult(requestCode, resultCode, data);
}
@Override
public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int [] grantResults) {
switch (requestCode) {
case CAMERA_REQUEST: {
if (grantResults.length > 0 ) {
boolean camera_accepted = grantResults[ 0 ] == PackageManager.PERMISSION_GRANTED;
boolean writeStorageaccepted = grantResults[ 1 ] == PackageManager.PERMISSION_GRANTED;
if (camera_accepted && writeStorageaccepted) {
pickFromCamera();
} else {
Toast.makeText( this , "Please Enable Camera and Storage Permissions" , Toast.LENGTH_LONG).show();
}
}
}
break ;
case STORAGE_REQUEST: {
if (grantResults.length > 0 ) {
boolean writeStorageaccepted = grantResults[ 0 ] == PackageManager.PERMISSION_GRANTED;
if (writeStorageaccepted) {
pickFromGallery();
} else {
Toast.makeText( this , "Please Enable Storage Permissions" , Toast.LENGTH_LONG).show();
}
}
}
break ;
}
}
// Here we will click a photo and then go to startactivityforresult for updating data
private void pickFromCamera() {
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Images.Media.TITLE, "Temp_pic" );
contentValues.put(MediaStore.Images.Media.DESCRIPTION, "Temp Description" );
imageuri = this .getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
Intent camerIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
camerIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri);
startActivityForResult(camerIntent, IMAGE_PICKCAMERA_REQUEST);
}
// We will select an image from gallery
private void pickFromGallery() {
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType( "image/*" );
startActivityForResult(galleryIntent, IMAGEPICK_GALLERY_REQUEST);
}
// We will upload the image from here.
private void uploadProfileCoverPhoto( final Uri uri) {
pd.show();
// We are taking the filepath as storagepath + firebaseauth.getUid()+".png"
String filepathname = storagepath + "" + profileOrCoverPhoto + "_" + firebaseUser.getUid();
StorageReference storageReference1 = storageReference.child(filepathname);
storageReference1.putFile(uri).addOnSuccessListener( new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Task<Uri> uriTask = taskSnapshot.getStorage().getDownloadUrl();
while (!uriTask.isSuccessful()) ;
// We will get the url of our image using uritask
final Uri downloadUri = uriTask.getResult();
if (uriTask.isSuccessful()) {
// updating our image url into the realtime database
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put(profileOrCoverPhoto, downloadUri.toString());
databaseReference.child(firebaseUser.getUid()).updateChildren(hashMap).addOnSuccessListener( new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
pd.dismiss();
Toast.makeText(EditProfilePage. this , "Updated" , Toast.LENGTH_LONG).show();
}
}).addOnFailureListener( new OnFailureListener() {
@Override
public void onFailure( @NonNull Exception e) {
pd.dismiss();
Toast.makeText(EditProfilePage. this , "Error Updating " , Toast.LENGTH_LONG).show();
}
});
} else {
pd.dismiss();
Toast.makeText(EditProfilePage. this , "Error" , Toast.LENGTH_LONG).show();
}
}
}).addOnFailureListener( new OnFailureListener() {
@Override
public void onFailure( @NonNull Exception e) {
pd.dismiss();
Toast.makeText(EditProfilePage. this , "Error" , Toast.LENGTH_LONG).show();
}
});
}
} |
Step 6: Create Realtime Database inside the firebase console
Go to the firebase console > Realtime Database and create your database.
Then Start in Test Mode and Enable the real-time database.
Output:
When you update the data, the data is stored like the following
For all the drawable file used in this article please refer to this link: https://drive.google.com/drive/folders/1M_knOH_ugCuwSP5nkYzeD4dRp-Honzbe?usp=sharing
Below is the file structure after performing these operations: