Implementing Edit Profile Data Functionality in Social Media Android App
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
<? 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
<? 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.
Java
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:
Please Login to comment...