├── .gitignore ├── .idea ├── assetWizardSettings.xml ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── koddev │ │ └── chatapp │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── koddev │ │ │ └── chatapp │ │ │ ├── Adapter │ │ │ ├── MessageAdapter.java │ │ │ └── UserAdapter.java │ │ │ ├── Fragments │ │ │ ├── APIService.java │ │ │ ├── ChatsFragment.java │ │ │ ├── ProfileFragment.java │ │ │ └── UsersFragment.java │ │ │ ├── LoginActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MessageActivity.java │ │ │ ├── Model │ │ │ ├── Chat.java │ │ │ ├── Chatlist.java │ │ │ └── User.java │ │ │ ├── Notifications │ │ │ ├── Client.java │ │ │ ├── Data.java │ │ │ ├── MyFirebaseIdService.java │ │ │ ├── MyFirebaseMessaging.java │ │ │ ├── MyResponse.java │ │ │ ├── OreoNotification.java │ │ │ ├── Sender.java │ │ │ └── Token.java │ │ │ ├── RegisterActivity.java │ │ │ ├── ResetPasswordActivity.java │ │ │ └── StartActivity.java │ └── res │ │ ├── drawable-hdpi │ │ └── ic_action_name.png │ │ ├── drawable-mdpi │ │ └── ic_action_name.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ └── ic_action_name.png │ │ ├── drawable-xxhdpi │ │ └── ic_action_name.png │ │ ├── drawable │ │ ├── background_left.xml │ │ ├── background_right.xml │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_message.xml │ │ ├── activity_register.xml │ │ ├── activity_reset_password.xml │ │ ├── activity_start.xml │ │ ├── bar_layout.xml │ │ ├── chat_item_left.xml │ │ ├── chat_item_right.xml │ │ ├── fragment_chats.xml │ │ ├── fragment_profile.xml │ │ ├── fragment_users.xml │ │ └── user_item.xml │ │ ├── menu │ │ └── menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── koddev │ └── chatapp │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | -------------------------------------------------------------------------------- /.idea/assetWizardSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 60 | 61 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/majlindavdylaj/ChatAppTutorial/4eea5c5d4100ab1e73661f02a04695d12176c0d0/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChatAppTutorial 2 | 3 | I have deleted google-services.json. Add yours 4 |
Change Authorization:key with your key from firebase project 5 | 6 |
Implementation Guide 7 |
1 - Project 8 |
1 - Open the Project in your android studio; 9 |
2 - *IMPORTANT* Change the Package Name. (https://stackoverflow.com/questions/16804093/android-studio-rename-package) 10 | 11 |
2 - Firebase Panel 12 |
- Create Firebase Project (https://console.firebase.google.com/); 13 |
- Import the file google-service.json into your project 14 |
- Connect to firebase console authentication and database from your IDE (video 2) 15 |
- in firebase Storage Rules, change value of "allow read, write:" from "if request.auth != null" to "if true;" (video 12) 16 |
- For sending notification, paste your Firebase project key into your project APIService.java (video 18) 17 |
- When you change database settings, you likely will need to uninstall and reinstall apps to avoid app crashes due to app caches. 18 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "com.koddev.chatapp" 7 | minSdkVersion 16 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:27.1.1' 24 | implementation 'com.android.support.constraint:constraint-layout:1.1.2' 25 | 26 | //libraries we need for now 27 | implementation 'com.android.support:support-v4:27.1.1' 28 | implementation 'com.android.support:design:27.1.1' 29 | implementation 'com.google.firebase:firebase-auth:16.0.2' 30 | implementation 'com.google.firebase:firebase-database:16.0.1' 31 | implementation 'com.google.firebase:firebase-core:16.0.1' 32 | //add this 33 | implementation 'com.google.firebase:firebase-storage:16.0.1' 34 | implementation 'com.android.support:cardview-v7:27.1.1' 35 | implementation 'com.rengwuxian.materialedittext:library:2.1.4' 36 | //add this library and this 37 | implementation 'de.hdodenhof:circleimageview:2.2.0' 38 | implementation 'com.github.bumptech.glide:glide:4.8.0' 39 | 40 | //add these libraries 41 | implementation 'com.squareup.retrofit2:retrofit:2.3.0' 42 | implementation 'com.squareup.retrofit2:converter-gson:2.3.0' 43 | implementation 'com.google.firebase:firebase-messaging:17.3.1' 44 | 45 | testImplementation 'junit:junit:4.12' 46 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 47 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 48 | } 49 | 50 | apply plugin: 'com.google.gms.google-services' 51 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/koddev/chatapp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.koddev.chatapp", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 30 | 31 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Adapter/MessageAdapter.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Adapter; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | import com.bumptech.glide.Glide; 13 | import com.google.firebase.auth.FirebaseAuth; 14 | import com.google.firebase.auth.FirebaseUser; 15 | import com.koddev.chatapp.Model.Chat; 16 | import com.koddev.chatapp.R; 17 | 18 | import java.util.List; 19 | 20 | public class MessageAdapter extends RecyclerView.Adapter { 21 | 22 | public static final int MSG_TYPE_LEFT = 0; 23 | public static final int MSG_TYPE_RIGHT = 1; 24 | 25 | private Context mContext; 26 | private List mChat; 27 | private String imageurl; 28 | 29 | FirebaseUser fuser; 30 | 31 | public MessageAdapter(Context mContext, List mChat, String imageurl){ 32 | this.mChat = mChat; 33 | this.mContext = mContext; 34 | this.imageurl = imageurl; 35 | } 36 | 37 | @NonNull 38 | @Override 39 | public MessageAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 40 | if (viewType == MSG_TYPE_RIGHT) { 41 | View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_right, parent, false); 42 | return new MessageAdapter.ViewHolder(view); 43 | } else { 44 | View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_left, parent, false); 45 | return new MessageAdapter.ViewHolder(view); 46 | } 47 | } 48 | 49 | @Override 50 | public void onBindViewHolder(@NonNull MessageAdapter.ViewHolder holder, int position) { 51 | 52 | Chat chat = mChat.get(position); 53 | 54 | holder.show_message.setText(chat.getMessage()); 55 | 56 | if (imageurl.equals("default")){ 57 | holder.profile_image.setImageResource(R.mipmap.ic_launcher); 58 | } else { 59 | Glide.with(mContext).load(imageurl).into(holder.profile_image); 60 | } 61 | 62 | if (position == mChat.size()-1){ 63 | if (chat.isIsseen()){ 64 | holder.txt_seen.setText("Seen"); 65 | } else { 66 | holder.txt_seen.setText("Delivered"); 67 | } 68 | } else { 69 | holder.txt_seen.setVisibility(View.GONE); 70 | } 71 | 72 | } 73 | 74 | @Override 75 | public int getItemCount() { 76 | return mChat.size(); 77 | } 78 | 79 | public class ViewHolder extends RecyclerView.ViewHolder{ 80 | 81 | public TextView show_message; 82 | public ImageView profile_image; 83 | public TextView txt_seen; 84 | 85 | public ViewHolder(View itemView) { 86 | super(itemView); 87 | 88 | show_message = itemView.findViewById(R.id.show_message); 89 | profile_image = itemView.findViewById(R.id.profile_image); 90 | txt_seen = itemView.findViewById(R.id.txt_seen); 91 | } 92 | } 93 | 94 | @Override 95 | public int getItemViewType(int position) { 96 | fuser = FirebaseAuth.getInstance().getCurrentUser(); 97 | if (mChat.get(position).getSender().equals(fuser.getUid())){ 98 | return MSG_TYPE_RIGHT; 99 | } else { 100 | return MSG_TYPE_LEFT; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Adapter/UserAdapter.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Adapter; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.support.annotation.NonNull; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | import android.widget.TextView; 12 | 13 | import com.bumptech.glide.Glide; 14 | import com.google.firebase.auth.FirebaseAuth; 15 | import com.google.firebase.auth.FirebaseUser; 16 | import com.google.firebase.database.DataSnapshot; 17 | import com.google.firebase.database.DatabaseError; 18 | import com.google.firebase.database.DatabaseReference; 19 | import com.google.firebase.database.FirebaseDatabase; 20 | import com.google.firebase.database.ValueEventListener; 21 | import com.koddev.chatapp.MessageActivity; 22 | import com.koddev.chatapp.Model.Chat; 23 | import com.koddev.chatapp.Model.User; 24 | import com.koddev.chatapp.R; 25 | 26 | import java.util.List; 27 | 28 | public class UserAdapter extends RecyclerView.Adapter { 29 | 30 | private Context mContext; 31 | private List mUsers; 32 | private boolean ischat; 33 | 34 | String theLastMessage; 35 | 36 | public UserAdapter(Context mContext, List mUsers, boolean ischat){ 37 | this.mUsers = mUsers; 38 | this.mContext = mContext; 39 | this.ischat = ischat; 40 | } 41 | 42 | @NonNull 43 | @Override 44 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 45 | View view = LayoutInflater.from(mContext).inflate(R.layout.user_item, parent, false); 46 | return new UserAdapter.ViewHolder(view); 47 | } 48 | 49 | @Override 50 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 51 | 52 | final User user = mUsers.get(position); 53 | holder.username.setText(user.getUsername()); 54 | if (user.getImageURL().equals("default")){ 55 | holder.profile_image.setImageResource(R.mipmap.ic_launcher); 56 | } else { 57 | Glide.with(mContext).load(user.getImageURL()).into(holder.profile_image); 58 | } 59 | 60 | if (ischat){ 61 | lastMessage(user.getId(), holder.last_msg); 62 | } else { 63 | holder.last_msg.setVisibility(View.GONE); 64 | } 65 | 66 | if (ischat){ 67 | if (user.getStatus().equals("online")){ 68 | holder.img_on.setVisibility(View.VISIBLE); 69 | holder.img_off.setVisibility(View.GONE); 70 | } else { 71 | holder.img_on.setVisibility(View.GONE); 72 | holder.img_off.setVisibility(View.VISIBLE); 73 | } 74 | } else { 75 | holder.img_on.setVisibility(View.GONE); 76 | holder.img_off.setVisibility(View.GONE); 77 | } 78 | 79 | holder.itemView.setOnClickListener(new View.OnClickListener() { 80 | @Override 81 | public void onClick(View view) { 82 | Intent intent = new Intent(mContext, MessageActivity.class); 83 | intent.putExtra("userid", user.getId()); 84 | mContext.startActivity(intent); 85 | } 86 | }); 87 | } 88 | 89 | @Override 90 | public int getItemCount() { 91 | return mUsers.size(); 92 | } 93 | 94 | public class ViewHolder extends RecyclerView.ViewHolder{ 95 | 96 | public TextView username; 97 | public ImageView profile_image; 98 | private ImageView img_on; 99 | private ImageView img_off; 100 | private TextView last_msg; 101 | 102 | public ViewHolder(View itemView) { 103 | super(itemView); 104 | 105 | username = itemView.findViewById(R.id.username); 106 | profile_image = itemView.findViewById(R.id.profile_image); 107 | img_on = itemView.findViewById(R.id.img_on); 108 | img_off = itemView.findViewById(R.id.img_off); 109 | last_msg = itemView.findViewById(R.id.last_msg); 110 | } 111 | } 112 | 113 | //check for last message 114 | private void lastMessage(final String userid, final TextView last_msg){ 115 | theLastMessage = "default"; 116 | final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); 117 | DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Chats"); 118 | 119 | reference.addValueEventListener(new ValueEventListener() { 120 | @Override 121 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 122 | for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 123 | Chat chat = snapshot.getValue(Chat.class); 124 | if (firebaseUser != null && chat != null) { 125 | if (chat.getReceiver().equals(firebaseUser.getUid()) && chat.getSender().equals(userid) || 126 | chat.getReceiver().equals(userid) && chat.getSender().equals(firebaseUser.getUid())) { 127 | theLastMessage = chat.getMessage(); 128 | } 129 | } 130 | } 131 | 132 | switch (theLastMessage){ 133 | case "default": 134 | last_msg.setText("No Message"); 135 | break; 136 | 137 | default: 138 | last_msg.setText(theLastMessage); 139 | break; 140 | } 141 | 142 | theLastMessage = "default"; 143 | } 144 | 145 | @Override 146 | public void onCancelled(@NonNull DatabaseError databaseError) { 147 | 148 | } 149 | }); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Fragments/APIService.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Fragments; 2 | 3 | import com.koddev.chatapp.Notifications.MyResponse; 4 | import com.koddev.chatapp.Notifications.Sender; 5 | 6 | import retrofit2.Call; 7 | import retrofit2.http.Body; 8 | import retrofit2.http.Headers; 9 | import retrofit2.http.POST; 10 | 11 | public interface APIService { 12 | @Headers( 13 | { 14 | "Content-Type:application/json", 15 | "Authorization:key=ADD HERE YOUR KEY FROM FIREBASE PROJECT" 16 | } 17 | ) 18 | 19 | @POST("fcm/send") 20 | Call sendNotification(@Body Sender body); 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Fragments/ChatsFragment.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.google.firebase.auth.FirebaseAuth; 13 | import com.google.firebase.auth.FirebaseUser; 14 | import com.google.firebase.database.DataSnapshot; 15 | import com.google.firebase.database.DatabaseError; 16 | import com.google.firebase.database.DatabaseReference; 17 | import com.google.firebase.database.FirebaseDatabase; 18 | import com.google.firebase.database.ValueEventListener; 19 | import com.google.firebase.iid.FirebaseInstanceId; 20 | import com.koddev.chatapp.Adapter.UserAdapter; 21 | import com.koddev.chatapp.Model.Chatlist; 22 | import com.koddev.chatapp.Model.User; 23 | import com.koddev.chatapp.Notifications.Token; 24 | import com.koddev.chatapp.R; 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | 30 | public class ChatsFragment extends Fragment { 31 | 32 | private RecyclerView recyclerView; 33 | 34 | private UserAdapter userAdapter; 35 | private List mUsers; 36 | 37 | FirebaseUser fuser; 38 | DatabaseReference reference; 39 | 40 | private List usersList; 41 | 42 | @Override 43 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 44 | Bundle savedInstanceState) { 45 | View view = inflater.inflate(R.layout.fragment_chats, container, false); 46 | 47 | recyclerView = view.findViewById(R.id.recycler_view); 48 | recyclerView.setHasFixedSize(true); 49 | recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 50 | 51 | fuser = FirebaseAuth.getInstance().getCurrentUser(); 52 | 53 | usersList = new ArrayList<>(); 54 | 55 | reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser.getUid()); 56 | reference.addValueEventListener(new ValueEventListener() { 57 | @Override 58 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 59 | usersList.clear(); 60 | for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 61 | Chatlist chatlist = snapshot.getValue(Chatlist.class); 62 | usersList.add(chatlist); 63 | } 64 | 65 | chatList(); 66 | } 67 | 68 | @Override 69 | public void onCancelled(@NonNull DatabaseError databaseError) { 70 | 71 | } 72 | }); 73 | 74 | updateToken(FirebaseInstanceId.getInstance().getToken()); 75 | 76 | 77 | return view; 78 | } 79 | 80 | private void updateToken(String token){ 81 | DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Tokens"); 82 | Token token1 = new Token(token); 83 | reference.child(fuser.getUid()).setValue(token1); 84 | } 85 | 86 | private void chatList() { 87 | mUsers = new ArrayList<>(); 88 | reference = FirebaseDatabase.getInstance().getReference("Users"); 89 | reference.addValueEventListener(new ValueEventListener() { 90 | @Override 91 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 92 | mUsers.clear(); 93 | for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 94 | User user = snapshot.getValue(User.class); 95 | for (Chatlist chatlist : usersList){ 96 | if (user.getId().equals(chatlist.getId())){ 97 | mUsers.add(user); 98 | } 99 | } 100 | } 101 | userAdapter = new UserAdapter(getContext(), mUsers, true); 102 | recyclerView.setAdapter(userAdapter); 103 | } 104 | 105 | @Override 106 | public void onCancelled(@NonNull DatabaseError databaseError) { 107 | 108 | } 109 | }); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Fragments/ProfileFragment.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Fragments; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.ContentResolver; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.support.annotation.NonNull; 9 | import android.support.v4.app.Fragment; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.webkit.MimeTypeMap; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.bumptech.glide.Glide; 18 | import com.google.android.gms.tasks.Continuation; 19 | import com.google.android.gms.tasks.OnCompleteListener; 20 | import com.google.android.gms.tasks.OnFailureListener; 21 | import com.google.android.gms.tasks.Task; 22 | import com.google.firebase.auth.FirebaseAuth; 23 | import com.google.firebase.auth.FirebaseUser; 24 | import com.google.firebase.database.DataSnapshot; 25 | import com.google.firebase.database.DatabaseError; 26 | import com.google.firebase.database.DatabaseReference; 27 | import com.google.firebase.database.FirebaseDatabase; 28 | import com.google.firebase.database.ValueEventListener; 29 | import com.google.firebase.storage.FirebaseStorage; 30 | import com.google.firebase.storage.StorageReference; 31 | import com.google.firebase.storage.StorageTask; 32 | import com.google.firebase.storage.UploadTask; 33 | import com.koddev.chatapp.Model.User; 34 | import com.koddev.chatapp.R; 35 | 36 | import java.util.HashMap; 37 | 38 | import de.hdodenhof.circleimageview.CircleImageView; 39 | 40 | import static android.app.Activity.RESULT_OK; 41 | 42 | 43 | public class ProfileFragment extends Fragment { 44 | 45 | CircleImageView image_profile; 46 | TextView username; 47 | 48 | DatabaseReference reference; 49 | FirebaseUser fuser; 50 | 51 | StorageReference storageReference; 52 | private static final int IMAGE_REQUEST = 1; 53 | private Uri imageUri; 54 | private StorageTask uploadTask; 55 | 56 | 57 | @Override 58 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 59 | Bundle savedInstanceState) { 60 | // Inflate the layout for this fragment 61 | View view = inflater.inflate(R.layout.fragment_profile, container, false); 62 | 63 | image_profile = view.findViewById(R.id.profile_image); 64 | username = view.findViewById(R.id.username); 65 | 66 | storageReference = FirebaseStorage.getInstance().getReference("uploads"); 67 | 68 | fuser = FirebaseAuth.getInstance().getCurrentUser(); 69 | reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); 70 | 71 | reference.addValueEventListener(new ValueEventListener() { 72 | @Override 73 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 74 | User user = dataSnapshot.getValue(User.class); 75 | username.setText(user.getUsername()); 76 | if (user.getImageURL().equals("default")){ 77 | image_profile.setImageResource(R.mipmap.ic_launcher); 78 | } else { 79 | Glide.with(getContext()).load(user.getImageURL()).into(image_profile); 80 | } 81 | } 82 | 83 | @Override 84 | public void onCancelled(@NonNull DatabaseError databaseError) { 85 | 86 | } 87 | }); 88 | 89 | image_profile.setOnClickListener(new View.OnClickListener() { 90 | @Override 91 | public void onClick(View view) { 92 | openImage(); 93 | } 94 | }); 95 | 96 | return view; 97 | } 98 | 99 | private void openImage() { 100 | Intent intent = new Intent(); 101 | intent.setType("image/*"); 102 | intent.setAction(Intent.ACTION_GET_CONTENT); 103 | startActivityForResult(intent, IMAGE_REQUEST); 104 | } 105 | 106 | private String getFileExtension(Uri uri){ 107 | ContentResolver contentResolver = getContext().getContentResolver(); 108 | MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); 109 | return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri)); 110 | } 111 | 112 | private void uploadImage(){ 113 | final ProgressDialog pd = new ProgressDialog(getContext()); 114 | pd.setMessage("Uploading"); 115 | pd.show(); 116 | 117 | if (imageUri != null){ 118 | final StorageReference fileReference = storageReference.child(System.currentTimeMillis() 119 | +"."+getFileExtension(imageUri)); 120 | 121 | uploadTask = fileReference.putFile(imageUri); 122 | uploadTask.continueWithTask(new Continuation>() { 123 | @Override 124 | public Task then(@NonNull Task task) throws Exception { 125 | if (!task.isSuccessful()){ 126 | throw task.getException(); 127 | } 128 | 129 | return fileReference.getDownloadUrl(); 130 | } 131 | }).addOnCompleteListener(new OnCompleteListener() { 132 | @Override 133 | public void onComplete(@NonNull Task task) { 134 | if (task.isSuccessful()){ 135 | Uri downloadUri = task.getResult(); 136 | String mUri = downloadUri.toString(); 137 | 138 | reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); 139 | HashMap map = new HashMap<>(); 140 | map.put("imageURL", ""+mUri); 141 | reference.updateChildren(map); 142 | 143 | pd.dismiss(); 144 | } else { 145 | Toast.makeText(getContext(), "Failed!", Toast.LENGTH_SHORT).show(); 146 | pd.dismiss(); 147 | } 148 | } 149 | }).addOnFailureListener(new OnFailureListener() { 150 | @Override 151 | public void onFailure(@NonNull Exception e) { 152 | Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 153 | pd.dismiss(); 154 | } 155 | }); 156 | } else { 157 | Toast.makeText(getContext(), "No image selected", Toast.LENGTH_SHORT).show(); 158 | } 159 | } 160 | 161 | @Override 162 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 163 | super.onActivityResult(requestCode, resultCode, data); 164 | 165 | if (requestCode == IMAGE_REQUEST && resultCode == RESULT_OK 166 | && data != null && data.getData() != null){ 167 | imageUri = data.getData(); 168 | 169 | if (uploadTask != null && uploadTask.isInProgress()){ 170 | Toast.makeText(getContext(), "Upload in preogress", Toast.LENGTH_SHORT).show(); 171 | } else { 172 | uploadImage(); 173 | } 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Fragments/UsersFragment.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.text.Editable; 9 | import android.text.TextWatcher; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.EditText; 14 | 15 | import com.google.firebase.auth.FirebaseAuth; 16 | import com.google.firebase.auth.FirebaseUser; 17 | import com.google.firebase.database.DataSnapshot; 18 | import com.google.firebase.database.DatabaseError; 19 | import com.google.firebase.database.DatabaseReference; 20 | import com.google.firebase.database.FirebaseDatabase; 21 | import com.google.firebase.database.Query; 22 | import com.google.firebase.database.ValueEventListener; 23 | import com.koddev.chatapp.Adapter.UserAdapter; 24 | import com.koddev.chatapp.Model.User; 25 | import com.koddev.chatapp.R; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | 31 | public class UsersFragment extends Fragment { 32 | 33 | private RecyclerView recyclerView; 34 | 35 | private UserAdapter userAdapter; 36 | private List mUsers; 37 | 38 | EditText search_users; 39 | 40 | 41 | @Override 42 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 43 | Bundle savedInstanceState) { 44 | 45 | View view = inflater.inflate(R.layout.fragment_users, container, false); 46 | 47 | recyclerView = view.findViewById(R.id.recycler_view); 48 | recyclerView.setHasFixedSize(true); 49 | recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 50 | 51 | mUsers = new ArrayList<>(); 52 | 53 | readUsers(); 54 | 55 | search_users = view.findViewById(R.id.search_users); 56 | search_users.addTextChangedListener(new TextWatcher() { 57 | @Override 58 | public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { 59 | 60 | } 61 | 62 | @Override 63 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { 64 | searchUsers(charSequence.toString().toLowerCase()); 65 | } 66 | 67 | @Override 68 | public void afterTextChanged(Editable editable) { 69 | 70 | } 71 | }); 72 | 73 | return view; 74 | } 75 | 76 | private void searchUsers(String s) { 77 | 78 | final FirebaseUser fuser = FirebaseAuth.getInstance().getCurrentUser(); 79 | Query query = FirebaseDatabase.getInstance().getReference("Users").orderByChild("search") 80 | .startAt(s) 81 | .endAt(s+"\uf8ff"); 82 | 83 | query.addValueEventListener(new ValueEventListener() { 84 | @Override 85 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 86 | mUsers.clear(); 87 | for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 88 | User user = snapshot.getValue(User.class); 89 | 90 | assert user != null; 91 | assert fuser != null; 92 | if (!user.getId().equals(fuser.getUid())){ 93 | mUsers.add(user); 94 | } 95 | } 96 | 97 | userAdapter = new UserAdapter(getContext(), mUsers, false); 98 | recyclerView.setAdapter(userAdapter); 99 | } 100 | 101 | @Override 102 | public void onCancelled(@NonNull DatabaseError databaseError) { 103 | 104 | } 105 | }); 106 | 107 | } 108 | 109 | private void readUsers() { 110 | 111 | final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); 112 | DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users"); 113 | 114 | reference.addValueEventListener(new ValueEventListener() { 115 | @Override 116 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 117 | if (search_users.getText().toString().equals("")) { 118 | mUsers.clear(); 119 | for (DataSnapshot snapshot : dataSnapshot.getChildren()) { 120 | User user = snapshot.getValue(User.class); 121 | 122 | if (!user.getId().equals(firebaseUser.getUid())) { 123 | mUsers.add(user); 124 | } 125 | 126 | } 127 | 128 | userAdapter = new UserAdapter(getContext(), mUsers, false); 129 | recyclerView.setAdapter(userAdapter); 130 | } 131 | } 132 | 133 | @Override 134 | public void onCancelled(@NonNull DatabaseError databaseError) { 135 | 136 | } 137 | }); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.Toolbar; 8 | import android.text.TextUtils; 9 | import android.view.View; 10 | import android.widget.Button; 11 | import android.widget.TextView; 12 | import android.widget.Toast; 13 | 14 | import com.google.android.gms.tasks.OnCompleteListener; 15 | import com.google.android.gms.tasks.Task; 16 | import com.google.firebase.auth.AuthResult; 17 | import com.google.firebase.auth.FirebaseAuth; 18 | import com.rengwuxian.materialedittext.MaterialEditText; 19 | 20 | public class LoginActivity extends AppCompatActivity { 21 | 22 | MaterialEditText email, password; 23 | Button btn_login; 24 | 25 | FirebaseAuth auth; 26 | TextView forgot_password; 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.activity_login); 32 | 33 | Toolbar toolbar = findViewById(R.id.toolbar); 34 | setSupportActionBar(toolbar); 35 | getSupportActionBar().setTitle("Login"); 36 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 37 | 38 | auth = FirebaseAuth.getInstance(); 39 | 40 | email = findViewById(R.id.email); 41 | password = findViewById(R.id.password); 42 | btn_login = findViewById(R.id.btn_login); 43 | forgot_password = findViewById(R.id.forgot_password); 44 | 45 | forgot_password.setOnClickListener(new View.OnClickListener() { 46 | @Override 47 | public void onClick(View view) { 48 | startActivity(new Intent(LoginActivity.this, ResetPasswordActivity.class)); 49 | } 50 | }); 51 | 52 | btn_login.setOnClickListener(new View.OnClickListener() { 53 | @Override 54 | public void onClick(View view) { 55 | String txt_email = email.getText().toString(); 56 | String txt_password = password.getText().toString(); 57 | 58 | if (TextUtils.isEmpty(txt_email) || TextUtils.isEmpty(txt_password)){ 59 | Toast.makeText(LoginActivity.this, "All fileds are required", Toast.LENGTH_SHORT).show(); 60 | } else { 61 | 62 | auth.signInWithEmailAndPassword(txt_email, txt_password) 63 | .addOnCompleteListener(new OnCompleteListener() { 64 | @Override 65 | public void onComplete(@NonNull Task task) { 66 | if (task.isSuccessful()){ 67 | Intent intent = new Intent(LoginActivity.this, MainActivity.class); 68 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); 69 | startActivity(intent); 70 | finish(); 71 | } else { 72 | Toast.makeText(LoginActivity.this, "Authentication failed!", Toast.LENGTH_SHORT).show(); 73 | } 74 | } 75 | }); 76 | } 77 | } 78 | }); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.support.design.widget.TabLayout; 8 | import android.support.v4.app.Fragment; 9 | import android.support.v4.app.FragmentManager; 10 | import android.support.v4.app.FragmentPagerAdapter; 11 | import android.support.v4.view.ViewPager; 12 | import android.support.v7.app.AppCompatActivity; 13 | import android.support.v7.widget.Toolbar; 14 | import android.view.Menu; 15 | import android.view.MenuItem; 16 | import android.widget.TextView; 17 | 18 | import com.bumptech.glide.Glide; 19 | import com.google.firebase.auth.FirebaseAuth; 20 | import com.google.firebase.auth.FirebaseUser; 21 | import com.google.firebase.database.DataSnapshot; 22 | import com.google.firebase.database.DatabaseError; 23 | import com.google.firebase.database.DatabaseReference; 24 | import com.google.firebase.database.FirebaseDatabase; 25 | import com.google.firebase.database.ValueEventListener; 26 | import com.koddev.chatapp.Fragments.ChatsFragment; 27 | import com.koddev.chatapp.Fragments.ProfileFragment; 28 | import com.koddev.chatapp.Fragments.UsersFragment; 29 | import com.koddev.chatapp.Model.Chat; 30 | import com.koddev.chatapp.Model.User; 31 | 32 | import java.util.ArrayList; 33 | import java.util.HashMap; 34 | 35 | import de.hdodenhof.circleimageview.CircleImageView; 36 | 37 | public class MainActivity extends AppCompatActivity { 38 | 39 | CircleImageView profile_image; 40 | TextView username; 41 | 42 | FirebaseUser firebaseUser; 43 | DatabaseReference reference; 44 | 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | setContentView(R.layout.activity_main); 49 | 50 | Toolbar toolbar = findViewById(R.id.toolbar); 51 | setSupportActionBar(toolbar); 52 | getSupportActionBar().setTitle(""); 53 | 54 | profile_image = findViewById(R.id.profile_image); 55 | username = findViewById(R.id.username); 56 | 57 | firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); 58 | reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser.getUid()); 59 | 60 | reference.addValueEventListener(new ValueEventListener() { 61 | @Override 62 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 63 | User user = dataSnapshot.getValue(User.class); 64 | username.setText(user.getUsername()); 65 | if (user.getImageURL().equals("default")){ 66 | profile_image.setImageResource(R.mipmap.ic_launcher); 67 | } else { 68 | 69 | //change this 70 | Glide.with(getApplicationContext()).load(user.getImageURL()).into(profile_image); 71 | } 72 | } 73 | 74 | @Override 75 | public void onCancelled(@NonNull DatabaseError databaseError) { 76 | 77 | } 78 | }); 79 | 80 | final TabLayout tabLayout = findViewById(R.id.tab_layout); 81 | final ViewPager viewPager = findViewById(R.id.view_pager); 82 | 83 | 84 | reference = FirebaseDatabase.getInstance().getReference("Chats"); 85 | reference.addValueEventListener(new ValueEventListener() { 86 | @Override 87 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 88 | ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager()); 89 | int unread = 0; 90 | for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 91 | Chat chat = snapshot.getValue(Chat.class); 92 | if (chat.getReceiver().equals(firebaseUser.getUid()) && !chat.isIsseen()){ 93 | unread++; 94 | } 95 | } 96 | 97 | if (unread == 0){ 98 | viewPagerAdapter.addFragment(new ChatsFragment(), "Chats"); 99 | } else { 100 | viewPagerAdapter.addFragment(new ChatsFragment(), "("+unread+") Chats"); 101 | } 102 | 103 | viewPagerAdapter.addFragment(new UsersFragment(), "Users"); 104 | viewPagerAdapter.addFragment(new ProfileFragment(), "Profile"); 105 | 106 | viewPager.setAdapter(viewPagerAdapter); 107 | 108 | tabLayout.setupWithViewPager(viewPager); 109 | 110 | } 111 | 112 | @Override 113 | public void onCancelled(@NonNull DatabaseError databaseError) { 114 | 115 | } 116 | }); 117 | 118 | 119 | } 120 | 121 | @Override 122 | public boolean onCreateOptionsMenu(Menu menu) { 123 | getMenuInflater().inflate(R.menu.menu, menu); 124 | return true; 125 | } 126 | 127 | @Override 128 | public boolean onOptionsItemSelected(MenuItem item) { 129 | switch (item.getItemId()){ 130 | 131 | case R.id.logout: 132 | FirebaseAuth.getInstance().signOut(); 133 | // change this code beacuse your app will crash 134 | startActivity(new Intent(MainActivity.this, StartActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); 135 | return true; 136 | } 137 | 138 | return false; 139 | } 140 | 141 | class ViewPagerAdapter extends FragmentPagerAdapter { 142 | 143 | private ArrayList fragments; 144 | private ArrayList titles; 145 | 146 | ViewPagerAdapter(FragmentManager fm){ 147 | super(fm); 148 | this.fragments = new ArrayList<>(); 149 | this.titles = new ArrayList<>(); 150 | } 151 | 152 | @Override 153 | public Fragment getItem(int position) { 154 | return fragments.get(position); 155 | } 156 | 157 | @Override 158 | public int getCount() { 159 | return fragments.size(); 160 | } 161 | 162 | public void addFragment(Fragment fragment, String title){ 163 | fragments.add(fragment); 164 | titles.add(title); 165 | } 166 | 167 | // Ctrl + O 168 | 169 | @Nullable 170 | @Override 171 | public CharSequence getPageTitle(int position) { 172 | return titles.get(position); 173 | } 174 | } 175 | 176 | private void status(String status){ 177 | reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser.getUid()); 178 | 179 | HashMap hashMap = new HashMap<>(); 180 | hashMap.put("status", status); 181 | 182 | reference.updateChildren(hashMap); 183 | } 184 | 185 | @Override 186 | protected void onResume() { 187 | super.onResume(); 188 | status("online"); 189 | } 190 | 191 | @Override 192 | protected void onPause() { 193 | super.onPause(); 194 | status("offline"); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/MessageActivity.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp; 2 | 3 | import android.content.Intent; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.View; 12 | import android.widget.EditText; 13 | import android.widget.ImageButton; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.bumptech.glide.Glide; 18 | import com.google.firebase.auth.FirebaseAuth; 19 | import com.google.firebase.auth.FirebaseUser; 20 | import com.google.firebase.database.DataSnapshot; 21 | import com.google.firebase.database.DatabaseError; 22 | import com.google.firebase.database.DatabaseReference; 23 | import com.google.firebase.database.FirebaseDatabase; 24 | import com.google.firebase.database.Query; 25 | import com.google.firebase.database.ValueEventListener; 26 | import com.koddev.chatapp.Adapter.MessageAdapter; 27 | import com.koddev.chatapp.Fragments.APIService; 28 | import com.koddev.chatapp.Model.Chat; 29 | import com.koddev.chatapp.Model.User; 30 | import com.koddev.chatapp.Notifications.Client; 31 | import com.koddev.chatapp.Notifications.Data; 32 | import com.koddev.chatapp.Notifications.MyResponse; 33 | import com.koddev.chatapp.Notifications.Sender; 34 | import com.koddev.chatapp.Notifications.Token; 35 | 36 | import java.util.ArrayList; 37 | import java.util.HashMap; 38 | import java.util.List; 39 | 40 | import de.hdodenhof.circleimageview.CircleImageView; 41 | import retrofit2.Call; 42 | import retrofit2.Callback; 43 | import retrofit2.Response; 44 | 45 | public class MessageActivity extends AppCompatActivity { 46 | 47 | CircleImageView profile_image; 48 | TextView username; 49 | 50 | FirebaseUser fuser; 51 | DatabaseReference reference; 52 | 53 | ImageButton btn_send; 54 | EditText text_send; 55 | 56 | MessageAdapter messageAdapter; 57 | List mchat; 58 | 59 | RecyclerView recyclerView; 60 | 61 | Intent intent; 62 | 63 | ValueEventListener seenListener; 64 | 65 | String userid; 66 | 67 | APIService apiService; 68 | 69 | boolean notify = false; 70 | 71 | @Override 72 | protected void onCreate(Bundle savedInstanceState) { 73 | super.onCreate(savedInstanceState); 74 | setContentView(R.layout.activity_message); 75 | 76 | Toolbar toolbar = findViewById(R.id.toolbar); 77 | setSupportActionBar(toolbar); 78 | getSupportActionBar().setTitle(""); 79 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 80 | toolbar.setNavigationOnClickListener(new View.OnClickListener() { 81 | @Override 82 | public void onClick(View view) { 83 | // and this 84 | startActivity(new Intent(MessageActivity.this, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); 85 | } 86 | }); 87 | 88 | apiService = Client.getClient("https://fcm.googleapis.com/").create(APIService.class); 89 | 90 | recyclerView = findViewById(R.id.recycler_view); 91 | recyclerView.setHasFixedSize(true); 92 | LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext()); 93 | linearLayoutManager.setStackFromEnd(true); 94 | recyclerView.setLayoutManager(linearLayoutManager); 95 | 96 | profile_image = findViewById(R.id.profile_image); 97 | username = findViewById(R.id.username); 98 | btn_send = findViewById(R.id.btn_send); 99 | text_send = findViewById(R.id.text_send); 100 | 101 | intent = getIntent(); 102 | userid = intent.getStringExtra("userid"); 103 | fuser = FirebaseAuth.getInstance().getCurrentUser(); 104 | 105 | btn_send.setOnClickListener(new View.OnClickListener() { 106 | @Override 107 | public void onClick(View view) { 108 | notify = true; 109 | String msg = text_send.getText().toString(); 110 | if (!msg.equals("")){ 111 | sendMessage(fuser.getUid(), userid, msg); 112 | } else { 113 | Toast.makeText(MessageActivity.this, "You can't send empty message", Toast.LENGTH_SHORT).show(); 114 | } 115 | text_send.setText(""); 116 | } 117 | }); 118 | 119 | 120 | reference = FirebaseDatabase.getInstance().getReference("Users").child(userid); 121 | 122 | reference.addValueEventListener(new ValueEventListener() { 123 | @Override 124 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 125 | User user = dataSnapshot.getValue(User.class); 126 | username.setText(user.getUsername()); 127 | if (user.getImageURL().equals("default")){ 128 | profile_image.setImageResource(R.mipmap.ic_launcher); 129 | } else { 130 | //and this 131 | Glide.with(getApplicationContext()).load(user.getImageURL()).into(profile_image); 132 | } 133 | 134 | readMesagges(fuser.getUid(), userid, user.getImageURL()); 135 | } 136 | 137 | @Override 138 | public void onCancelled(@NonNull DatabaseError databaseError) { 139 | 140 | } 141 | }); 142 | 143 | seenMessage(userid); 144 | } 145 | 146 | private void seenMessage(final String userid){ 147 | reference = FirebaseDatabase.getInstance().getReference("Chats"); 148 | seenListener = reference.addValueEventListener(new ValueEventListener() { 149 | @Override 150 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 151 | for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 152 | Chat chat = snapshot.getValue(Chat.class); 153 | if (chat.getReceiver().equals(fuser.getUid()) && chat.getSender().equals(userid)){ 154 | HashMap hashMap = new HashMap<>(); 155 | hashMap.put("isseen", true); 156 | snapshot.getRef().updateChildren(hashMap); 157 | } 158 | } 159 | } 160 | 161 | @Override 162 | public void onCancelled(@NonNull DatabaseError databaseError) { 163 | 164 | } 165 | }); 166 | } 167 | 168 | private void sendMessage(String sender, final String receiver, String message){ 169 | 170 | DatabaseReference reference = FirebaseDatabase.getInstance().getReference(); 171 | 172 | HashMap hashMap = new HashMap<>(); 173 | hashMap.put("sender", sender); 174 | hashMap.put("receiver", receiver); 175 | hashMap.put("message", message); 176 | hashMap.put("isseen", false); 177 | 178 | reference.child("Chats").push().setValue(hashMap); 179 | 180 | 181 | // add user to chat fragment 182 | final DatabaseReference chatRef = FirebaseDatabase.getInstance().getReference("Chatlist") 183 | .child(fuser.getUid()) 184 | .child(userid); 185 | 186 | chatRef.addListenerForSingleValueEvent(new ValueEventListener() { 187 | @Override 188 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 189 | if (!dataSnapshot.exists()){ 190 | chatRef.child("id").setValue(userid); 191 | } 192 | } 193 | 194 | @Override 195 | public void onCancelled(@NonNull DatabaseError databaseError) { 196 | 197 | } 198 | }); 199 | 200 | final DatabaseReference chatRefReceiver = FirebaseDatabase.getInstance().getReference("Chatlist") 201 | .child(userid) 202 | .child(fuser.getUid()); 203 | chatRefReceiver.child("id").setValue(fuser.getUid()); 204 | 205 | final String msg = message; 206 | 207 | reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); 208 | reference.addValueEventListener(new ValueEventListener() { 209 | @Override 210 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 211 | User user = dataSnapshot.getValue(User.class); 212 | if (notify) { 213 | sendNotifiaction(receiver, user.getUsername(), msg); 214 | } 215 | notify = false; 216 | } 217 | 218 | @Override 219 | public void onCancelled(@NonNull DatabaseError databaseError) { 220 | 221 | } 222 | }); 223 | } 224 | 225 | private void sendNotifiaction(String receiver, final String username, final String message){ 226 | DatabaseReference tokens = FirebaseDatabase.getInstance().getReference("Tokens"); 227 | Query query = tokens.orderByKey().equalTo(receiver); 228 | query.addValueEventListener(new ValueEventListener() { 229 | @Override 230 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 231 | for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 232 | Token token = snapshot.getValue(Token.class); 233 | Data data = new Data(fuser.getUid(), R.mipmap.ic_launcher, username+": "+message, "New Message", 234 | userid); 235 | 236 | Sender sender = new Sender(data, token.getToken()); 237 | 238 | apiService.sendNotification(sender) 239 | .enqueue(new Callback() { 240 | @Override 241 | public void onResponse(Call call, Response response) { 242 | if (response.code() == 200){ 243 | if (response.body().success != 1){ 244 | Toast.makeText(MessageActivity.this, "Failed!", Toast.LENGTH_SHORT).show(); 245 | } 246 | } 247 | } 248 | 249 | @Override 250 | public void onFailure(Call call, Throwable t) { 251 | 252 | } 253 | }); 254 | } 255 | } 256 | 257 | @Override 258 | public void onCancelled(@NonNull DatabaseError databaseError) { 259 | 260 | } 261 | }); 262 | } 263 | 264 | private void readMesagges(final String myid, final String userid, final String imageurl){ 265 | mchat = new ArrayList<>(); 266 | 267 | reference = FirebaseDatabase.getInstance().getReference("Chats"); 268 | reference.addValueEventListener(new ValueEventListener() { 269 | @Override 270 | public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 271 | mchat.clear(); 272 | for (DataSnapshot snapshot : dataSnapshot.getChildren()){ 273 | Chat chat = snapshot.getValue(Chat.class); 274 | if (chat.getReceiver().equals(myid) && chat.getSender().equals(userid) || 275 | chat.getReceiver().equals(userid) && chat.getSender().equals(myid)){ 276 | mchat.add(chat); 277 | } 278 | 279 | messageAdapter = new MessageAdapter(MessageActivity.this, mchat, imageurl); 280 | recyclerView.setAdapter(messageAdapter); 281 | } 282 | } 283 | 284 | @Override 285 | public void onCancelled(@NonNull DatabaseError databaseError) { 286 | 287 | } 288 | }); 289 | } 290 | 291 | private void currentUser(String userid){ 292 | SharedPreferences.Editor editor = getSharedPreferences("PREFS", MODE_PRIVATE).edit(); 293 | editor.putString("currentuser", userid); 294 | editor.apply(); 295 | } 296 | 297 | private void status(String status){ 298 | reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); 299 | 300 | HashMap hashMap = new HashMap<>(); 301 | hashMap.put("status", status); 302 | 303 | reference.updateChildren(hashMap); 304 | } 305 | 306 | @Override 307 | protected void onResume() { 308 | super.onResume(); 309 | status("online"); 310 | currentUser(userid); 311 | } 312 | 313 | @Override 314 | protected void onPause() { 315 | super.onPause(); 316 | reference.removeEventListener(seenListener); 317 | status("offline"); 318 | currentUser("none"); 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Model/Chat.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Model; 2 | 3 | public class Chat { 4 | 5 | private String sender; 6 | private String receiver; 7 | private String message; 8 | private boolean isseen; 9 | 10 | public Chat(String sender, String receiver, String message, boolean isseen) { 11 | this.sender = sender; 12 | this.receiver = receiver; 13 | this.message = message; 14 | this.isseen = isseen; 15 | } 16 | 17 | public Chat() { 18 | } 19 | 20 | public String getSender() { 21 | return sender; 22 | } 23 | 24 | public void setSender(String sender) { 25 | this.sender = sender; 26 | } 27 | 28 | public String getReceiver() { 29 | return receiver; 30 | } 31 | 32 | public void setReceiver(String receiver) { 33 | this.receiver = receiver; 34 | } 35 | 36 | public String getMessage() { 37 | return message; 38 | } 39 | 40 | public void setMessage(String message) { 41 | this.message = message; 42 | } 43 | 44 | public boolean isIsseen() { 45 | return isseen; 46 | } 47 | 48 | public void setIsseen(boolean isseen) { 49 | this.isseen = isseen; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Model/Chatlist.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Model; 2 | 3 | public class Chatlist { 4 | public String id; 5 | 6 | public Chatlist(String id) { 7 | this.id = id; 8 | } 9 | 10 | public Chatlist() { 11 | } 12 | 13 | public String getId() { 14 | return id; 15 | } 16 | 17 | public void setId(String id) { 18 | this.id = id; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Model/User.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Model; 2 | 3 | public class User { 4 | 5 | private String id; 6 | private String username; 7 | private String imageURL; 8 | private String status; 9 | private String search; 10 | 11 | public User(String id, String username, String imageURL, String status, String search) { 12 | this.id = id; 13 | this.username = username; 14 | this.imageURL = imageURL; 15 | this.status = status; 16 | this.search = search; 17 | } 18 | 19 | public User() { 20 | 21 | } 22 | 23 | public String getId() { 24 | return id; 25 | } 26 | 27 | public void setId(String id) { 28 | this.id = id; 29 | } 30 | 31 | public String getUsername() { 32 | return username; 33 | } 34 | 35 | public void setUsername(String username) { 36 | this.username = username; 37 | } 38 | 39 | public String getImageURL() { 40 | return imageURL; 41 | } 42 | 43 | public void setImageURL(String imageURL) { 44 | this.imageURL = imageURL; 45 | } 46 | 47 | public String getStatus() { 48 | return status; 49 | } 50 | 51 | public void setStatus(String status) { 52 | this.status = status; 53 | } 54 | 55 | public String getSearch() { 56 | return search; 57 | } 58 | 59 | public void setSearch(String search) { 60 | this.search = search; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Notifications/Client.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Notifications; 2 | 3 | import retrofit2.Retrofit; 4 | import retrofit2.converter.gson.GsonConverterFactory; 5 | 6 | public class Client { 7 | 8 | private static Retrofit retrofit = null; 9 | 10 | public static Retrofit getClient(String url){ 11 | if (retrofit == null){ 12 | retrofit = new Retrofit.Builder() 13 | .baseUrl(url) 14 | .addConverterFactory(GsonConverterFactory.create()) 15 | .build(); 16 | } 17 | return retrofit; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Notifications/Data.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Notifications; 2 | 3 | public class Data { 4 | private String user; 5 | private int icon; 6 | private String body; 7 | private String title; 8 | private String sented; 9 | 10 | public Data(String user, int icon, String body, String title, String sented) { 11 | this.user = user; 12 | this.icon = icon; 13 | this.body = body; 14 | this.title = title; 15 | this.sented = sented; 16 | } 17 | 18 | public Data() { 19 | } 20 | 21 | public String getUser() { 22 | return user; 23 | } 24 | 25 | public void setUser(String user) { 26 | this.user = user; 27 | } 28 | 29 | public int getIcon() { 30 | return icon; 31 | } 32 | 33 | public void setIcon(int icon) { 34 | this.icon = icon; 35 | } 36 | 37 | public String getBody() { 38 | return body; 39 | } 40 | 41 | public void setBody(String body) { 42 | this.body = body; 43 | } 44 | 45 | public String getTitle() { 46 | return title; 47 | } 48 | 49 | public void setTitle(String title) { 50 | this.title = title; 51 | } 52 | 53 | public String getSented() { 54 | return sented; 55 | } 56 | 57 | public void setSented(String sented) { 58 | this.sented = sented; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Notifications/MyFirebaseIdService.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Notifications; 2 | 3 | import com.google.firebase.auth.FirebaseAuth; 4 | import com.google.firebase.auth.FirebaseUser; 5 | import com.google.firebase.database.DatabaseReference; 6 | import com.google.firebase.database.FirebaseDatabase; 7 | import com.google.firebase.iid.FirebaseInstanceId; 8 | import com.google.firebase.iid.FirebaseInstanceIdService; 9 | 10 | public class MyFirebaseIdService extends FirebaseInstanceIdService { 11 | 12 | @Override 13 | public void onTokenRefresh() { 14 | super.onTokenRefresh(); 15 | FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); 16 | 17 | String refreshToken = FirebaseInstanceId.getInstance().getToken(); 18 | if (firebaseUser != null){ 19 | updateToken(refreshToken); 20 | } 21 | } 22 | 23 | private void updateToken(String refreshToken) { 24 | FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); 25 | 26 | DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Tokens"); 27 | Token token = new Token(refreshToken); 28 | reference.child(firebaseUser.getUid()).setValue(token); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Notifications/MyFirebaseMessaging.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Notifications; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationManager; 5 | import android.app.PendingIntent; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.SharedPreferences; 9 | import android.media.RingtoneManager; 10 | import android.net.Uri; 11 | import android.os.Build; 12 | import android.os.Bundle; 13 | import android.support.v4.app.NotificationCompat; 14 | 15 | import com.google.firebase.auth.FirebaseAuth; 16 | import com.google.firebase.auth.FirebaseUser; 17 | import com.google.firebase.messaging.FirebaseMessagingService; 18 | import com.google.firebase.messaging.RemoteMessage; 19 | import com.koddev.chatapp.MessageActivity; 20 | 21 | public class MyFirebaseMessaging extends FirebaseMessagingService { 22 | 23 | @Override 24 | public void onMessageReceived(RemoteMessage remoteMessage) { 25 | super.onMessageReceived(remoteMessage); 26 | 27 | String sented = remoteMessage.getData().get("sented"); 28 | String user = remoteMessage.getData().get("user"); 29 | 30 | SharedPreferences preferences = getSharedPreferences("PREFS", MODE_PRIVATE); 31 | String currentUser = preferences.getString("currentuser", "none"); 32 | 33 | FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); 34 | 35 | if (firebaseUser != null && sented.equals(firebaseUser.getUid())){ 36 | if (!currentUser.equals(user)) { 37 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 38 | sendOreoNotification(remoteMessage); 39 | } else { 40 | sendNotification(remoteMessage); 41 | } 42 | } 43 | } 44 | } 45 | 46 | private void sendOreoNotification(RemoteMessage remoteMessage){ 47 | String user = remoteMessage.getData().get("user"); 48 | String icon = remoteMessage.getData().get("icon"); 49 | String title = remoteMessage.getData().get("title"); 50 | String body = remoteMessage.getData().get("body"); 51 | 52 | RemoteMessage.Notification notification = remoteMessage.getNotification(); 53 | int j = Integer.parseInt(user.replaceAll("[\\D]", "")); 54 | Intent intent = new Intent(this, MessageActivity.class); 55 | Bundle bundle = new Bundle(); 56 | bundle.putString("userid", user); 57 | intent.putExtras(bundle); 58 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 59 | PendingIntent pendingIntent = PendingIntent.getActivity(this, j, intent, PendingIntent.FLAG_ONE_SHOT); 60 | Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); 61 | 62 | OreoNotification oreoNotification = new OreoNotification(this); 63 | Notification.Builder builder = oreoNotification.getOreoNotification(title, body, pendingIntent, 64 | defaultSound, icon); 65 | 66 | int i = 0; 67 | if (j > 0){ 68 | i = j; 69 | } 70 | 71 | oreoNotification.getManager().notify(i, builder.build()); 72 | 73 | } 74 | 75 | private void sendNotification(RemoteMessage remoteMessage) { 76 | 77 | String user = remoteMessage.getData().get("user"); 78 | String icon = remoteMessage.getData().get("icon"); 79 | String title = remoteMessage.getData().get("title"); 80 | String body = remoteMessage.getData().get("body"); 81 | 82 | RemoteMessage.Notification notification = remoteMessage.getNotification(); 83 | int j = Integer.parseInt(user.replaceAll("[\\D]", "")); 84 | Intent intent = new Intent(this, MessageActivity.class); 85 | Bundle bundle = new Bundle(); 86 | bundle.putString("userid", user); 87 | intent.putExtras(bundle); 88 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 89 | PendingIntent pendingIntent = PendingIntent.getActivity(this, j, intent, PendingIntent.FLAG_ONE_SHOT); 90 | 91 | Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); 92 | NotificationCompat.Builder builder = new NotificationCompat.Builder(this) 93 | .setSmallIcon(Integer.parseInt(icon)) 94 | .setContentTitle(title) 95 | .setContentText(body) 96 | .setAutoCancel(true) 97 | .setSound(defaultSound) 98 | .setContentIntent(pendingIntent); 99 | NotificationManager noti = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); 100 | 101 | int i = 0; 102 | if (j > 0){ 103 | i = j; 104 | } 105 | 106 | noti.notify(i, builder.build()); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Notifications/MyResponse.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Notifications; 2 | 3 | public class MyResponse { 4 | 5 | public int success; 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Notifications/OreoNotification.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Notifications; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Notification; 5 | import android.app.NotificationChannel; 6 | import android.app.NotificationManager; 7 | import android.app.PendingIntent; 8 | import android.content.Context; 9 | import android.content.ContextWrapper; 10 | import android.net.Uri; 11 | import android.os.Build; 12 | 13 | public class OreoNotification extends ContextWrapper { 14 | 15 | private static final String CHANNEL_ID = "com.koddev.chatapp"; 16 | private static final String CHANNEL_NAME = "chatapp"; 17 | 18 | private NotificationManager notificationManager; 19 | 20 | public OreoNotification(Context base) { 21 | super(base); 22 | 23 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ 24 | createChannel(); 25 | } 26 | } 27 | 28 | @TargetApi(Build.VERSION_CODES.O) 29 | private void createChannel() { 30 | 31 | NotificationChannel channel = new NotificationChannel(CHANNEL_ID, 32 | CHANNEL_NAME, 33 | NotificationManager.IMPORTANCE_DEFAULT); 34 | channel.enableLights(false); 35 | channel.enableVibration(true); 36 | channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); 37 | 38 | getManager().createNotificationChannel(channel); 39 | } 40 | 41 | public NotificationManager getManager(){ 42 | if (notificationManager == null){ 43 | notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); 44 | } 45 | 46 | return notificationManager; 47 | } 48 | 49 | @TargetApi(Build.VERSION_CODES.O) 50 | public Notification.Builder getOreoNotification(String title, String body, 51 | PendingIntent pendingIntent, Uri soundUri, String icon){ 52 | return new Notification.Builder(getApplicationContext(), CHANNEL_ID) 53 | .setContentIntent(pendingIntent) 54 | .setContentTitle(title) 55 | .setContentText(body) 56 | .setSmallIcon(Integer.parseInt(icon)) 57 | .setSound(soundUri) 58 | .setAutoCancel(true); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Notifications/Sender.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Notifications; 2 | 3 | public class Sender { 4 | public Data data; 5 | public String to; 6 | 7 | public Sender(Data data, String to) { 8 | this.data = data; 9 | this.to = to; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/Notifications/Token.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp.Notifications; 2 | 3 | public class Token { 4 | private String token; 5 | 6 | public Token(String token) { 7 | this.token = token; 8 | } 9 | 10 | public Token() { 11 | } 12 | 13 | public String getToken() { 14 | return token; 15 | } 16 | 17 | public void setToken(String token) { 18 | this.token = token; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/RegisterActivity.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.Toolbar; 8 | import android.text.TextUtils; 9 | import android.view.View; 10 | import android.widget.Button; 11 | import android.widget.Toast; 12 | 13 | import com.google.android.gms.tasks.OnCompleteListener; 14 | import com.google.android.gms.tasks.Task; 15 | import com.google.firebase.auth.AuthResult; 16 | import com.google.firebase.auth.FirebaseAuth; 17 | import com.google.firebase.auth.FirebaseUser; 18 | import com.google.firebase.database.DatabaseReference; 19 | import com.google.firebase.database.FirebaseDatabase; 20 | import com.rengwuxian.materialedittext.MaterialEditText; 21 | 22 | import java.util.HashMap; 23 | 24 | public class RegisterActivity extends AppCompatActivity { 25 | 26 | MaterialEditText username, email, password; 27 | Button btn_register; 28 | 29 | FirebaseAuth auth; 30 | DatabaseReference reference; 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_register); 36 | 37 | Toolbar toolbar = findViewById(R.id.toolbar); 38 | setSupportActionBar(toolbar); 39 | getSupportActionBar().setTitle("Register"); 40 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 41 | 42 | username = findViewById(R.id.username); 43 | email = findViewById(R.id.email); 44 | password = findViewById(R.id.password); 45 | btn_register = findViewById(R.id.btn_register); 46 | 47 | auth = FirebaseAuth.getInstance(); 48 | 49 | btn_register.setOnClickListener(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View view) { 52 | String txt_username = username.getText().toString(); 53 | String txt_email = email.getText().toString(); 54 | String txt_password = password.getText().toString(); 55 | 56 | if (TextUtils.isEmpty(txt_username) || TextUtils.isEmpty(txt_email) || TextUtils.isEmpty(txt_password)){ 57 | Toast.makeText(RegisterActivity.this, "All fileds are required", Toast.LENGTH_SHORT).show(); 58 | } else if (txt_password.length() < 6 ){ 59 | Toast.makeText(RegisterActivity.this, "password must be at least 6 characters", Toast.LENGTH_SHORT).show(); 60 | } else { 61 | register(txt_username, txt_email, txt_password); 62 | } 63 | } 64 | }); 65 | } 66 | 67 | private void register(final String username, String email, String password){ 68 | 69 | auth.createUserWithEmailAndPassword(email, password) 70 | .addOnCompleteListener(new OnCompleteListener() { 71 | @Override 72 | public void onComplete(@NonNull Task task) { 73 | if (task.isSuccessful()){ 74 | FirebaseUser firebaseUser = auth.getCurrentUser(); 75 | assert firebaseUser != null; 76 | String userid = firebaseUser.getUid(); 77 | 78 | reference = FirebaseDatabase.getInstance().getReference("Users").child(userid); 79 | 80 | HashMap hashMap = new HashMap<>(); 81 | hashMap.put("id", userid); 82 | hashMap.put("username", username); 83 | hashMap.put("imageURL", "default"); 84 | hashMap.put("status", "offline"); 85 | hashMap.put("search", username.toLowerCase()); 86 | 87 | reference.setValue(hashMap).addOnCompleteListener(new OnCompleteListener() { 88 | @Override 89 | public void onComplete(@NonNull Task task) { 90 | if (task.isSuccessful()){ 91 | Intent intent = new Intent(RegisterActivity.this, MainActivity.class); 92 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); 93 | startActivity(intent); 94 | finish(); 95 | } 96 | } 97 | }); 98 | } else { 99 | Toast.makeText(RegisterActivity.this, "You can't register woth this email or password", Toast.LENGTH_SHORT).show(); 100 | } 101 | } 102 | }); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/ResetPasswordActivity.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp; 2 | 3 | import android.content.Intent; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.EditText; 11 | import android.widget.Toast; 12 | 13 | import com.google.android.gms.tasks.OnCompleteListener; 14 | import com.google.android.gms.tasks.Task; 15 | import com.google.firebase.auth.FirebaseAuth; 16 | 17 | public class ResetPasswordActivity extends AppCompatActivity { 18 | 19 | EditText send_email; 20 | Button btn_reset; 21 | 22 | FirebaseAuth firebaseAuth; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_reset_password); 28 | 29 | Toolbar toolbar = findViewById(R.id.toolbar); 30 | setSupportActionBar(toolbar); 31 | getSupportActionBar().setTitle("Reset Password"); 32 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 33 | 34 | send_email = findViewById(R.id.send_email); 35 | btn_reset = findViewById(R.id.btn_reset); 36 | 37 | firebaseAuth = FirebaseAuth.getInstance(); 38 | 39 | btn_reset.setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View view) { 42 | String email = send_email.getText().toString(); 43 | 44 | if (email.equals("")){ 45 | Toast.makeText(ResetPasswordActivity.this, "All fileds are required!", Toast.LENGTH_SHORT).show(); 46 | } else { 47 | firebaseAuth.sendPasswordResetEmail(email).addOnCompleteListener(new OnCompleteListener() { 48 | @Override 49 | public void onComplete(@NonNull Task task) { 50 | if (task.isSuccessful()){ 51 | Toast.makeText(ResetPasswordActivity.this, "Please check you Email", Toast.LENGTH_SHORT).show(); 52 | startActivity(new Intent(ResetPasswordActivity.this, LoginActivity.class)); 53 | } else { 54 | String error = task.getException().getMessage(); 55 | Toast.makeText(ResetPasswordActivity.this, error, Toast.LENGTH_SHORT).show(); 56 | } 57 | } 58 | }); 59 | } 60 | } 61 | }); 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/koddev/chatapp/StartActivity.java: -------------------------------------------------------------------------------- 1 | package com.koddev.chatapp; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.widget.Button; 8 | 9 | import com.google.firebase.auth.FirebaseAuth; 10 | import com.google.firebase.auth.FirebaseUser; 11 | 12 | public class StartActivity extends AppCompatActivity { 13 | 14 | Button login, register; 15 | 16 | FirebaseUser firebaseUser; 17 | 18 | @Override 19 | protected void onStart() { 20 | super.onStart(); 21 | 22 | firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); 23 | 24 | //check if user is null 25 | if (firebaseUser != null){ 26 | Intent intent = new Intent(StartActivity.this, MainActivity.class); 27 | startActivity(intent); 28 | finish(); 29 | } 30 | } 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_start); 36 | 37 | 38 | 39 | login = findViewById(R.id.login); 40 | register = findViewById(R.id.register); 41 | 42 | login.setOnClickListener(new View.OnClickListener() { 43 | @Override 44 | public void onClick(View view) { 45 | startActivity(new Intent(StartActivity.this, LoginActivity.class)); 46 | } 47 | }); 48 | 49 | register.setOnClickListener(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View view) { 52 | startActivity(new Intent(StartActivity.this, RegisterActivity.class)); 53 | } 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_action_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/majlindavdylaj/ChatAppTutorial/4eea5c5d4100ab1e73661f02a04695d12176c0d0/app/src/main/res/drawable-hdpi/ic_action_name.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_action_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/majlindavdylaj/ChatAppTutorial/4eea5c5d4100ab1e73661f02a04695d12176c0d0/app/src/main/res/drawable-mdpi/ic_action_name.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_action_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/majlindavdylaj/ChatAppTutorial/4eea5c5d4100ab1e73661f02a04695d12176c0d0/app/src/main/res/drawable-xhdpi/ic_action_name.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_action_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/majlindavdylaj/ChatAppTutorial/4eea5c5d4100ab1e73661f02a04695d12176c0d0/app/src/main/res/drawable-xxhdpi/ic_action_name.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 20 | 21 | 27 | 28 | 36 | 37 | 45 | 46 |