Transcripts
1. Introduction to the class: Hello everyone. Thank you for showing interest in my class. In this class we're going to learn how apps like chatting apps are built in general. Before we continue, I must point out that these class II designed for the people who are already familiar with Android app development in Android Studio. Integrated development environment, or Java programming language, at least. And if you're not familiar, you might find some parts difficult to understand at first. Now let us see a quick preview of the app that we are going to build and things that we are going to learn. Here we have two emulators. On the right one, we are already logged in and we can see a list of all of the users. And on the left one, you can see that we don't have username in here because we don't need it. We will be logging in with email and password. So let's now create new user. Let's name it John. We will put some random email and we will put some kind of password in here. When we click on sign up. Once signing up is complete and successful, we will be presented with the screen. And the screen is actually screen where all of the users of our app will be shown. So here is John, and at the right side, we don't have it yet. But if we do something like this, we will have John also. So we will see how to implement this thing right here. Now, if we click on this icon in here, we can see profile activity where we can applaud profile image. So we will use one from the gallery. And when we click on upload photo, we can see these progress. And then image uploaded message. If we now go back, you can see that these images still not updated. We can easily modify that also, but we will see how to do it with refreshing, with implementing swiped or refresh feature. So now here if we do it once again, we will also see this image. Now will start conversation with this user. So in here we will open John because on the left or device we are registered as John. Now, i will send some kind of message from here. And you can see that we are getting a message right there. So I will now send some smileys. And it is working just fine. So you can see that once we send the message, it is automatically registered in here. So now, if we go back and if we open this chat again, you can see that messages are still there. After you complete this class, you will learn skills that are very popular and the widely used when it comes to the mobile app development. So not only will you learn how to build chatting app, but you will also learn technologies that you can apply in your other projects. So for example, we will learn how to use Firebase as online database. We will see why do we use it. We will learn a recycler view, scarred views and many other things. So that's it. Let's get started and I'm seeing you in the next video.
2. Designing SignUp/Login screen: Hey everyone, now is the time to start creating our chat application. So let's firstly creates new Android Studio project. Let's choose empty activity. And for the name of the app. Let's put chat up. You can change package name however you want and click on finish. Building is now finished and we are ready to proceed. So firstly, let's go and change colors that we will be using in our app. So let's open values folder and open colors. So let's change primary color to the 33 a2 OFF. Now let's change primary dark to the 3.3.1 one FF. Change this one to the f, f, a, f, f. And let's add one more color, which will be called color secondary. And color will be F four, 33 a to F, F. So we have here some kind of transparency. So now when we have changed colors, we will start creating our main activity where a user can sign in and login. By the way, you can use whichever colors you like. You can do however you think that is the best. So let's open main activity and click on Split. We will delete this TextView. Will put edit text with match parent as the width for the height. We will use wrap content. Let's close this tag. This one will be used for the username. So we will put hint to be username. We will now add ID, which will be ADT username. And we will move it somewhere in here. Now let's click on this went to constraint, this edit text. We will now add one more editText, which will be also match parent and wrap content. But this one will be for the email. So let's put ID, ADT email. Let's constraint this one like this. So it will be below username edit text. We will now add last edit text for the password. So here we will put hint password. Id will be EDTA password. Also, we want to change the input type to be text password so that we have our password hidden when the user types in. So we want to have those dots when the user starts, it starts writing its password. We can now move this a little bit like here. We can also manually put here some values, but I will keep those. Now we will add a button where user will submit this form. This button will be Wrap Content. Id will be btn submit. Initial text will be sign up. And we will constraint it here. But it will be centered. And we will add some margin in here. Will be top margin and it will be ten dB. Below this button. We want this text which will say already have account login. So it'll be text view. Wrap Content. Id will be dx t login info. And initial text will be I. Already have an account login. And we will move this one below these button. So we can constraint it like this as well. So that it is centered according to these buttons. So if we move this button awake here, it will be related to these Button. We will now change this margin top to the 24, and we will add margin to this TextView to ten d p. Now we need to change background in here as well as shape of our button. So let's create a file inside drawable folder. Let's name it gradient. Here instead of selector, we want to have shape. And we will now declare gradient, which will have starting color. Accent, and ending color will be. Secondary colour like this. Now let's apply these gradient to our root layout, which is constraint layout. Now let's put it for the background attribute like this. And now we need to change the text color to the white and droid white. And we need to change shape of these button. So we'll create one more file inside this drawable folder. We will call it round blue shape. So here we will change this to the shape. It will be colored in secondary colour, and corners will be 90 db radius. We will just apply this to the background attribute of the button. And we have our button. So now lets also change text color to white in here. And I believe that we have our main screen designed. So let's run the app to see how it looks like. Now, you can see that these angle of the color is kind of wrong. So we have this pink color at the left and blue at the right side. So it is because of rendering problem in Android Studio, we are getting fake image. So we will change angle of this color to the 270 to achieve these exact gradient color. So here you can try different things. So for example, if we put 19, we will have at the bottom. If we put 135, we will have from bottom-right corner. So basically we can set angles to the numbers which can be divided by 45. So if you put 5454, for example, you see that we don't have anything. So you can try with 4726 and similar. We'll use 270. We will now run the app again to see if we have correct color now. So now it is working just fine. Now let us go in main activity to declare those views. So let's declare edit texts. We will have EDTA username, password, and ADT email. We will have. Button. And we have a text view, which is about logging information. We will now initialize them. He in here. Now we will initialize button. And finally TextView, like this. So now we want to differentiate somehow whether is user going to sign up or to login. So we will have variable which will be of type Boolean. And it will be called ease signing up. So by default, it will be equal to the true because going to open our app, we want to present the signup page at first. And when the user clicks on the text view in here, we want to change this screen to the login one, so we want to update text inside button. We want to update these text in here. And we want to hide username field. So how to do that? We will set onClickListener to the text view in here firstly, so let's do it like this. And when we click if the screen was for signing up, we want to now change it to the login screen and we will set this variable to false. And if we were on login page, we now want to change it to the signup page, and this variable will be now true. We now also need to update text. Now, button needs to have text which will be login. And in here we want to say sign up. We also want to change text. In here. Text will be don't have an account signup. And in here, we want to set the text to the already have an account. Login. Will also update this text in here. Like this. And also what do we want to achieve is to hide this edit text. So we will in here set the visibility of these EDTA username to gone. And in here we want to be visible. Now let's run the app and see if it works. If we click on this text to you, we now have this screen which will tell us login. And if we don't have an account and we want to sign up, we can click in here and we will be presented with this field. So now if you wonder why do we have this variable? Variable is used to determine when we click the Sign Up button, whether we want to start logging in process or signing up. So you will see that when we start implementing logic for the user authentication. So that's for this video. And in the next one we will connect this app to the Firebase and we will register our first users. So see you in the next video.
3. User authentication: Hey everyone, in this lecture we will integrate Firebase with our project. So easier way to implement Firebase in our project is to click on Tools, Firebase, and click on authentication, email and password authentication. And then let's connect to Firebase. Now maybe you don't see this kind of screen if you are not already logged in, in Android Studio. But since I'm logged in with this account, I'm presented with the screen. And it already knows some of my projects that are in Firebase that are associated with this account. So if you don't see something like this, I believe that you will be prompted with signing in form. And I suggest you to sign in. So it will be much more easier to integrate Firebase in that way. So here you see that I'm already suggested with the name of the project, which is the same of the project in Android Studio. So I will now click on connect to Firebase. Connecting is now in progress. Now I will open my internet browser. Open Firebase. I will now open my Firebase console, but with the account which is associated with Android Studio. And I will now click on go to the console. Mei. You can see that I have chat app, which is just created. In here. It says that Firebase project is created and we are now connected. So here now is the time to integrate authentication to our app. So let's click in here and accept changes. It will now inject the dependencies in our Gradle scripts in build-up Gradle file to be more exact. But because newer versions of Android Firebase authentication is available, we will change it to the newest one and click on sync. Now. Now we can close this assistant and open main activity. So to be able to authenticate users, we must firstly enable authentication in our project. So we'll open project in the console. And we will go to authentication and we will set up signing method. We will enable email password. And we can now create users. Since this activity will be used both for registering and logging in, we will create two methods in here. One will be called handle login, and second one will be called handle. Sign up. Handle login will be called when we click on the button. And we are not signing up. So in here and in here, we will handle sign-up because it means that we are currently in, let's say, signing up mode. Now, let's implement this method. So we will call Firebase authentication. Dot instance dot create user with email and password. Email will be taken from this edit text and password. From this one. We will also add onComplete listener. And here we will check if the task was successful. We will create dosed, which will say signed up successfully. Otherwise, we will say the Ask dot get exception that gets localized message. So it will tell us what went wrong. And that's it for the signup method. And in handle login method. We wanted to say a similar thing, but now instead of create user with email and password, we want to use sign-in with email and password. We will use same edit texts for this and same onComplete listener. And if it went wrong, we want to get the message. So that's it. Now, we want to make sure that user have correct input. So if user, for example, leaves empty some of the fields, we don't want to handle signing up or login. It will firstly here check if the email. Is empty or password is empty. And in here, if we are in sign-up mode, we need to check also for the username. So we don't want to let the user sign-up without putting username. So here we must check if we are in signing up mode and EdD username is empty. We will put those that will say invalid input. And we will hear return. So code below will not be executed. Now let's explain this in more details. So if we are in login activity, for example, in login mode, actually this is the same activity. We don't have username field, and it will be empty by default. So that's why we need to separate the CIF statement from here. So we couldn't say or EDTA username is empty because username must be empty if we are looking at in. So that's why we hear specifically checking if the we are in sign-up mode, only then check if the username is empty. So let's run the app and see how it behaves. So here it says that file Google services.js or is missing. To get this file, we need to open Chrome. You need to open also our project and click on this project settings here. And that file can be downloaded from here. And we will do that. We will now copy this file. I have already copied it, and I will just paste it in this app folder. So let's firstly choose project to make it more clear. Open this app folder and paste it in here. So make sure that it is called like this. So why we need this file is because it contains key, it contains basically information about Project and about Firebase so that our project can successfully communicate with the Firebase. Let's now try to run the app again. Also makes sure to add internet permission inside manifest file. Because sometimes it will not work. If we don't have Internet permission since our app is using Internet to do operations with the Firebase. So now I need to run this app once again so that these internet permission is applied. I will run it now. If we now start typing something in here and click on sign up, we will get invalid input message. If we create some user like this, and if we click on sign up, we have a message which says that user is signed up successfully. And let's refresh this console in here. And we have our user successfully authenticate. So now let's check if the Login works. So we will now click on login. If we now click on Login, it says that we are logged in successfully. So that's nice. So that's for this lecture.
4. Designing Profile activity: In this lecture, we will learn how to upload profile picture to the Firebase and associated with the user. But firstly, let's create Friends activity, which will be activity where all of the users will be shown here. So we will firstly create these activity because we want to go to the profile activity where we want to applaud picture from the friend's, friend's activity. Plus firstly, create that activity. They need friends activity. And click on finish. Now let's click on this. I am click on Show System UI. And basically what we want to have here, some kind of icon where we can tap and go to the profile. So to do that, we need to create menu. To create a menu, let's go right-click on the rest folder. And let's now go on new and Android resource directory. Change this to the menu and click on OK. Now in here, let's create a new menu resource file. And let's name it. Profile menu splits. And in here we want to add item, which will have ID of menu item profile. It will heal icon, which will be created right now. So let's go on drawable and create a vector asset. Let's start searching for the account. So chose this one. So we can leave it as it is. Just change the name to the account image, and add it in here. And we want to show it as action always. So now we are here having warning, which is that we should have a title, but we don't want any title since it will always be put in here. Now let's go in friend's activity and inflate that menu. So we will call on create options menu actually, we will override that method, which will be called by the system automatically. We will get menu inflator and we will inflate menu that we have just created. And here we want to put it inside these menu, which is parameter in here. And we will return true. So we wanted to go to different activity once we are successfully logged in. And we will open the main activity for that. And when we handle login, if it is complete successfully, we will start activity from Main activity to the friend's activity. We will also do the same thing when we, when we are successfully signed up. So we don't want the user to be on the screen. When we sign up, we want to translate it to the friend's activity right away. Let's now run the app and see what is going on. So let's switch to the login. Let's put credentials and click on login. So we are now in the friend's activity and we have our item in here. So since we are in main activity, let's do one more thing. And it will be when this activity gets created. We here want to check if the user is already logged in. And if it is, we want to send it. We want to send it to the friend's activity. So to check if the user is already logged in, all we need to do is to check if the current user is not equal to null. So that's how it works. And then here we want to finish main activity. So now if you run app, again, we will be presented with this activity straight away. Like so. So now let's put on click listener to this menu item. And we will do that by overriding on options menu item selected. And in here we want to check if the item that we have selected is menu item profile. And if it is the case, we will then start new activity, which will be from the Friends activity to the profile activity. But we need to create profile activity now since it doesn't exist. So let's go and do that. Name it profile, and click on finish. So now if you go here, error is gone. Now let's run the app to test if it works. Okay, now, if we click on this item in here, we are now in the profile activity. So let's now design profile activity. Here we want to have that around it image. We want to have two buttons for applauding and logging out. And we want to have texts you in here which will be use to present information about current user, such as email. So we need to download cards you. Firstly, now we can go back to the designing. We will put cards you, which will be 180 DP wide and 180 dB height. It will have Corner Radius of 90. And we will now close tag like this so that we can put image view in here. It will be match_parent id of the image will be profile image. And we can constraint it like this. We need some kind of place holder in here. And for that purpose we can use image that we have created for the Profile menu. So we will here use that account image as the source image of this image view. And we want scale type to be centered crop. Now let's open this image and let's actually change the color to the color accent. And let's remove this tint so that we can, so that we have the scholar like here. Now we will add button, which will be Wrap Content. Id will be btn. Upload image. The background will be this one. Text will be upload photo and color of the text will be white. So we will put it in here. Like this. We will add bedding to these Button. We will now add one more button for the login or sorry, for the login OUT purpose. Background will be the same, and ID will be btn logout. We will move this one in here. So now let's add some margins. We will add here. We will also add some margin in here. And we can move this card up by changing vertical bias to the 0.4. So if you put 0.5. you will have it centered. If you put one, it will be at the bottom. And if you put 0, it will be at the top. So we can use something like this. So now let's add TextView. Color will be black. Id will be dxdy, user info or user email. We will put that text to you to be here. We will add margin bottom, dB, 30 dB, like this. So now let's run the app to see how it looks on our emulator. So I have an error because I forgot to add the P in here. Let's run it again. Ok, so let's click on this item and we have our profile activity designed. So this video is getting long and because of that, we will continue in the next video where we will see how to upload data of our user in Firebase database. So see you then.
5. Uploading profile picture to Firebase - Working with Firebase Storage: Now we want to upload user data, such as username, email, and profile picture in our database. So we will firstly need to enable real-time database. And we will click on create database. And we will start it in test mode. Now we will open Android Studio. We will open this assistant. And we will now integrate real-time database. So we'll click on save and retrieve data. Now, add realtime database to the app. And let's close this assistant for now. Open build-up Gradle so that we can update Firebase database version to the latest one, like this. And click on sync. So basically, when we sign up in here, we want to put some additional data in our database. And that additional data will be actually user object. So we'll create a class called user. User object, will have username. If we'll have email. And it will have profile picture. So profile picture is also a string, which will be actually a URL to the profile picture that we will, we will upload later. So we will create, will actually generate constructor like this. We will also create one empty constructor. Because of Firebase. It needs it in order to use objects directly. In. Database. Operations will also generate getters and setters like this. So in here, when we handle sign up, if the task is successful, we want to access Firebase database dot instance dot get reference. And this reference will be user. So when we put user in here as reference, it will create user node in here. And that on that, it will set value, which will be a new user object with the username which is passed in this method in here. It will have this email. And for the profile picture, initially it will be an empty string. So we want the user to be able to add profile picture later. And initially it will have default one like this. But here, as dereference, every user is unique. And thus, we want to have one central node which will be user. And after that, we want to have some kind of branch where every user will be separated from each one by some kind of identifier. And the identifier is actually one that we can get from the Firebase ought object with get current user, get UID. And now if we run our app, but firstly, now let's firstly add logout functionality so that we can logout our user. So we will for now just initialize Logout button. And once the logout button is clicked, we want to we want to sign out. And we also want to start a new activity, which is main activity. But we also want to clear all the activities so that we can, so that we can't go back actually. And we will close this one. So let's now run the app to test this out. Ok, so let's click on this profile. Let's log out. And let's now create new user. So some random user. And let's click on sign up. And let's see what will happen in database. So we have new user in here. This user now have email, username and profile picture, which is empty at the moment. Now you understand why we used here user and then we have appended with these UID. So in this way, we can have multiple users in here. And if we were about to omit this part here, we would only be deleting this user and creating a new one every single time. So let's go logout and create one more user. Let's say something like this. Click on sign up. And then we have other user in here. Okay, so this is how it works. Now is the time to work on applauding photo part. So let's go back into code and open profile activity. So what we want to do is that when the user clicks on this image, we want to open gallery with our photos. And when the user select particular photo, we want it in here. And then when we click on upload, we want it to be uploaded on Firebase somewhere. So let's now focus on the first part where we will get the image from gallery in here. So firstly, let's go and initialize this image view. So we will firstly declare it. Okay, so this is, this is it. Let's set onClickListener for this image. And here we will open gallery solids, see how it's done. We need to create new Intent object, which will be called photo intent. It will be equal to the intent. But this time we are specifying something called action. And that action is action peak. So it will know that we want to pick something from this intent object. And that will be image. Because of that, we need to specify type, which will be imaged. Slash asterix. Now we will start activity, but activity for result because we want to get particular image with request code one. So this string here basically tells our system that we want to open gallery. So let's run the app and test it out. What's open profile activity and click on the image. You can see that it sends us to the gallery where we can select a photo. But we don't have any photo on our device. And because of that, we will need to take some photos later. But now we need to handle these result. So we need to handle our peaked image. We need to get it in here somehow. For that we will override method called on activity result. In here we will check if the request code is equal to one. And result code is ok. We also need to check that the data is not equal to null because these data will actually be image. And if all of these is the case, we will get image from these data with data.dat. Data. And now we need to store it somewhere. For that, we will need to have some global variable in here. If you wonder what is the type of this data that we are getting? It is URI. So it is basically pad to some kind of file in our device. And we will declare it in here, private URI, image Pat. And in here, we will assign these data to this image Pat, like so. Now next, what we need to do is get image in image view. And we will create that method in here. So it will be void. We will need to have bitmap. And that bitmap will be basically image that we will get from these image bet. So to do that, we need to call media store, images.me, dot get bitmap. And in here we need to get content resolver. And we will use our image bet to get it. So it is hard to remember all of those. You don't even need to remember it. Just simply Google about how to transform URI to a bitmap and you will find something like this. And now when we have our image in here, we want to set it to our image profile. So we will refer to the image profile and we will set image bitmap. This bitmap. Now you can see this underlying in here. And this is telling us that we must handle exception if basically our image is not found. So what we will do is we can simply go on more actions and we can surround this. We try catch block. And that's it. So if the image is not found, our app will not crash. Now, let's run our app and test how it works. Firstly, we must take some pictures in order to have them in our gallery. So we will open the camera of our emulator. Okay, let's, okay, let's capture this one. Now we will go back and we will open our app. So when we open profile and click on this, we will now have photos. So we will choose one. And you can see that our photo is in here. So we have successfully solved first task. And the second one is to applaud these photo on Firebase. So how we do that, where we do we actually applaud these photo. For that, we will need to use Firebase storage. So actually, storage is something where we can upload files on Firebase. And for that we will need to include dependencies first. So let's open our Firebase assistance assistant. And let's click on storage. And click on this. And let's add Cloud storage to our project. While it is getting built, let's open a web browser and let's enable storage. So we will click on get started. Let's click on Next. Click on Done. And these will be our database storage. And here we can upload files. So now let's get back to the code and see how to do that through the application. Now, we will set onClickListener to these upload photo button. But we will need to declare and initialize it firstly. So we will put it in here, and we will initialize it here. We will set onClickListener to these button. And when we click this button, we want to upload image. So let's create that method below. Now, when we start applauding task, we want to show some kind of progress of that task to the user, and that will be ProgressDialog. So we will create progress dialogue. Context will be this class. We will set title to that progress to the applauding three dots. And we wanted to show that dialogue. Finally. Now here we want to get reference of the storage so that we can applaud these picture and we will hear call Firebase, storage, dot getInstance, get reference and reference. And will be images with some kind of random string which will be generated in this way. So this will give us some random string. Which will be the name of the photo that we want to upload. And in that way, we can put multiple photos without overriding. So there is no chance that we'll have same name for some kind of photo. And when we applaud this photo to the storage, we need to associate it with our users somehow. And you will see in a moment how we will do that. So here now let's say put file. File will be our image PET. And we want to put on complete listener so that we know when complete, when uploading task is complete. And if the task was successful. We will now dismiss our progress dialog. And then we will output doest message, which will say image uploaded. Else. We will say that something went wrong with the corresponding message. But also we need to dismiss ProgressDialog anyway. And because of that, we will simply move this in here so that even our task was successful or not. We will be sure that progress dialogue will be dismissed. Let's now run the app and test how this work. Now let us go open profile activity. Let's put some image in here. And let's click on upload. Photo. App is crashed. And let's see why is that. So error is probably because when we put the dependency of the Firebase storage, it is outdated. And we should update it to the latest possible version. Because you can see that it says that there is no method which is used inside firebase storage. And we will change this to the latest version. And after we sync project will try again. So let's run the app now and see how we will work. So let's select Photo. Once again. Let's click on upload photo. And it says that images uploaded. So let's refresh this page in our web browser. You can see that there is Folder images that we have created. Any side, there is an image with these random strings that we have generated. So it working, it is working. Okay. Now what we want to do is that we want to keep track of how much of our photo is uploaded. So we want some kind of percentage of the data uploaded. So to do that, we will need to put on progress listener in here. And when these progress changes, we will update our progress dialog with this text so that progress will be double variable, which will be equal to 100 multiplied by Snapshot dot. Get bytes transferred. Divided by Snapshot dot gets total byte count. And when we get this progress, we will update message to something like this. And we will convert the this progress to integer. We will also add percentage sign. So let's now run the app and see if this works. Well, it's now open this profile. Let's applaud once again something you can see here that we have progress, but you can notice that it jumped right through, right to the 100%. This probably because our image is too small, so it finished fast. I believe that if the image is larger, it will work nicely. Now is the part when we want to associate this image to a certain user that have uploaded this picture. So to do that in here, when the task is successful, we will need to get URL of this image. And then we will put that URL in our database instead of that empty string that we have in here. So here we have empty string. We will update that field with the corresponding URL to get downloading, download URL. To get the URL from which this picture can be done loaded, we will refer to these task. We will get a result. Then we will get storage and get download URL. So this also takes some time. Basically this download URL will be available only when these, these task of getting storage and getting this URL is completed. So we will need to add one more on completely Center in here. And when this is completed, if task is successful, we will update profile picture of our user. And we will put argument in here, which will be the exact URL. And now that URL is simply a result of this task, and this task actually is getting download URL. So now we will create a method in here and we will see how it works. So we are passing string URL. So now we need to put this string URL in here. And this is how it will be done. So we must get somehow pat in our database to this profile picture field. And that Pat is this one. So we will firstly referred to the Firebase Database getInstance and get reference. In here. We will put pet to this profile picture and that bat is user. So we have user slash. We now need to get the UID of specific user. We will get that from the Firebase old object and get current user, get UID. And now all we need to do is to write profile picture. So we are now here. And to put finally that URL, we'll just set value and we will write URL. So now let's run the app and see if it works or not. Let's open profile. Well, it's now upload image. Click on upload photo. And when image is uploaded, we have our image in here. So why we have string in here, why we did that? That's because later on we will inflate our image view of the profile of our user with this string. So we will use glide library to inflate our view with this image. And if you copy this link and paste it in here, you can see that we have the image. So now you learn how to upload a photo or any file pretty much to the Firebase and associating it to our user. So in the next video, we will see how to fetch a list of all of the users. So I'm seeing you then.
6. Designing Friends activity - Fetching users from Firebase: Now is the time to design our friend's activity and to fetch a list of all of the users in Firebase. So we will need recycler view where we will put all of the users. Because of that, we will firstly need to download recycler view component. Now let's go back to the coding in here. For the background of our root layout will put gradient. In here we want progress bar, which will be 200 dp tall and wide, will put ID to be progress bar. And we will move it to the center. And that's it. Now we will put recycler view. Recycler view will be basically match parent ID of it will be recycler. But initially we want recycler view to be gone because we want to display a progress bar it first. And when we get data, we will hide this progress bar and we will show recycler view. Now let's go and create adapter for our recycler view will create new class which will be called users adapter. It will extend recycler view dot adapter. We will here create interclass, which will be our view holder. It is user holder and it extends.edu holder. Here we need to generate constructor. And we will hear at type to be of our user Holder. Now we need to implement methods that are required to get rid of the errors. Inside these adaptor, we will need ArrayList of the users. It will be called users. We will store users user objects in here. We will need context. And we will also need some kind of interface for click event. Listening are actually passing click events to our friends activity so that we can respond onclick events. And we'll hear create new interface which will be called On user click listener. It will have method called on user clicked. And we will pass position of the user that is clicked, position inside these ArrayList. So that in friend's activity we know which user is actually clicked. We will now add that interface in here. And we will now create constructor with those three parameters. We will now create view holder. It will be View, which is equal to layout inflator from context dot inflate. And we need to create our user holder inside layout. So now let's design a row which will be displayed in our friend's activity. Root layout will be cards you. It will be wrap content. For the height. We will give some margins in here. So horizontal margin will be ten dB. Margin top will be ten dB. So we want to have space between user rows and corner radius will be 40 DP, 14. In here we will have linear layout which will be matched parent wheat padding off 70 b. We will close tag in this way. And in here we want to have another card view because we want to have our profile picture around it. So we will use tarik with Descartes view and corner radius to get ground image. So in here that will be image, which will hold our profile as we will fetch from the Firebase. Idea of it will be image prof and scale type of this image will be centered crop so that we can have our image cropped inside the circle background of these card view. Actually background color will be primary color. And we also need to have text view here, which will display a username of our user. So we'll put it here below discard view. It will be Wrap Content. Id, techs dx, t, username. Text color will be white. We'll put some left margin here. And Gravity will be center, so that it will now go back to our adapter. We will hear inflated these user holder will put parents and we don't want to attach it to wrote. And we will return a new user holder with this view. Here, we want to get a user's dot-dot-dot size. And in onBind view holder, we will set the data to our layout that we have just designed. So firstly, let go in this view holder and put text view and image view that we have just added in our XML file. So here we will initialize those TXT username. So this is the text view, and now we need to initialize this image view. And on binding you holder method is called when we want to inflate the data in our layout. So we'll refer to these. The username. We will set text to users dot get position, dot get username. Let's semicolon here. If you didn't. If you wonder now how to inflate it, this image view with profile picture, we need to use glide. So open your web browser and search for glide dependency. So open this link and copy those to go back to Android studio. And in here, simply paste it and click on sync. Now, let's go back to the adapter and refer to these glide twit context dot load. To get the image URL, we need to refer to users ArrayList. We will get specific user, the position and we will get profile picture. If you, if you don't remember, this is the metal that we are referring. So we are basically fetching it from the user object, which is in Firebase. Here we will specify which image will be inflated in case the error occurs. So that image will be these image. Now here, we need to put a place holder. And it is, I believe that There is no error, but image is not fetched because it doesn't exist. Or if the URL is not valid. We'll put it the same image. And finally, we will inflate it into holder dot image view. So that's it. Our adapter is finished. Let's go back to the friend's activity and L. In France activity we need to declare recycler view. We will need array a list of users. And then progress bar user adapter that we have just created. Users adapter dot OnClickListener. So we are referring to the interface that we have put in here. Now in onCreate method, we will initialize some of those. So we will initialize progress bar. Users ArrayList, recycler view. And on user click listener will be equal to new users adapter dot on new user click listener. We forgot to basically set the sampling listener on our item. And we will do it in here in this constructor. So we'll here just say item view dot setOnClickListener, new onClickListener. And in here we will call these on user clicked, like this. On user clicked and get adapter position. So we refer to this interface, to these user click listener. And because inferences activity, we will pass this click listener to constructor of our adapter. When we click in here something, this here will be triggered and we will know that user is clicked. So we will for now put toast message that will say tapped on user. And we will get user by this position, and we will get username of that user. Now we will need to fetch users somehow and we will create a new method for, for that purpose. We will refer to the Firebase database dot getInstance get to reference user. And we will add. A listener for single event, like so. So in here, we will use for loop to get our users. So for data snapshot, in this snapshot, dot get children. Basically get children will give us a list of those items. So this is, this will be first children, this will be second children in this for loop. So we will add these children, but we need to get the value and that value will be object is itself. So in this way, when these Firstly gets in for-loop, First time, we will have this user object. From here. Next time we will have this one, and so on. When this gets completed, we'll create users adapter, wheat, users ArrayList. We'd click listener that is specified here. And activity is this one. So let's see if the order is correct. So we need to change places in here. It will be like this. Now we want to set layout manager of our recycler view to linear layout manager. And we will set adapter to be this one. Now, what we need to do is we need to set visibility of progress bar to gun, and visibility of recycler view to visible. So when we open our app, when we open this activity, we will call get users like this. So let's run the app and see if it works. So now app is running and you can see that the progress bar is spinning because it still didn't fetch the data. And once the data is fetched, progress disappeared and we have two users from our database. Now let's see how to implement swipe to refresh thing. When we pull, when we called click and pull from up to down, we want to fetch users once again. So also, you can see that when we click on user, we have toast message that we have set in here. So to implement the swipe to refresh, we will need to, we will need to search for that on Google because it is library. If we click on this, we can find easily. Implementation code and that will be put in build-up Gradle. We will upgrade this to the newest version and sync. Now. Now let's go back to friends activity. And in here, we need to use these swipe to refresh layout. And it must be root layout. So let's just start typing swipe refresh layout. And we will need to move our constraint layout to be below. So it will be match_parent and it will be surrounding all of those inside. But constraint layout itself will be surrounded with swipe to refresh, with swipe refresh layout. So here we have error. We did, We don't have actual image because o here just injected these 5p refresh layout and Android Studio is not yet ready, but trust me it works. Let's set some ID in here so that we can referred to it inferences activity, let's hear declare, survive, refresh layout. We will initialize it in here. And we will set on refresh listener. Basically, when we pulled from up to down, this metal here will be triggered. And what we will do, we will call again get users. But let's see what will happen if we run the app right now. If we pull like this, it will start spinning indefinitely. And the, we have duplicated values in here. So to solve first issue with indefinite spinning, after this method is called, we need to set swipe refresh layout, set refreshing to false. And now it will stop refreshing after we pull it. But to prevent these data duplicating. Here in here, we firstly must clear all of the data from our users database. Because recall get users we tell this is we just append our users list with same data. So now when we run the app, it will be fixed. So let's see. Okay, so let's now pull and you can see that everything is working as expected. In the next video, we will work on message activity, and we will finally see how to send messages from user to user.
7. Messaging - ChatApp final: Now is the time to create message activity. So let's go in here and create a new empty activity. Let's name it message activity. And click on finish or press the Enter key. And let's firstly design XML. Back ground will be gradient. We will put linear layout in here, which will be match parent, and the height will be 75 dp. So what we want to do with this LinearLayout, and basically we want these linear layout to be instead of this here toolbar. So firstly, we will need to remove these toolbar in here. For that purpose, we will need to define new style in here. That style will be style. We tell toolbar. Parent will be actually this one. Colors will be the same as colors from this team. But the difference is only that we don't want action bar. Now in the manifest file, in here, we will apply. And this team that we have just created. So now to refresh these layout, all you need to do is to click on here and click force refresh layout. Our layout is still not updated for some reason, probably because of some bugs in Android Studio. But if we go back to friends activity, let's start this message activity to see if it really doesn't have ActionBar, or it is in this, or it is like in this preview. So we will just open it from here when we click on some user. So let's run the app. If we click on the user, we see that there is no toolbar as expected. But for some reason, Android Studio is buggy. So you can try with closing and opening Android Studio. Again if it happens to you as well. So I will just work like it is because it doesn't bother me too much. I know that it will be working okay. So I will just continue. We're working on with this. So background of these LinearLayout will be secondary color. Its orientation will be horizontal. And I will need to close it in this way because I want to put some items in here. Those items will be card view. We'd 55 DP for width and height. Gravity will be center. And in here I want image view, which will be matched parent. And this image will basically be profile image of the user, which is chatting with us. We will add Corner Radius to 44 DP, for example, to make it round. Id of the image toolbar. And scale type will be centered crop. By default, source image will be this one. So we can do it in this way. Also. Next to these profile image, we want to have text to you, which will show username of the user that we are chatting with it. So we can be wrapped content. We will add a margin left, and we will make it to be at the center. You can see on this blueprint as well, where it will be positioned. Now we need to add tax ID, which will be TXT, chatting with, for example. Now we need to design this part in here. So we will put a progress bar which will be 200 dp. It will be centered in the middle. We will constraint it. We will constraint it like this. Id of it will be progress messages. We need to put the recycler view in here as well, which will be 0 dP. Wide and tall because we will constraint it later on to some Component ID of it will be recycler messages. And below that recycler, we want to have edit text. Let's put some random width for now because we will also constraint it's something ID will be EdD text. And for now it will be constraint like this. We need to give some background, some custom background to this edit text. And we will create it in here. So we will put, we will call it message input, background. It will be shape. We'd solid color of the scholar. We will add a radius to be 13 dp. We will apply this. So we will also need image view in here, which will be used for sending messages. So we will create a vector asset for that. Let's click and search for sense. So it will be this one. Sand image will be the name. And finish. Now we will here put that image view with 40 dB dimensions. We will move it to here. We need to put source of this image to be sand image. So we will constraint it like this. Now, we will constraint edit text to this image view. Now for the width, we'll put 0 for the height. It will be an interesting thing. So we will leave this height to be wrap content. But we will set minimum height, this edit text to be 45 dp, and maximum height will be 100 dB. So what does it mean? It means that this EditText can't be less, can be smaller than 45 dp. And when we start typing messages, it will be expanded because these attribute here is wrap content. Once expanding. Reach 100 dp. It will not be expanded anymore. So that's why we use the minimum and maximum height. Padding vertical will be ten dp and padding horizontally and B will be 20 db. So now what we need to do also is to set margin at the bottom to ten dp. And also we will put bottom margin to this image view to something like this. So you can also modify it a little bit so you can put horizontal margins to nine DP, for example, to achieve this look. Or however you like, you can even expand. You can even increase these corner radius to achieve something like this. Now let's go back to this recycler view. We wanted this recycler view to be constraint at the bottom to this and top should be here. So we can now change the width of these recycler view to match parent. And here we will have messages. But initially visibility will be gone. Because when we get the messages, we will expand it and we will hide progress bar. So now let's run the app and let's see how it looks like. Let's open this. And this is the layout. It will, it will be spinning forever because we don't have any logic in our message activity in Java code. So we will now work on that. So let's open message activity and let's initialize all of the components. So we have recycler view. Then we have EditText for inputting a message. We have TextView. This wine here. We will name it dxdy, chatting with. We will have progress bar. We will now initialize all of those. Ma, we will initialize ADT text. I believe. This is the one, so yes. Now text to you. And progress bar. So it is this one. Now what we need to do is we need to create message object. So message object will have following attributes. Sender, which will be string. It will have message receiver and the message content. So let's now create constructor. Let's create getters and setters. And let's create one empty constructor because of Firebase like this. So in here we will also have ArrayList of messages. We will initialize it in here. We forgot to add this image view in here. So we will do it now. And we will initialize it in here. We also have this image for sending message. It is this one. So it will change its ID to the IMG send message. Change this here as well. And we will initialize it in here. Now we need to go back to the friend's activity. And when we click on particular user, we will delete this toast message. And what we want to do is we want to start Message activity, but we need to pass some items in here as well. So we will put extra username of, let's say, a room mate. Because basically we have chat rooms. You'll see how we create the later and this will be are made, let's say. This will be users.js yet get position and get, get username of their roommate. Because when we fetch users list, when we click on particular user, we want to transfer its username to our message activity. Basically, if you want to chat with John, when we click on John, John, username will be transferred in here. And we will be able to put that username in here, for example. But let's firstly here put all the data that we need. We also need e-mail of the roommate. And we will get it like this. Then we will put image of roommate. And we want to get our own image. And now with the question how to get our own image. So we will hear specified string variable, which will be my image, URL. And here, when we fetch the data, we will set that image. And how to do that. In here, we will need to go in these get users method. And after we do all of that, will simply loop through all of the users that we have fetched. And we will check if user dot get email is equal to Firebase ought dot, instance, dot get current user. We get email. So this is our email. And here we are checking if our email is equal to the email of the user from users list. And that's because this user list, this user's list. When it gets inflated, it will happen that also our object, our own profile will be stored in here. So later on in here, we will loop through all of those objects and we want to find ourself. And if this is the case, my image is equal to profile picture of that user because this is us. And we will hear return because if we find ourself, we don't want to loop anymore. To save some memory. And because of performance, we don't need to lope later on if we already found ourself. So we will put, so we will put that image also. Like so. So now we can go back to our, to our message activity. Here we will put some strings. It will be, it will be Username or the roommate. Then we will have chatting with user. And we will have chatroom ID. And you will see later how we will get the room ID and the what it is actually. For now, let's firstly get username or a roommate from get intent dot GetString extra. And this is the string. Now lets get chatting with user. Actually, we will change this to email of a roommate. We have typo in here, so we need to fix that as well. And now we will here set the width to be Username, the roommate. So we now basically have set this text in here with the user that we are chatting with. So now is the hard part to grasp at first, maybe we need to set shut up room. So why we do that and what it is. So logic of keeping our messages in Firebase will be the following. So in here next to the user, we will have not called messages. And when we expand that not, we will have a room IDs. So let's imagine that we have max and we have Alex, and they are chatting, which each with each other. So we basically need to generate some kind of ID, which will be ID of the chatroom. For max and Alex, we need only one room for two different users. And it doesn't matter if Lx is sending messages to max firstly or max to Alex, that row must be unique. So to generate that kind of ID, the easiest thing to do is to. Make something with names of our users. So basically, our chat room ID should be composed of usernames of the users in that chatroom. So how to make that name unique? So basically we will compare a name of our users and alphabetically, we will generate that kind of name. So if we have Max and Alex, chatting, name of our room should be like smacks. And then let's go back to the Firebase, will hear have message is not. It is better if I show you how it works on the app that I have created before recording those tutorials. So this is, we have users and messages not and if we expand this one, those are basically chat rooms. So when we have John Wayne or with Max communicating, we will generate John Wayne max chatroom, and it will contain messages objects. It will contain message objects. So each of those are message objects that we have created, that we created before. So we have sender, receiver and the message content. So it this way. If John started conversation first, we will get this wrong created with this ID, which is basically name, which is composed of two usernames. And if max starts polarization, firstly, this Romain will be also the same. So in this way we are avoiding duplicating rooms and we are saving database space. So it maybe seems a little bit difficult to grasp. But when we start creating it, and when you see how it actually works in practice, it will be much easier. So we'll create a method called setup chatter. Oh, so we will hear referred to the user. We will here need to get UID of ourself. We will add listener for single event. So now when we go to the ID, we will get username of ourself. That username is. Snapshot dot get value users, that class, user_data class actually and get username. So here we have our username. Then we need to compare this username with the username of our roommate so that we can know which name will go first and which name will go last. And we will compare it like this. So if username of the roommate.com, my username is greater than 0, it means that our username will be first and username of the roommate will be last. So chatroom ID will be equal to this. Else if username of the roommate compares to our username is equal to 0, it means that basically usernames are the same and alphabetically their order will be the same. So it is basically comparing. If we here have Macs compared to Alex, It will see 0s before a in the alphabet. So at first, it can see that this is not the case, is we'll return number which is higher than 0. And we will get this as the username. Here. This will happen if we have users, Alex, Alex. So it will compare a to a, then it will compare L2, l, and so on. If it determines that all have same order, it will return 0. So in this case, it doesn't matter how we concatenate those. We can do the same thing like we did before. And else. It means that chatroom ID needs to be composed like this. So your user name of the user that we're chatting with needs to be first. Now what we need to do is we need to attach message, listener and it will also initialize these group. So far we are only getting the data and we are not writing anything to Firebase. And what I mean by attaching listener is that we need to put a listener to specific NADH. And when the message is changed in here, when we get some data, we need to notify our activity and it will fetch new messages. So we'll create that method. It will get, it will need basically chatroom ID. We will set and at least in our two messages plus chatroom id dot add. Now we need, we're now we want to get a value event listener not single. Because if you put single, We will not be notified about data changes. And in this way, on data change will be triggered every time a new message is received. So when we get new messages, Firstly, we want to clear previous messages. And for data snapshots. In snapshot get children. We will add message to our Messages ArrayList. So we are doing similar thing like we did when we were adding users. So after every time we fetch new messages, we want to scroll to the last message that is received. So it is size of all the messages minus1. So we want to keep messages at the bottom. So we want to, when we get new message, recycler view will be automatically scrolled to bottom. You will see that in practice, we want to set visibility of our recycler view to visible and progress bar needs to be gone. Now what we also need to do is we need to create that messages adapter. So here let's add semicolon to avoid error. We will call this method. After all of those calculations with chatroom ID and set up chat room will be called when we open this activity. Okay, now we need to create message adapter. So we'll create a new class. It will extend recycler view dot adapter will create interclass of which will be called message holder. It extends view holder was generate constructor. In here. Type will be message holder. And let's implement all of the metals. We want to have fields, ArrayList message. Then we want to have sender image. We want to have a receiver image, and we want to have context. So why we need sender and receiver image this because we want to have right, right at right side our images. Next to the balloon, which will hold the message. And sander image will be at the left side of our screen. So you'll see how we do that later. Now let's create constructor. With all of those. Here we want to return messages size. And now we need to create message holder. So we'll create new layout. And we will split here the code inside. We will put constraint layout. It will be meshed parent and the height will be Wrap Content. Id of it will be CC layout because it is constraint layout. Inside it where you have called you 35 DP, 35-day beam, because we want to have rounded image of the sender and receiver. So you'll hear that image view. Id will be small. Profile image, scale type will be centered crop. And source. We can put it to be by default this one. So let's add Corner Radius 35. Let's also add margin horizontal. Now below card view, we want to add TextView, which will actually hold message content. So it will be wrap content with margin horizontal of nine DEP. Background will be this one. We can change it later. Let's put some tools text just to see how it real. Well, it's important. Let's put some random texts to see how well message look like. Now you can see that our message is going to white. And to fix that, we also need to use three quid max width. This time before we used with maximum height when we were working on edit text in here. So now you see that our message can be wider than this. We'll add some padding in here. Let's put these bedding. And we want to put top margin. So that we can have some spacing between your messages. We also need ID for the scar view. You'll see later. Why? If you wonder why is it looking like this? Why didn't tweak constraint anything? Well, that is because in the runtime, we want to move profile picture to left or right. And these text, depending on whether it is whether it is sent by us or by our roommate. So if we are sending message, we want profile picture to be here and text message to be here. And if we are receiving message, we want profile to be here and text message to be next to it. So we will do all of that in these onBind view holder. So firstly, let's in message holder defined constraint layout. Text view, which will be message, ImageView, which will be profile image. Now initialize those. Let's check what was the idea of this? We didn't add it. So let's say txt message contents. This image is small profile image. And let's go firstly. And here create our view and return new message holder. And this you will be argument. Now is the interesting part. In onBind view holder, we firstly want to get a message. And that message will be taken from this ArrayList by position and get content. And in here, we need to manipulate with constraints through the Java code. So how to do that? We need to use constraint layout. And it is holder dot LL, holder dot, cc. All. Now we want to hear check. If the message is don't get position. Don't forget sender. Is equal to the Firebase auth dot getInstance dot get current user that get email. This means that we are sender of this message and we want to constrain all of these to the right. So let's see how it's done. We want to use constraint set, which is equal to new constraint set. Then we need to clone constraints set dot clone constraint layout, which is, which is this constraint, this entire row, basically. So that we can have information about constraints at this moment. Then we want to clear constraints from card view. So let's check which card view is that. We want to clear from this guard view. So we need to use these ID actually, we want to clear constraints between this profile card view. From the left side. We also want to clear the message content from the left side. And we want to connect card view from its right side. 2d linearly to the constraint layout and constraint right? Margin 0. So what does it mean? Let's make it more clear. So if you go here, it means basically that we have pulled constraint from here to there. So in other words, through this code, we have done this. So E have written constraint, right, to write off parent. So from the right side of card view to the right side of constraint layout with 0 margins. Then we want to constraint these TextView to these card view. And we will do that by changing this to message content right? To the right side of profile card view. And now after all of those is completed, we will basically have this. And this is how it will look like. So let's undo those changes and we need to hearsay. Constraints set a dot apply to constraint layout. Else. Now it means that we are not sender of the message. We have received the message. And we want basically to do different thing. So let's copy all of those. We want to do opposite. So here we will clear right constraints, those that are set in here. Basically we have set right constraints in here. Then in here, we want to set left constraints instead of right. But here we want to set left to right, because what we now want to achieve is this. So left side of this text to right side of the card view. Now we need to put, we need to inflate image by using glide. And here we will inflate center image. Error will, will inflate. This image. Plays whole. Holder will also be this image. And we will allow the Ds into holder dot profile image. We will do the same thing in here, but instead of sender image, we want to inflate receiver image. So that's it. Now let's go back to the message activity. And here inside onCreate method, we want to initialize a message adapter. But firstly, let's declare it here. So what we need to pass is Messages ArrayList. We need to put Sander image, which we will get from getInt and dot get string extra. Let's go back to the friend's activity and image of roommate. Basically, my images actually sender image and receiver image is image of roommate. Now we need to put context. It will be. Message activity. This. Now we have errors because we need to separate this like so and make sure that you put it that after we initialize messages, we also now want to inflate image at the toolbar here. So we will do that like this. So it is image of her roommate. If I'm not mistaking, place holder will be this one. Error will be this one. And we will load these into image toolbar. So what else we need to do is here, after we successfully get messages, we need to notify adapter. That dataset has changed. So now let's run the app and see what is going on. Let's now click on Alex, Which is by the way, US. And for some reason we don't see picture in here. So let's hear. Lx does have picture. And here we have typo and as because and that's why we don't have appropriate image in here. So let's run the app again. So let's now click on Alex. You can see that we have image in here. It is working fine. Let's set some kind of message. We forgot to setOnClickListener on these image view in here. So we firstly need to okay these, okay, so let's set onClickListener on this image sent. And when we click on this message will be sent in this way. So Firebase Database getInstance get reference. Reference is message is plus chatroom ID. We now use dot push because we want to generate random, random string like, like this one in here, like those. And then we will set value on that random string. New message, Firebase, ot, the getInstance, get current user, get email. Now we need to put email of the receiver. That email of the receiver is taken from friends activity. It is email of roommate. So here we are getting it in here and simply refer it like this. And message content will be taken from this edit text. So that's it. And after we send the message, we want to empty our edit text so that we can start typing new message. Now last thing is that we need to set this adapter to these recycler view. And this recycler view needs to have layout manager. Now run the app and see what will happen. So we will now start chatting with max. We will say hi. And here we have some problems with UI. So let's see how this went wrong. Let's open adapter, and let's check those constraints in here. So here we were supposed to say left because we want to connect this message to the left side of the card you. So let's run the app once again. And now in here you can see that we have messages not chatroom ID is Alex Max and message object is this one. So now when we run up again, when we open chatting with max, we see this message. We can send even emojis. You can see now we have another problem. And that is because in message holder, this think should have been wrapped content. So let's run App one last time. So you can see how complicated it gets to create an app like this one. There are a lot of tries and errors. But at the end, the most important thing is to understand why we did something in the way that we did. So now we can start sending some other messages. It is working just fine. So let's run this app on one more device to test how it behaves skating with another user. Let's register some user in here. Let's sign up. Let's start chatting with Alex. Here. If we refresh users and OpenGL conversation, we see that we have message from Jill and we can chat. It is working just fine. If you are wondering how to make notification. If we get new message or basically if our app is closed and we send message, how to let the user know that there is new message. We are using push notifications in that purpose and that is topic. For some other lectures. We will learn that also. But for now, it is a bit advanced topic because we need to know about notifications in general, and we need to know about servers and APIs. I believe that you enjoyed creating this app. It was a bit difficult with a lot of errors. But if you have any questions or doubts, I'm here to answer all of your questions. So that's it for me. See you in the next lecture.