├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── fir-chat-a154a-export.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── crazyhitty │ │ └── chdev │ │ └── ks │ │ └── firebasechat │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── crazyhitty │ │ │ └── chdev │ │ │ └── ks │ │ │ └── firebasechat │ │ │ ├── FirebaseChatMainApp.java │ │ │ ├── core │ │ │ ├── chat │ │ │ │ ├── ChatContract.java │ │ │ │ ├── ChatInteractor.java │ │ │ │ └── ChatPresenter.java │ │ │ ├── login │ │ │ │ ├── LoginContract.java │ │ │ │ ├── LoginInteractor.java │ │ │ │ └── LoginPresenter.java │ │ │ ├── logout │ │ │ │ ├── LogoutContract.java │ │ │ │ ├── LogoutInteractor.java │ │ │ │ └── LogoutPresenter.java │ │ │ ├── registration │ │ │ │ ├── RegisterContract.java │ │ │ │ ├── RegisterInteractor.java │ │ │ │ └── RegisterPresenter.java │ │ │ └── users │ │ │ │ ├── add │ │ │ │ ├── AddUserContract.java │ │ │ │ ├── AddUserInteractor.java │ │ │ │ └── AddUserPresenter.java │ │ │ │ └── get │ │ │ │ └── all │ │ │ │ ├── GetUsersContract.java │ │ │ │ ├── GetUsersInteractor.java │ │ │ │ └── GetUsersPresenter.java │ │ │ ├── events │ │ │ └── PushNotificationEvent.java │ │ │ ├── fcm │ │ │ ├── FcmNotificationBuilder.java │ │ │ ├── MyFirebaseInstanceIDService.java │ │ │ └── MyFirebaseMessagingService.java │ │ │ ├── models │ │ │ ├── Chat.java │ │ │ ├── User.java │ │ │ └── Users.java │ │ │ ├── ui │ │ │ ├── activities │ │ │ │ ├── ChatActivity.java │ │ │ │ ├── LoginActivity.java │ │ │ │ ├── RegisterActivity.java │ │ │ │ ├── SplashActivity.java │ │ │ │ └── UserListingActivity.java │ │ │ ├── adapters │ │ │ │ ├── ChatRecyclerAdapter.java │ │ │ │ ├── UserListingPagerAdapter.java │ │ │ │ └── UserListingRecyclerAdapter.java │ │ │ └── fragments │ │ │ │ ├── ChatFragment.java │ │ │ │ ├── LoginFragment.java │ │ │ │ ├── RegisterFragment.java │ │ │ │ └── UsersFragment.java │ │ │ └── utils │ │ │ ├── Constants.java │ │ │ ├── ItemClickSupport.java │ │ │ ├── NetworkConnectionUtil.java │ │ │ └── SharedPrefUtil.java │ └── res │ │ ├── drawable-hdpi-v11 │ │ └── ic_messaging.png │ │ ├── drawable-hdpi │ │ └── ic_messaging.png │ │ ├── drawable-mdpi-v11 │ │ └── ic_messaging.png │ │ ├── drawable-mdpi │ │ └── ic_messaging.png │ │ ├── drawable-nodpi │ │ └── firebase_chat_splash.jpg │ │ ├── drawable-xhdpi-v11 │ │ └── ic_messaging.png │ │ ├── drawable-xhdpi │ │ └── ic_messaging.png │ │ ├── drawable-xxhdpi-v11 │ │ └── ic_messaging.png │ │ ├── drawable-xxhdpi │ │ └── ic_messaging.png │ │ ├── drawable-xxxhdpi-v11 │ │ └── ic_messaging.png │ │ ├── drawable-xxxhdpi │ │ └── ic_messaging.png │ │ ├── drawable │ │ ├── chat_rounded_rect_bg.xml │ │ ├── circle_accent.xml │ │ ├── ic_error_24dp.xml │ │ └── rounded_rect_bg.xml │ │ ├── layout │ │ ├── activity_chat.xml │ │ ├── activity_login.xml │ │ ├── activity_register.xml │ │ ├── activity_splash.xml │ │ ├── activity_user_listing.xml │ │ ├── fragment_chat.xml │ │ ├── fragment_login.xml │ │ ├── fragment_register.xml │ │ ├── fragment_users.xml │ │ ├── item_all_user_listing.xml │ │ ├── item_chat_mine.xml │ │ ├── item_chat_other.xml │ │ └── item_user_listing.xml │ │ ├── menu │ │ └── menu_user_listing.xml │ │ ├── mipmap-hdpi │ │ └── ic_logo.png │ │ ├── mipmap-mdpi │ │ └── ic_logo.png │ │ ├── mipmap-xhdpi │ │ └── ic_logo.png │ │ ├── mipmap-xxhdpi │ │ └── ic_logo.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_logo.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── crazyhitty │ └── chdev │ └── ks │ └── firebasechat │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── chat.png ├── login.png ├── push_notification.png ├── splash.png └── users.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | /app/build 10 | /app/google-services.json 11 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Kartik Sharma 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Firebase chat 2 | One to one chat implementation using firebase. 3 | 4 | # Introduction: Why implement chat with firebase? 5 | 6 | Because it's easier and you can create a working app with one to one chat system in a single day. Let's consider some pros and cons of firebase if we use it as a back end for our chat application. 7 | 8 | ###### Pros 9 | 10 | * Firebase has a realtime database, that means you just need to add appropriate listeners in your app and you will automatically get notified when something is updated in the database. 11 | * It uses json format (key/value pairs) to represent its database which can be user friendly to some of the users who deal with json data on day to day basis. 12 | * It's very fast and manages offline states automatically. 13 | * It also has a authentication system through which you can provide proper login/signup for users. 14 | 15 | ###### Cons 16 | 17 | * No straightforward api available for sending push notification from one device to another (without the use of a separate backend). 18 | * No inbuilt encryption, you would have to implement your own encryption for chatting. 19 | 20 | # Dependencies required for firebase 21 | 22 | Add this line to your project level build.gradle file in [**dependencies**](https://github.com/crazyhitty/firebase-chat/blob/master/build.gradle#L9) section. 23 | 24 | ``` 25 | classpath 'com.google.gms:google-services:3.0.0' 26 | ``` 27 | 28 | Then, add these to your app level build.gradle file in [**dependencies**](https://github.com/crazyhitty/firebase-chat/blob/master/app/build.gradle) section. 29 | 30 | ``` 31 | // firebase related dependencies 32 | compile 'com.google.firebase:firebase-database:9.6.1' 33 | compile 'com.google.firebase:firebase-messaging:9.6.1' 34 | compile 'com.google.firebase:firebase-auth:9.6.1' 35 | ``` 36 | 37 | Don't forget to apply google services plugin at the end of your app level build.gradle file. 38 | 39 | ``` 40 | apply plugin: 'com.google.gms.google-services' 41 | ``` 42 | 43 | Also, add [google-services.json](https://support.google.com/firebase/answer/7015592) associated with your project to the app module. 44 | 45 | # Understanding firebase database 46 | 47 | Before we get our hands dirty in android studio, we must understand how firebase database is structured so we don't get confused in the later stages. 48 | 49 | As you would have guessed by now, firebase database is structured in a json format. So let's suppose we have to save a user's information in firebase, then we will write the data in this format: 50 | 51 | ``` 52 | { 53 | "user": { 54 | "name": "Kartik", 55 | "age": 22, 56 | "hobby": "video games" 57 | } 58 | } 59 | ``` 60 | 61 | We can write this piece of data in our application by first creating a model class for a user which will contain name, age and hobby fields. 62 | 63 | ``` 64 | public class User { 65 | public String name; 66 | public int age; 67 | public String hobby; 68 | 69 | public User() { 70 | } 71 | 72 | public User(String name, int age, String hobby) { 73 | this.name = name; 74 | this.age = age; 75 | this.hobby = hobby; 76 | } 77 | } 78 | ``` 79 | 80 | Then we can get database reference of firebase and add the object of User class to child "user" to save it in the database. 81 | 82 | ``` 83 | User user = new User("Kartik", 22, "video games"); 84 | FirebaseDatabase.getInstance() 85 | .getReference() 86 | .child("user") 87 | .setValue(user); 88 | ``` 89 | 90 | Now you can easily add data to firebase database, yay! But wait… what if you wanted to add multiple users. In the above scenario the data for “user” will be always replaced instead of maintaining a list. So let's create a list of users. 91 | 92 | ``` 93 | { 94 | "users": { 95 | "unique_id_1": { 96 | "name": "Kartik", 97 | "age": 22, 98 | "hobby": "video games" 99 | }, 100 | "unique_id_2": { 101 | "name": "Kajal", 102 | "age": 22, 103 | "hobby": "studying" 104 | } 105 | } 106 | } 107 | ``` 108 | 109 | We can achieve a somewhat similar format by using **push()** method instead of using **setValue(Object object)** method. This would generate random keys for your user's object. But this would make it difficult to find a particular user without the knowledge of that random key. So instead, we will add key based on unique uid of user which can be retrieved from **FirebaseAuth** class. 110 | 111 | ``` 112 | User user1 = new User("Kartik", 22, "video games"); 113 | FirebaseDatabase.getInstance() 114 | .getReference() 115 | .child("users") 116 | .child("unique_id_1") 117 | .setValue(user1); 118 | 119 | User user2 = new User("Kajal", 22, "studying"); 120 | FirebaseDatabase.getInstance() 121 | .getReference() 122 | .child("users") 123 | .child("unique_id_2") 124 | .setValue(user2); 125 | ``` 126 | 127 | Now we have learned how to create a single object and a object containing multiple list of similar objects. 128 | 129 | # Creating appropriate model classes for firebase 130 | 131 | Let's create a list of model classes we will be requiring in this project: 132 | 133 | ###### User.java 134 | 135 | ``` 136 | public class User { 137 | public String uid; 138 | public String email; 139 | public String firebaseToken; 140 | 141 | public User() {} 142 | 143 | public User(String uid, String email, String firebaseToken) { 144 | this.uid = uid; 145 | this.email = email; 146 | this.firebaseToken = firebaseToken; 147 | } 148 | } 149 | ``` 150 | 151 | ###### Chat.java 152 | 153 | ``` 154 | public class Chat { 155 | public String sender; 156 | public String receiver; 157 | public String senderUid; 158 | public String receiverUid; 159 | public String message; 160 | public long timestamp; 161 | 162 | public Chat() {} 163 | 164 | public Chat(String sender, String receiver, String senderUid, String receiverUid, String message, long timestamp) { 165 | this.sender = sender; 166 | this.receiver = receiver; 167 | this.senderUid = senderUid; 168 | this.receiverUid = receiverUid; 169 | this.message = message; 170 | this.timestamp = timestamp; 171 | } 172 | } 173 | ``` 174 | 175 | **Note:** Make sure to add an empty constructor to your model classes as sometimes firebase crashes due to the lack of empty constructors. 176 | 177 | # Creating users for our application 178 | 179 | Well we need users for our app, so we need to find a way to add them to our backend. In the application I have created, I add users to the database after they signup using **FirebaseAuth**. You can skip the authorization part and directly add them to firebase database also. But I would recommend using **FirebaseAuth** as it would make your life a little bit easier and reduce the development time too. 180 | 181 | In order to add a new user, we fill the data in our model class and then add this object to our "users" child using the same method as we used above. 182 | 183 | ``` 184 | public void addUserToDatabase(Context context, FirebaseUser firebaseUser) { 185 | User user = new User(firebaseUser.getUid(), 186 | firebaseUser.getEmail(), 187 | new SharedPrefUtil(context).getString(Constants.ARG_FIREBASE_TOKEN)); 188 | FirebaseDatabase.getInstance() 189 | .getReference() 190 | .child(Constants.ARG_USERS) 191 | .child(firebaseUser.getUid()) 192 | .setValue(user) 193 | .addOnCompleteListener(new OnCompleteListener () { 194 | @Override 195 | public void onComplete(@NonNull Task task) { 196 | if (task.isSuccessful()) { 197 | // successfully added user 198 | } else { 199 | // failed to add user 200 | } 201 | } 202 | }); 203 | } 204 | ``` 205 | 206 | # Getting list of users 207 | 208 | Now, the next step is to show listing of available users so that we can select one of them and start chatting. 209 | 210 | We need to bind a single time listener to the "users" child so that we can get the initial listing of available users. 211 | 212 | ``` 213 | public void getAllUsersFromFirebase() { 214 | FirebaseDatabase.getInstance() 215 | .getReference() 216 | .child(Constants.ARG_USERS) 217 | .addListenerForSingleValueEvent(new ValueEventListener() { 218 | @Override 219 | public void onDataChange(DataSnapshot dataSnapshot) { 220 | Iterator dataSnapshots = dataSnapshot.getChildren() 221 | .iterator(); 222 | List users = new ArrayList<>(); 223 | while (dataSnapshots.hasNext()) { 224 | DataSnapshot dataSnapshotChild = dataSnapshots.next(); 225 | User user = dataSnapshotChild.getValue(User.class); 226 | if (!TextUtils.equals(user.uid, 227 | FirebaseAuth.getInstance().getCurrentUser().getUid())) { 228 | users.add(user); 229 | } 230 | } 231 | // All users are retrieved except the one who is currently logged 232 | // in device. 233 | } 234 | 235 | @Override 236 | public void onCancelled(DatabaseError databaseError) { 237 | // Unable to retrieve the users. 238 | } 239 | }); 240 | } 241 | ``` 242 | 243 | # Chat rooms 244 | 245 | After retrieving the list of users we can create a chat room through which users will chat with each other. 246 | 247 | A chat room will consist of two users in case of one to one chat: 248 | 249 | * Currently logged in user. 250 | * User we want to chat with. 251 | 252 | For future references let's take two users: 253 | 254 | * Kartik (logged in user) 255 | * Kajal (other user Kartik wants to chat with) 256 | 257 | Now, we can create a child named "chat_rooms" in our database which will contain all of the data regarding chats between multiple users. We can further create a child of object “chat_rooms” like “Kartik_Kajal” or “Kajal_Kartik”. The reason behind this naming is to make the searching of chat rooms much easier on application's end. You can also use any sort of unique separator instead of underscore, just make sure that it doesn’t conflict with your usernames. 258 | 259 | Also, if Kartik is chatting with Kajal for the first time, a room with name “Kartik_Kajal” will be created otherwise if the case is reversed then “Kajal_Kartik” will be created. 260 | 261 | ``` 262 | public void sendMessageToFirebaseUser(final Context context, 263 | final Chat chat, 264 | final String receiverFirebaseToken) { 265 | final String room_type_1 = chat.senderUid + "_" + chat.receiverUid; 266 | final String room_type_2 = chat.receiverUid + "_" + chat.senderUid; 267 | 268 | final DatabaseReference databaseReference = FirebaseDatabase.getInstance() 269 | .getReference(); 270 | 271 | databaseReference.child(Constants.ARG_CHAT_ROOMS) 272 | .getRef() 273 | .addListenerForSingleValueEvent(new ValueEventListener() { 274 | @Override 275 | public void onDataChange(DataSnapshot dataSnapshot) { 276 | if (dataSnapshot.hasChild(room_type_1)) { 277 | Log.e(TAG, "sendMessageToFirebaseUser: " + room_type_1 + " exists"); 278 | databaseReference.child(Constants.ARG_CHAT_ROOMS) 279 | .child(room_type_1) 280 | .child(String.valueOf(chat.timestamp)) 281 | .setValue(chat); 282 | } else if (dataSnapshot.hasChild(room_type_2)) { 283 | Log.e(TAG, "sendMessageToFirebaseUser: " + room_type_2 + " exists"); 284 | databaseReference.child(Constants.ARG_CHAT_ROOMS) 285 | .child(room_type_2) 286 | .child(String.valueOf(chat.timestamp)) 287 | .setValue(chat); 288 | } else { 289 | Log.e(TAG, "sendMessageToFirebaseUser: success"); 290 | databaseReference.child(Constants.ARG_CHAT_ROOMS) 291 | .child(room_type_1) 292 | .child(String.valueOf(chat.timestamp)) 293 | .setValue(chat); 294 | } 295 | } 296 | 297 | @Override 298 | public void onCancelled(DatabaseError databaseError) { 299 | // Unable to send message. 300 | } 301 | }); 302 | } 303 | ``` 304 | 305 | We can get list of chat messages by adding a listener to either “Kartik_Kajal” or “Kajal_Kartik” depending upon which one exists. In order to check which one exists we can use method hasChild on “chat_rooms” object. 306 | 307 | ``` 308 | public void getMessageFromFirebaseUser(String senderUid, String receiverUid) { 309 | final String room_type_1 = senderUid + "_" + receiverUid; 310 | final String room_type_2 = receiverUid + "_" + senderUid; 311 | 312 | final DatabaseReference databaseReference = FirebaseDatabase.getInstance() 313 | .getReference(); 314 | 315 | databaseReference.child(Constants.ARG_CHAT_ROOMS) 316 | .getRef() 317 | .addListenerForSingleValueEvent(new ValueEventListener() { 318 | @Override 319 | public void onDataChange(DataSnapshot dataSnapshot) { 320 | if (dataSnapshot.hasChild(room_type_1)) { 321 | Log.e(TAG, "getMessageFromFirebaseUser: " + room_type_1 + " exists"); 322 | FirebaseDatabase.getInstance() 323 | .getReference() 324 | .child(Constants.ARG_CHAT_ROOMS) 325 | .child(room_type_1) 326 | .addChildEventListener(new ChildEventListener() { 327 | @Override 328 | public void onChildAdded(DataSnapshot dataSnapshot, String s) { 329 | // Chat message is retreived. 330 | Chat chat = dataSnapshot.getValue(Chat.class); 331 | } 332 | 333 | @Override 334 | public void onChildChanged(DataSnapshot dataSnapshot, String s) { 335 | 336 | } 337 | 338 | @Override 339 | public void onChildRemoved(DataSnapshot dataSnapshot) { 340 | 341 | } 342 | 343 | @Override 344 | public void onChildMoved(DataSnapshot dataSnapshot, String s) { 345 | 346 | } 347 | 348 | @Override 349 | public void onCancelled(DatabaseError databaseError) { 350 | // Unable to get message. 351 | } 352 | }); 353 | } else if (dataSnapshot.hasChild(room_type_2)) { 354 | Log.e(TAG, "getMessageFromFirebaseUser: " + room_type_2 + " exists"); 355 | FirebaseDatabase.getInstance() 356 | .getReference() 357 | .child(Constants.ARG_CHAT_ROOMS) 358 | .child(room_type_2) 359 | .addChildEventListener(new ChildEventListener() { 360 | @Override 361 | public void onChildAdded(DataSnapshot dataSnapshot, String s) { 362 | // Chat message is retreived. 363 | Chat chat = dataSnapshot.getValue(Chat.class); 364 | } 365 | 366 | @Override 367 | public void onChildChanged(DataSnapshot dataSnapshot, String s) { 368 | 369 | } 370 | 371 | @Override 372 | public void onChildRemoved(DataSnapshot dataSnapshot) { 373 | 374 | } 375 | 376 | @Override 377 | public void onChildMoved(DataSnapshot dataSnapshot, String s) { 378 | 379 | } 380 | 381 | @Override 382 | public void onCancelled(DatabaseError databaseError) { 383 | // Unable to get message. 384 | } 385 | }); 386 | } else { 387 | Log.e(TAG, "getMessageFromFirebaseUser: no such room available"); 388 | } 389 | } 390 | 391 | @Override 392 | public void onCancelled(DatabaseError databaseError) { 393 | // Unable to get message 394 | } 395 | }); 396 | } 397 | ``` 398 | 399 | The above listener will give callbacks on every new chat message added to the firebase database inside the “Kartik_Kajal” chatroom. 400 | 401 | # Sending push notifications to users 402 | 403 | If you want to send a push notification to a particular user, we would have to use firebase push notifications api. 404 | 405 | Before that make sure that you have generated a firebase token (using fcm aka firebase cloud messaging) for your user and saved it in your users table in firebase for every individual user. 406 | 407 | [Link to firebase cloud messaging for android tutorial.](https://firebase.google.com/docs/cloud-messaging/android/client) 408 | 409 | After you have integrated the code to generate a firebase token, then we can test sample notifications by manually hitting the api in postman. 410 | 411 | ![Postman screenshot for sending push notification](http://i.imgur.com/A8G7AtQ.png) 412 | 413 | Now, we can hit the same api using any rest client on our device with custom data object (containing extra information that you would like to send with you push notification). I have used okhttp for managing the api calls, but feel free to use any rest client as per your requirements. 414 | 415 | ``` 416 | import android.util.Log; 417 | 418 | import org.json.JSONException; 419 | import org.json.JSONObject; 420 | 421 | import java.io.IOException; 422 | 423 | import okhttp3.Call; 424 | import okhttp3.Callback; 425 | import okhttp3.MediaType; 426 | import okhttp3.OkHttpClient; 427 | import okhttp3.Request; 428 | import okhttp3.RequestBody; 429 | import okhttp3.Response; 430 | 431 | /** 432 | * Author: Kartik Sharma 433 | * Created on: 10/16/2016 , 1:53 PM 434 | * Project: FirebaseChat 435 | */ 436 | 437 | public class FcmNotificationBuilder { 438 | public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8"); 439 | private static final String TAG = "FcmNotificationBuilder"; 440 | private static final String SERVER_API_KEY = "YOUR_SERVER_API_KEY"; 441 | private static final String CONTENT_TYPE = "Content-Type"; 442 | private static final String APPLICATION_JSON = "application/json"; 443 | private static final String AUTHORIZATION = "Authorization"; 444 | private static final String AUTH_KEY = "key=" + SERVER_API_KEY; 445 | private static final String FCM_URL = "https://fcm.googleapis.com/fcm/send"; 446 | // json related keys 447 | private static final String KEY_TO = "to"; 448 | private static final String KEY_NOTIFICATION = "notification"; 449 | private static final String KEY_TITLE = "title"; 450 | private static final String KEY_TEXT = "text"; 451 | private static final String KEY_DATA = "data"; 452 | private static final String KEY_USERNAME = "username"; 453 | private static final String KEY_UID = "uid"; 454 | private static final String KEY_FCM_TOKEN = "fcm_token"; 455 | 456 | private String mTitle; 457 | private String mMessage; 458 | private String mUsername; 459 | private String mUid; 460 | private String mFirebaseToken; 461 | private String mReceiverFirebaseToken; 462 | 463 | private FcmNotificationBuilder() { 464 | 465 | } 466 | 467 | public static FcmNotificationBuilder initialize() { 468 | return new FcmNotificationBuilder(); 469 | } 470 | 471 | public FcmNotificationBuilder title(String title) { 472 | mTitle = title; 473 | return this; 474 | } 475 | 476 | public FcmNotificationBuilder message(String message) { 477 | mMessage = message; 478 | return this; 479 | } 480 | 481 | public FcmNotificationBuilder username(String username) { 482 | mUsername = username; 483 | return this; 484 | } 485 | 486 | public FcmNotificationBuilder uid(String uid) { 487 | mUid = uid; 488 | return this; 489 | } 490 | 491 | public FcmNotificationBuilder firebaseToken(String firebaseToken) { 492 | mFirebaseToken = firebaseToken; 493 | return this; 494 | } 495 | 496 | public FcmNotificationBuilder receiverFirebaseToken(String receiverFirebaseToken) { 497 | mReceiverFirebaseToken = receiverFirebaseToken; 498 | return this; 499 | } 500 | 501 | public void send() { 502 | RequestBody requestBody = null; 503 | try { 504 | requestBody = RequestBody.create(MEDIA_TYPE_JSON, getValidJsonBody().toString()); 505 | } catch (JSONException e) { 506 | e.printStackTrace(); 507 | } 508 | 509 | Request request = new Request.Builder() 510 | .addHeader(CONTENT_TYPE, APPLICATION_JSON) 511 | .addHeader(AUTHORIZATION, AUTH_KEY) 512 | .url(FCM_URL) 513 | .post(requestBody) 514 | .build(); 515 | 516 | Call call = new OkHttpClient().newCall(request); 517 | call.enqueue(new Callback() { 518 | @Override 519 | public void onFailure(Call call, IOException e) { 520 | Log.e(TAG, "onGetAllUsersFailure: " + e.getMessage()); 521 | } 522 | 523 | @Override 524 | public void onResponse(Call call, Response response) throws IOException { 525 | Log.e(TAG, "onResponse: " + response.body().string()); 526 | } 527 | }); 528 | } 529 | 530 | private JSONObject getValidJsonBody() throws JSONException { 531 | JSONObject jsonObjectBody = new JSONObject(); 532 | jsonObjectBody.put(KEY_TO, mReceiverFirebaseToken); 533 | 534 | JSONObject jsonObjectData = new JSONObject(); 535 | jsonObjectData.put(KEY_TITLE, mTitle); 536 | jsonObjectData.put(KEY_TEXT, mMessage); 537 | jsonObjectData.put(KEY_USERNAME, mUsername); 538 | jsonObjectData.put(KEY_UID, mUid); 539 | jsonObjectData.put(KEY_FCM_TOKEN, mFirebaseToken); 540 | jsonObjectBody.put(KEY_DATA, jsonObjectData); 541 | 542 | return jsonObjectBody; 543 | } 544 | } 545 | ``` 546 | 547 | Now you can easily create a one to one chatting system with inbuilt push notifications without the need of an extra backend, yay! 548 | 549 | # Screenshots 550 | 551 | alt text alt text 552 | 553 | alt text alt text 554 | 555 | alt text 556 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "24.0.3" 6 | defaultConfig { 7 | applicationId "com.crazyhitty.chdev.ks.firebasechat" 8 | minSdkVersion 17 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 26 | exclude group: 'com.android.support', module: 'support-annotations' 27 | }) 28 | 29 | compile 'com.android.support:appcompat-v7:24.2.1' 30 | compile 'com.android.support:design:24.2.1' 31 | 32 | // firebase related dependencies 33 | compile 'com.google.firebase:firebase-database:9.6.1' 34 | compile 'com.google.firebase:firebase-messaging:9.6.1' 35 | compile 'com.google.firebase:firebase-auth:9.6.1' 36 | 37 | // okhttp 38 | compile 'com.squareup.okhttp3:okhttp:3.4.1' 39 | 40 | // event bus 41 | compile 'org.greenrobot:eventbus:3.0.0' 42 | } 43 | 44 | 45 | apply plugin: 'com.google.gms.google-services' -------------------------------------------------------------------------------- /app/fir-chat-a154a-export.json: -------------------------------------------------------------------------------- 1 | { 2 | "chat_rooms": { 3 | "WGy6ypyaKLWdYaG9P9qUE7vXeXO2_faRJCuYYQuM3PVvicC5XkDuvJbB2": { 4 | "1476809803496": { 5 | "message": "hi", 6 | "receiver": "ez@ez.com", 7 | "receiverUid": "faRJCuYYQuM3PVvicC5XkDuvJbB2", 8 | "sender": "test@test.com", 9 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 10 | "timestamp": 1476809803496 11 | }, 12 | "1476809807381": { 13 | "message": "yo", 14 | "receiver": "ez@ez.com", 15 | "receiverUid": "faRJCuYYQuM3PVvicC5XkDuvJbB2", 16 | "sender": "test@test.com", 17 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 18 | "timestamp": 1476809807381 19 | }, 20 | "1476809834299": { 21 | "message": "yup m8", 22 | "receiver": "test@test.com", 23 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 24 | "sender": "ez@ez.com", 25 | "senderUid": "faRJCuYYQuM3PVvicC5XkDuvJbB2", 26 | "timestamp": 1476809834299 27 | }, 28 | "1476809835184": { 29 | "message": "", 30 | "receiver": "test@test.com", 31 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 32 | "sender": "ez@ez.com", 33 | "senderUid": "faRJCuYYQuM3PVvicC5XkDuvJbB2", 34 | "timestamp": 1476809835184 35 | }, 36 | "1476809844908": { 37 | "message": "....", 38 | "receiver": "test@test.com", 39 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 40 | "sender": "ez@ez.com", 41 | "senderUid": "faRJCuYYQuM3PVvicC5XkDuvJbB2", 42 | "timestamp": 1476809844908 43 | } 44 | }, 45 | "a256m4vRqDhm8IsJjR2XVX9IE353_WGy6ypyaKLWdYaG9P9qUE7vXeXO2": { 46 | "1476850098210": { 47 | "message": "hello", 48 | "receiver": "test@test.com", 49 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 50 | "sender": "pankaj@gmail.com", 51 | "senderUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 52 | "timestamp": 1476850098210 53 | }, 54 | "1476850123243": { 55 | "message": "hi", 56 | "receiver": "test@test.com", 57 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 58 | "sender": "pankaj@gmail.com", 59 | "senderUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 60 | "timestamp": 1476850123243 61 | }, 62 | "1476850126368": { 63 | "message": "hii", 64 | "receiver": "pankaj@gmail.com", 65 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 66 | "sender": "test@test.com", 67 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 68 | "timestamp": 1476850126368 69 | }, 70 | "1476850128335": { 71 | "message": "hii", 72 | "receiver": "pankaj@gmail.com", 73 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 74 | "sender": "test@test.com", 75 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 76 | "timestamp": 1476850128335 77 | }, 78 | "1476850141270": { 79 | "message": "hello", 80 | "receiver": "pankaj@gmail.com", 81 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 82 | "sender": "test@test.com", 83 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 84 | "timestamp": 1476850141270 85 | }, 86 | "1476850146434": { 87 | "message": "yo", 88 | "receiver": "test@test.com", 89 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 90 | "sender": "pankaj@gmail.com", 91 | "senderUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 92 | "timestamp": 1476850146434 93 | }, 94 | "1476850162752": { 95 | "message": "these emojis look awesome \uD83D\uDC74\uD83D\uDE3F\uD83D\uDC71\uD83D\uDC69\uD83D\uDC75\uD83D\uDC81\uD83D\uDC86\uD83D\uDC70", 96 | "receiver": "pankaj@gmail.com", 97 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 98 | "sender": "test@test.com", 99 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 100 | "timestamp": 1476850162752 101 | }, 102 | "1476850179702": { 103 | "message": "what tha hell ?", 104 | "receiver": "pankaj@gmail.com", 105 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 106 | "sender": "test@test.com", 107 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 108 | "timestamp": 1476850179702 109 | }, 110 | "1476850199114": { 111 | "message": "yo", 112 | "receiver": "test@test.com", 113 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 114 | "sender": "pankaj@gmail.com", 115 | "senderUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 116 | "timestamp": 1476850199114 117 | }, 118 | "1476850242843": { 119 | "message": "hii !", 120 | "receiver": "pankaj@gmail.com", 121 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 122 | "sender": "test@test.com", 123 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 124 | "timestamp": 1476850242843 125 | }, 126 | "1476850262288": { 127 | "message": "emojis", 128 | "receiver": "pankaj@gmail.com", 129 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 130 | "sender": "test@test.com", 131 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 132 | "timestamp": 1476850262288 133 | }, 134 | "1476850268543": { 135 | "message": "\uD83D\uDE46\uD83D\uDE46\uD83D\uDC86", 136 | "receiver": "pankaj@gmail.com", 137 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 138 | "sender": "test@test.com", 139 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 140 | "timestamp": 1476850268543 141 | }, 142 | "1476850294954": { 143 | "message": "yo", 144 | "receiver": "pankaj@gmail.com", 145 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 146 | "sender": "test@test.com", 147 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 148 | "timestamp": 1476850294954 149 | }, 150 | "1476850613707": { 151 | "message": "hi", 152 | "receiver": "test@test.com", 153 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 154 | "sender": "pankaj@gmail.com", 155 | "senderUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 156 | "timestamp": 1476850613707 157 | }, 158 | "1476850631716": { 159 | "message": "yo", 160 | "receiver": "pankaj@gmail.com", 161 | "receiverUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 162 | "sender": "test@test.com", 163 | "senderUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 164 | "timestamp": 1476850631716 165 | }, 166 | "1476851786540": { 167 | "message": "yello m8 \uD83D\uDE00", 168 | "receiver": "test@test.com", 169 | "receiverUid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2", 170 | "sender": "pankaj@gmail.com", 171 | "senderUid": "a256m4vRqDhm8IsJjR2XVX9IE353", 172 | "timestamp": 1476851786540 173 | } 174 | } 175 | }, 176 | "users": { 177 | "WGy6ypyaKLWdYaG9P9qUE7vXeXO2": { 178 | "email": "test@test.com", 179 | "firebaseToken": "dIEbZp1m1OU:APA91bGZlHf_hw9F6yGoli_7avaiV2vReBSH3aaAE4UdMhPPBVHwLSL0mytAqvOjQ7szSACXRa-W9fCF0xutu3ROTkUk8eDTr-Zr-pWBqVEegAcU7tbSSQ9XAU1j-xQ55AWuXHkHrZGo", 180 | "uid": "WGy6ypyaKLWdYaG9P9qUE7vXeXO2" 181 | }, 182 | "a256m4vRqDhm8IsJjR2XVX9IE353": { 183 | "email": "pankaj@gmail.com", 184 | "firebaseToken": "dvkpRfQIPC8:APA91bEihoAdlohR5PXr2RjEh47ovkyvY5rihRbu_VS8VX2gVgj6sNnXPQdO8zvH5nTsLq3EnJxYVlsnMcUhCdHkHVG22_rSwh5QXKIvQ4MpMCmj6IEBNPYE65iOs3C6oPr4DkKt5PnH", 185 | "uid": "a256m4vRqDhm8IsJjR2XVX9IE353" 186 | }, 187 | "faRJCuYYQuM3PVvicC5XkDuvJbB2": { 188 | "email": "ez@ez.com", 189 | "firebaseToken": "cvzs8SIqM7g:APA91bESCTNYcJkq1MleVyiEYMzL5NHYEihJYFbn8j9wvaWC7u0HAPCKHEnET1sffBS-yg1JT-sjNHu9xqDvyHan1kl6rJP8Xihm7B09Iuxqh66HmCYb9MqIqve6K_6n7e58FnylA4Dk", 190 | "uid": "faRJCuYYQuM3PVvicC5XkDuvJbB2" 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Kartik_ch\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/crazyhitty/chdev/ks/firebasechat/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat; 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.assertEquals; 11 | 12 | /** 13 | * Instrumentation 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() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.crazyhitty.chdev.ks.firebasechat", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 30 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/FirebaseChatMainApp.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat; 2 | 3 | import android.app.Application; 4 | 5 | /** 6 | * Author: Kartik Sharma 7 | * Created on: 10/16/2016 , 9:35 PM 8 | * Project: FirebaseChat 9 | */ 10 | 11 | public class FirebaseChatMainApp extends Application { 12 | private static boolean sIsChatActivityOpen = false; 13 | 14 | public static boolean isChatActivityOpen() { 15 | return sIsChatActivityOpen; 16 | } 17 | 18 | public static void setChatActivityOpen(boolean isChatActivityOpen) { 19 | FirebaseChatMainApp.sIsChatActivityOpen = isChatActivityOpen; 20 | } 21 | 22 | @Override 23 | public void onCreate() { 24 | super.onCreate(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/chat/ChatContract.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.chat; 2 | 3 | import android.content.Context; 4 | 5 | import com.crazyhitty.chdev.ks.firebasechat.models.Chat; 6 | 7 | /** 8 | * Author: Kartik Sharma 9 | * Created on: 8/28/2016 , 11:06 AM 10 | * Project: FirebaseChat 11 | */ 12 | 13 | public interface ChatContract { 14 | interface View { 15 | void onSendMessageSuccess(); 16 | 17 | void onSendMessageFailure(String message); 18 | 19 | void onGetMessagesSuccess(Chat chat); 20 | 21 | void onGetMessagesFailure(String message); 22 | } 23 | 24 | interface Presenter { 25 | void sendMessage(Context context, Chat chat, String receiverFirebaseToken); 26 | 27 | void getMessage(String senderUid, String receiverUid); 28 | } 29 | 30 | interface Interactor { 31 | void sendMessageToFirebaseUser(Context context, Chat chat, String receiverFirebaseToken); 32 | 33 | void getMessageFromFirebaseUser(String senderUid, String receiverUid); 34 | } 35 | 36 | interface OnSendMessageListener { 37 | void onSendMessageSuccess(); 38 | 39 | void onSendMessageFailure(String message); 40 | } 41 | 42 | interface OnGetMessagesListener { 43 | void onGetMessagesSuccess(Chat chat); 44 | 45 | void onGetMessagesFailure(String message); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/chat/ChatInteractor.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.chat; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.crazyhitty.chdev.ks.firebasechat.fcm.FcmNotificationBuilder; 7 | import com.crazyhitty.chdev.ks.firebasechat.models.Chat; 8 | import com.crazyhitty.chdev.ks.firebasechat.utils.Constants; 9 | import com.crazyhitty.chdev.ks.firebasechat.utils.SharedPrefUtil; 10 | import com.google.firebase.database.ChildEventListener; 11 | import com.google.firebase.database.DataSnapshot; 12 | import com.google.firebase.database.DatabaseError; 13 | import com.google.firebase.database.DatabaseReference; 14 | import com.google.firebase.database.FirebaseDatabase; 15 | import com.google.firebase.database.ValueEventListener; 16 | 17 | /** 18 | * Author: Kartik Sharma 19 | * Created on: 9/2/2016 , 10:08 PM 20 | * Project: FirebaseChat 21 | */ 22 | 23 | public class ChatInteractor implements ChatContract.Interactor { 24 | private static final String TAG = "ChatInteractor"; 25 | 26 | private ChatContract.OnSendMessageListener mOnSendMessageListener; 27 | private ChatContract.OnGetMessagesListener mOnGetMessagesListener; 28 | 29 | public ChatInteractor(ChatContract.OnSendMessageListener onSendMessageListener) { 30 | this.mOnSendMessageListener = onSendMessageListener; 31 | } 32 | 33 | public ChatInteractor(ChatContract.OnGetMessagesListener onGetMessagesListener) { 34 | this.mOnGetMessagesListener = onGetMessagesListener; 35 | } 36 | 37 | public ChatInteractor(ChatContract.OnSendMessageListener onSendMessageListener, 38 | ChatContract.OnGetMessagesListener onGetMessagesListener) { 39 | this.mOnSendMessageListener = onSendMessageListener; 40 | this.mOnGetMessagesListener = onGetMessagesListener; 41 | } 42 | 43 | @Override 44 | public void sendMessageToFirebaseUser(final Context context, final Chat chat, final String receiverFirebaseToken) { 45 | final String room_type_1 = chat.senderUid + "_" + chat.receiverUid; 46 | final String room_type_2 = chat.receiverUid + "_" + chat.senderUid; 47 | 48 | final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference(); 49 | 50 | databaseReference.child(Constants.ARG_CHAT_ROOMS).getRef().addListenerForSingleValueEvent(new ValueEventListener() { 51 | @Override 52 | public void onDataChange(DataSnapshot dataSnapshot) { 53 | if (dataSnapshot.hasChild(room_type_1)) { 54 | Log.e(TAG, "sendMessageToFirebaseUser: " + room_type_1 + " exists"); 55 | databaseReference.child(Constants.ARG_CHAT_ROOMS).child(room_type_1).child(String.valueOf(chat.timestamp)).setValue(chat); 56 | } else if (dataSnapshot.hasChild(room_type_2)) { 57 | Log.e(TAG, "sendMessageToFirebaseUser: " + room_type_2 + " exists"); 58 | databaseReference.child(Constants.ARG_CHAT_ROOMS).child(room_type_2).child(String.valueOf(chat.timestamp)).setValue(chat); 59 | } else { 60 | Log.e(TAG, "sendMessageToFirebaseUser: success"); 61 | databaseReference.child(Constants.ARG_CHAT_ROOMS).child(room_type_1).child(String.valueOf(chat.timestamp)).setValue(chat); 62 | getMessageFromFirebaseUser(chat.senderUid, chat.receiverUid); 63 | } 64 | // send push notification to the receiver 65 | sendPushNotificationToReceiver(chat.sender, 66 | chat.message, 67 | chat.senderUid, 68 | new SharedPrefUtil(context).getString(Constants.ARG_FIREBASE_TOKEN), 69 | receiverFirebaseToken); 70 | mOnSendMessageListener.onSendMessageSuccess(); 71 | } 72 | 73 | @Override 74 | public void onCancelled(DatabaseError databaseError) { 75 | mOnSendMessageListener.onSendMessageFailure("Unable to send message: " + databaseError.getMessage()); 76 | } 77 | }); 78 | } 79 | 80 | private void sendPushNotificationToReceiver(String username, 81 | String message, 82 | String uid, 83 | String firebaseToken, 84 | String receiverFirebaseToken) { 85 | FcmNotificationBuilder.initialize() 86 | .title(username) 87 | .message(message) 88 | .username(username) 89 | .uid(uid) 90 | .firebaseToken(firebaseToken) 91 | .receiverFirebaseToken(receiverFirebaseToken) 92 | .send(); 93 | } 94 | 95 | @Override 96 | public void getMessageFromFirebaseUser(String senderUid, String receiverUid) { 97 | final String room_type_1 = senderUid + "_" + receiverUid; 98 | final String room_type_2 = receiverUid + "_" + senderUid; 99 | 100 | final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference(); 101 | 102 | databaseReference.child(Constants.ARG_CHAT_ROOMS).getRef().addListenerForSingleValueEvent(new ValueEventListener() { 103 | @Override 104 | public void onDataChange(DataSnapshot dataSnapshot) { 105 | if (dataSnapshot.hasChild(room_type_1)) { 106 | Log.e(TAG, "getMessageFromFirebaseUser: " + room_type_1 + " exists"); 107 | FirebaseDatabase.getInstance() 108 | .getReference() 109 | .child(Constants.ARG_CHAT_ROOMS) 110 | .child(room_type_1).addChildEventListener(new ChildEventListener() { 111 | @Override 112 | public void onChildAdded(DataSnapshot dataSnapshot, String s) { 113 | Chat chat = dataSnapshot.getValue(Chat.class); 114 | mOnGetMessagesListener.onGetMessagesSuccess(chat); 115 | } 116 | 117 | @Override 118 | public void onChildChanged(DataSnapshot dataSnapshot, String s) { 119 | 120 | } 121 | 122 | @Override 123 | public void onChildRemoved(DataSnapshot dataSnapshot) { 124 | 125 | } 126 | 127 | @Override 128 | public void onChildMoved(DataSnapshot dataSnapshot, String s) { 129 | 130 | } 131 | 132 | @Override 133 | public void onCancelled(DatabaseError databaseError) { 134 | mOnGetMessagesListener.onGetMessagesFailure("Unable to get message: " + databaseError.getMessage()); 135 | } 136 | }); 137 | } else if (dataSnapshot.hasChild(room_type_2)) { 138 | Log.e(TAG, "getMessageFromFirebaseUser: " + room_type_2 + " exists"); 139 | FirebaseDatabase.getInstance() 140 | .getReference() 141 | .child(Constants.ARG_CHAT_ROOMS) 142 | .child(room_type_2).addChildEventListener(new ChildEventListener() { 143 | @Override 144 | public void onChildAdded(DataSnapshot dataSnapshot, String s) { 145 | Chat chat = dataSnapshot.getValue(Chat.class); 146 | mOnGetMessagesListener.onGetMessagesSuccess(chat); 147 | } 148 | 149 | @Override 150 | public void onChildChanged(DataSnapshot dataSnapshot, String s) { 151 | 152 | } 153 | 154 | @Override 155 | public void onChildRemoved(DataSnapshot dataSnapshot) { 156 | 157 | } 158 | 159 | @Override 160 | public void onChildMoved(DataSnapshot dataSnapshot, String s) { 161 | 162 | } 163 | 164 | @Override 165 | public void onCancelled(DatabaseError databaseError) { 166 | mOnGetMessagesListener.onGetMessagesFailure("Unable to get message: " + databaseError.getMessage()); 167 | } 168 | }); 169 | } else { 170 | Log.e(TAG, "getMessageFromFirebaseUser: no such room available"); 171 | } 172 | } 173 | 174 | @Override 175 | public void onCancelled(DatabaseError databaseError) { 176 | mOnGetMessagesListener.onGetMessagesFailure("Unable to get message: " + databaseError.getMessage()); 177 | } 178 | }); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/chat/ChatPresenter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.chat; 2 | 3 | import android.content.Context; 4 | 5 | import com.crazyhitty.chdev.ks.firebasechat.models.Chat; 6 | 7 | /** 8 | * Author: Kartik Sharma 9 | * Created on: 9/2/2016 , 10:05 PM 10 | * Project: FirebaseChat 11 | */ 12 | 13 | public class ChatPresenter implements ChatContract.Presenter, ChatContract.OnSendMessageListener, 14 | ChatContract.OnGetMessagesListener { 15 | private ChatContract.View mView; 16 | private ChatInteractor mChatInteractor; 17 | 18 | public ChatPresenter(ChatContract.View view) { 19 | this.mView = view; 20 | mChatInteractor = new ChatInteractor(this, this); 21 | } 22 | 23 | @Override 24 | public void sendMessage(Context context, Chat chat, String receiverFirebaseToken) { 25 | mChatInteractor.sendMessageToFirebaseUser(context, chat, receiverFirebaseToken); 26 | } 27 | 28 | @Override 29 | public void getMessage(String senderUid, String receiverUid) { 30 | mChatInteractor.getMessageFromFirebaseUser(senderUid, receiverUid); 31 | } 32 | 33 | @Override 34 | public void onSendMessageSuccess() { 35 | mView.onSendMessageSuccess(); 36 | } 37 | 38 | @Override 39 | public void onSendMessageFailure(String message) { 40 | mView.onSendMessageFailure(message); 41 | } 42 | 43 | @Override 44 | public void onGetMessagesSuccess(Chat chat) { 45 | mView.onGetMessagesSuccess(chat); 46 | } 47 | 48 | @Override 49 | public void onGetMessagesFailure(String message) { 50 | mView.onGetMessagesFailure(message); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/login/LoginContract.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.login; 2 | 3 | import android.app.Activity; 4 | 5 | /** 6 | * Author: Kartik Sharma 7 | * Created on: 8/28/2016 , 11:06 AM 8 | * Project: FirebaseChat 9 | */ 10 | 11 | public interface LoginContract { 12 | interface View { 13 | void onLoginSuccess(String message); 14 | 15 | void onLoginFailure(String message); 16 | } 17 | 18 | interface Presenter { 19 | void login(Activity activity, String email, String password); 20 | } 21 | 22 | interface Interactor { 23 | void performFirebaseLogin(Activity activity, String email, String password); 24 | } 25 | 26 | interface OnLoginListener { 27 | void onSuccess(String message); 28 | 29 | void onFailure(String message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/login/LoginInteractor.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.login; 2 | 3 | import android.app.Activity; 4 | import android.support.annotation.NonNull; 5 | import android.util.Log; 6 | 7 | import com.crazyhitty.chdev.ks.firebasechat.utils.Constants; 8 | import com.crazyhitty.chdev.ks.firebasechat.utils.SharedPrefUtil; 9 | import com.google.android.gms.tasks.OnCompleteListener; 10 | import com.google.android.gms.tasks.Task; 11 | import com.google.firebase.auth.AuthResult; 12 | import com.google.firebase.auth.FirebaseAuth; 13 | import com.google.firebase.database.FirebaseDatabase; 14 | 15 | import static android.content.ContentValues.TAG; 16 | 17 | /** 18 | * Author: Kartik Sharma 19 | * Created on: 8/28/2016 , 11:10 AM 20 | * Project: FirebaseChat 21 | */ 22 | 23 | public class LoginInteractor implements LoginContract.Interactor { 24 | private LoginContract.OnLoginListener mOnLoginListener; 25 | 26 | public LoginInteractor(LoginContract.OnLoginListener onLoginListener) { 27 | this.mOnLoginListener = onLoginListener; 28 | } 29 | 30 | @Override 31 | public void performFirebaseLogin(final Activity activity, final String email, String password) { 32 | FirebaseAuth.getInstance() 33 | .signInWithEmailAndPassword(email, password) 34 | .addOnCompleteListener(activity, new OnCompleteListener() { 35 | @Override 36 | public void onComplete(@NonNull Task task) { 37 | Log.d(TAG, "performFirebaseLogin:onComplete:" + task.isSuccessful()); 38 | 39 | // If sign in fails, display a message to the user. If sign in succeeds 40 | // the auth state listener will be notified and logic to handle the 41 | // signed in user can be handled in the listener. 42 | if (task.isSuccessful()) { 43 | mOnLoginListener.onSuccess(task.getResult().toString()); 44 | updateFirebaseToken(task.getResult().getUser().getUid(), 45 | new SharedPrefUtil(activity.getApplicationContext()).getString(Constants.ARG_FIREBASE_TOKEN, null)); 46 | } else { 47 | mOnLoginListener.onFailure(task.getException().getMessage()); 48 | } 49 | } 50 | }); 51 | } 52 | 53 | private void updateFirebaseToken(String uid, String token) { 54 | FirebaseDatabase.getInstance() 55 | .getReference() 56 | .child(Constants.ARG_USERS) 57 | .child(uid) 58 | .child(Constants.ARG_FIREBASE_TOKEN) 59 | .setValue(token); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/login/LoginPresenter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.login; 2 | 3 | import android.app.Activity; 4 | 5 | /** 6 | * Author: Kartik Sharma 7 | * Created on: 8/28/2016 , 11:10 AM 8 | * Project: FirebaseChat 9 | */ 10 | 11 | public class LoginPresenter implements LoginContract.Presenter, LoginContract.OnLoginListener { 12 | private LoginContract.View mLoginView; 13 | private LoginInteractor mLoginInteractor; 14 | 15 | public LoginPresenter(LoginContract.View loginView) { 16 | this.mLoginView = loginView; 17 | mLoginInteractor = new LoginInteractor(this); 18 | } 19 | 20 | @Override 21 | public void login(Activity activity, String email, String password) { 22 | mLoginInteractor.performFirebaseLogin(activity, email, password); 23 | } 24 | 25 | @Override 26 | public void onSuccess(String message) { 27 | mLoginView.onLoginSuccess(message); 28 | } 29 | 30 | @Override 31 | public void onFailure(String message) { 32 | mLoginView.onLoginFailure(message); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/logout/LogoutContract.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.logout; 2 | 3 | /** 4 | * Author: Kartik Sharma 5 | * Created on: 8/28/2016 , 11:06 AM 6 | * Project: FirebaseChat 7 | */ 8 | 9 | public interface LogoutContract { 10 | interface View { 11 | void onLogoutSuccess(String message); 12 | 13 | void onLogoutFailure(String message); 14 | } 15 | 16 | interface Presenter { 17 | void logout(); 18 | } 19 | 20 | interface Interactor { 21 | void performFirebaseLogout(); 22 | } 23 | 24 | interface OnLogoutListener { 25 | void onSuccess(String message); 26 | 27 | void onFailure(String message); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/logout/LogoutInteractor.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.logout; 2 | 3 | import com.google.firebase.auth.FirebaseAuth; 4 | 5 | /** 6 | * Author: Kartik Sharma 7 | * Created on: 8/28/2016 , 11:10 AM 8 | * Project: FirebaseChat 9 | */ 10 | 11 | public class LogoutInteractor implements LogoutContract.Interactor { 12 | private LogoutContract.OnLogoutListener mOnLogoutListener; 13 | 14 | public LogoutInteractor(LogoutContract.OnLogoutListener onLogoutListener) { 15 | mOnLogoutListener = onLogoutListener; 16 | } 17 | 18 | @Override 19 | public void performFirebaseLogout() { 20 | if (FirebaseAuth.getInstance().getCurrentUser() != null) { 21 | FirebaseAuth.getInstance().signOut(); 22 | mOnLogoutListener.onSuccess("Successfully logged out!"); 23 | } else { 24 | mOnLogoutListener.onFailure("No user logged in yet!"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/logout/LogoutPresenter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.logout; 2 | 3 | /** 4 | * Author: Kartik Sharma 5 | * Created on: 8/28/2016 , 11:10 AM 6 | * Project: FirebaseChat 7 | */ 8 | 9 | public class LogoutPresenter implements LogoutContract.Presenter, LogoutContract.OnLogoutListener { 10 | private LogoutContract.View mLogoutView; 11 | private LogoutInteractor mLogoutInteractor; 12 | 13 | public LogoutPresenter(LogoutContract.View logoutView) { 14 | mLogoutView = logoutView; 15 | mLogoutInteractor = new LogoutInteractor(this); 16 | } 17 | 18 | @Override 19 | public void logout() { 20 | mLogoutInteractor.performFirebaseLogout(); 21 | } 22 | 23 | @Override 24 | public void onSuccess(String message) { 25 | mLogoutView.onLogoutSuccess(message); 26 | } 27 | 28 | @Override 29 | public void onFailure(String message) { 30 | mLogoutView.onLogoutFailure(message); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/registration/RegisterContract.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.registration; 2 | 3 | import android.app.Activity; 4 | 5 | import com.google.firebase.auth.FirebaseUser; 6 | 7 | /** 8 | * Author: Kartik Sharma 9 | * Created on: 8/28/2016 , 11:36 AM 10 | * Project: FirebaseChat 11 | */ 12 | 13 | public interface RegisterContract { 14 | interface View { 15 | void onRegistrationSuccess(FirebaseUser firebaseUser); 16 | 17 | void onRegistrationFailure(String message); 18 | } 19 | 20 | interface Presenter { 21 | void register(Activity activity, String email, String password); 22 | } 23 | 24 | interface Interactor { 25 | void performFirebaseRegistration(Activity activity, String email, String password); 26 | } 27 | 28 | interface OnRegistrationListener { 29 | void onSuccess(FirebaseUser firebaseUser); 30 | 31 | void onFailure(String message); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/registration/RegisterInteractor.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.registration; 2 | 3 | import android.app.Activity; 4 | import android.support.annotation.NonNull; 5 | import android.util.Log; 6 | 7 | import com.google.android.gms.tasks.OnCompleteListener; 8 | import com.google.android.gms.tasks.Task; 9 | import com.google.firebase.auth.AuthResult; 10 | import com.google.firebase.auth.FirebaseAuth; 11 | 12 | /** 13 | * Author: Kartik Sharma 14 | * Created on: 8/28/2016 , 11:10 AM 15 | * Project: FirebaseChat 16 | */ 17 | 18 | public class RegisterInteractor implements RegisterContract.Interactor { 19 | private static final String TAG = RegisterInteractor.class.getSimpleName(); 20 | 21 | private RegisterContract.OnRegistrationListener mOnRegistrationListener; 22 | 23 | public RegisterInteractor(RegisterContract.OnRegistrationListener onRegistrationListener) { 24 | this.mOnRegistrationListener = onRegistrationListener; 25 | } 26 | 27 | @Override 28 | public void performFirebaseRegistration(Activity activity, final String email, String password) { 29 | FirebaseAuth.getInstance() 30 | .createUserWithEmailAndPassword(email, password) 31 | .addOnCompleteListener(activity, new OnCompleteListener() { 32 | @Override 33 | public void onComplete(@NonNull Task task) { 34 | Log.e(TAG, "performFirebaseRegistration:onComplete:" + task.isSuccessful()); 35 | 36 | // If sign in fails, display a message to the user. If sign in succeeds 37 | // the auth state listener will be notified and logic to handle the 38 | // signed in user can be handled in the listener. 39 | if (!task.isSuccessful()) { 40 | mOnRegistrationListener.onFailure(task.getException().getMessage()); 41 | } else { 42 | // Add the user to users table. 43 | /*DatabaseReference database= FirebaseDatabase.getInstance().getReference(); 44 | User user = new User(task.getResult().getUser().getUid(), email); 45 | database.child("users").push().setValue(user);*/ 46 | 47 | mOnRegistrationListener.onSuccess(task.getResult().getUser()); 48 | } 49 | } 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/registration/RegisterPresenter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.registration; 2 | 3 | import android.app.Activity; 4 | 5 | import com.google.firebase.auth.FirebaseUser; 6 | 7 | /** 8 | * Author: Kartik Sharma 9 | * Created on: 8/28/2016 , 11:10 AM 10 | * Project: FirebaseChat 11 | */ 12 | 13 | public class RegisterPresenter implements RegisterContract.Presenter, RegisterContract.OnRegistrationListener { 14 | private RegisterContract.View mRegisterView; 15 | private RegisterInteractor mRegisterInteractor; 16 | 17 | public RegisterPresenter(RegisterContract.View registerView) { 18 | this.mRegisterView = registerView; 19 | mRegisterInteractor = new RegisterInteractor(this); 20 | } 21 | 22 | @Override 23 | public void register(Activity activity, String email, String password) { 24 | mRegisterInteractor.performFirebaseRegistration(activity, email, password); 25 | } 26 | 27 | @Override 28 | public void onSuccess(FirebaseUser firebaseUser) { 29 | mRegisterView.onRegistrationSuccess(firebaseUser); 30 | } 31 | 32 | @Override 33 | public void onFailure(String message) { 34 | mRegisterView.onRegistrationFailure(message); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/users/add/AddUserContract.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.users.add; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.firebase.auth.FirebaseUser; 6 | 7 | /** 8 | * Author: Kartik Sharma 9 | * Created on: 8/28/2016 , 11:06 AM 10 | * Project: FirebaseChat 11 | */ 12 | 13 | public interface AddUserContract { 14 | interface View { 15 | void onAddUserSuccess(String message); 16 | 17 | void onAddUserFailure(String message); 18 | } 19 | 20 | interface Presenter { 21 | void addUser(Context context, FirebaseUser firebaseUser); 22 | } 23 | 24 | interface Interactor { 25 | void addUserToDatabase(Context context, FirebaseUser firebaseUser); 26 | } 27 | 28 | interface OnUserDatabaseListener { 29 | void onSuccess(String message); 30 | 31 | void onFailure(String message); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/users/add/AddUserInteractor.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.users.add; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.crazyhitty.chdev.ks.firebasechat.R; 7 | import com.crazyhitty.chdev.ks.firebasechat.models.User; 8 | import com.crazyhitty.chdev.ks.firebasechat.utils.Constants; 9 | import com.crazyhitty.chdev.ks.firebasechat.utils.SharedPrefUtil; 10 | import com.google.android.gms.tasks.OnCompleteListener; 11 | import com.google.android.gms.tasks.Task; 12 | import com.google.firebase.auth.FirebaseUser; 13 | import com.google.firebase.database.DatabaseReference; 14 | import com.google.firebase.database.FirebaseDatabase; 15 | 16 | /** 17 | * Author: Kartik Sharma 18 | * Created on: 9/2/2016 , 10:08 PM 19 | * Project: FirebaseChat 20 | */ 21 | 22 | public class AddUserInteractor implements AddUserContract.Interactor { 23 | private AddUserContract.OnUserDatabaseListener mOnUserDatabaseListener; 24 | 25 | public AddUserInteractor(AddUserContract.OnUserDatabaseListener onUserDatabaseListener) { 26 | this.mOnUserDatabaseListener = onUserDatabaseListener; 27 | } 28 | 29 | @Override 30 | public void addUserToDatabase(final Context context, FirebaseUser firebaseUser) { 31 | DatabaseReference database = FirebaseDatabase.getInstance().getReference(); 32 | User user = new User(firebaseUser.getUid(), 33 | firebaseUser.getEmail(), 34 | new SharedPrefUtil(context).getString(Constants.ARG_FIREBASE_TOKEN)); 35 | database.child(Constants.ARG_USERS) 36 | .child(firebaseUser.getUid()) 37 | .setValue(user) 38 | .addOnCompleteListener(new OnCompleteListener() { 39 | @Override 40 | public void onComplete(@NonNull Task task) { 41 | if (task.isSuccessful()) { 42 | mOnUserDatabaseListener.onSuccess(context.getString(R.string.user_successfully_added)); 43 | } else { 44 | mOnUserDatabaseListener.onFailure(context.getString(R.string.user_unable_to_add)); 45 | } 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/users/add/AddUserPresenter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.users.add; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.firebase.auth.FirebaseUser; 6 | 7 | /** 8 | * Author: Kartik Sharma 9 | * Created on: 9/2/2016 , 10:05 PM 10 | * Project: FirebaseChat 11 | */ 12 | 13 | public class AddUserPresenter implements AddUserContract.Presenter, AddUserContract.OnUserDatabaseListener { 14 | private AddUserContract.View mView; 15 | private AddUserInteractor mAddUserInteractor; 16 | 17 | public AddUserPresenter(AddUserContract.View view) { 18 | this.mView = view; 19 | mAddUserInteractor = new AddUserInteractor(this); 20 | } 21 | 22 | @Override 23 | public void addUser(Context context, FirebaseUser firebaseUser) { 24 | mAddUserInteractor.addUserToDatabase(context, firebaseUser); 25 | } 26 | 27 | @Override 28 | public void onSuccess(String message) { 29 | mView.onAddUserSuccess(message); 30 | } 31 | 32 | @Override 33 | public void onFailure(String message) { 34 | mView.onAddUserFailure(message); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/users/get/all/GetUsersContract.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.users.get.all; 2 | 3 | import com.crazyhitty.chdev.ks.firebasechat.models.User; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Author: Kartik Sharma 9 | * Created on: 8/28/2016 , 11:06 AM 10 | * Project: FirebaseChat 11 | */ 12 | 13 | public interface GetUsersContract { 14 | interface View { 15 | void onGetAllUsersSuccess(List users); 16 | 17 | void onGetAllUsersFailure(String message); 18 | 19 | void onGetChatUsersSuccess(List users); 20 | 21 | void onGetChatUsersFailure(String message); 22 | } 23 | 24 | interface Presenter { 25 | void getAllUsers(); 26 | 27 | void getChatUsers(); 28 | } 29 | 30 | interface Interactor { 31 | void getAllUsersFromFirebase(); 32 | 33 | void getChatUsersFromFirebase(); 34 | } 35 | 36 | interface OnGetAllUsersListener { 37 | void onGetAllUsersSuccess(List users); 38 | 39 | void onGetAllUsersFailure(String message); 40 | } 41 | 42 | interface OnGetChatUsersListener { 43 | void onGetChatUsersSuccess(List users); 44 | 45 | void onGetChatUsersFailure(String message); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/users/get/all/GetUsersInteractor.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.users.get.all; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.crazyhitty.chdev.ks.firebasechat.models.User; 6 | import com.crazyhitty.chdev.ks.firebasechat.utils.Constants; 7 | import com.google.firebase.auth.FirebaseAuth; 8 | import com.google.firebase.database.DataSnapshot; 9 | import com.google.firebase.database.DatabaseError; 10 | import com.google.firebase.database.FirebaseDatabase; 11 | import com.google.firebase.database.ValueEventListener; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Iterator; 15 | import java.util.List; 16 | 17 | /** 18 | * Author: Kartik Sharma 19 | * Created on: 9/2/2016 , 10:08 PM 20 | * Project: FirebaseChat 21 | */ 22 | 23 | public class GetUsersInteractor implements GetUsersContract.Interactor { 24 | private static final String TAG = "GetUsersInteractor"; 25 | 26 | private GetUsersContract.OnGetAllUsersListener mOnGetAllUsersListener; 27 | 28 | public GetUsersInteractor(GetUsersContract.OnGetAllUsersListener onGetAllUsersListener) { 29 | this.mOnGetAllUsersListener = onGetAllUsersListener; 30 | } 31 | 32 | 33 | @Override 34 | public void getAllUsersFromFirebase() { 35 | FirebaseDatabase.getInstance().getReference().child(Constants.ARG_USERS).addListenerForSingleValueEvent(new ValueEventListener() { 36 | @Override 37 | public void onDataChange(DataSnapshot dataSnapshot) { 38 | Iterator dataSnapshots = dataSnapshot.getChildren().iterator(); 39 | List users = new ArrayList<>(); 40 | while (dataSnapshots.hasNext()) { 41 | DataSnapshot dataSnapshotChild = dataSnapshots.next(); 42 | User user = dataSnapshotChild.getValue(User.class); 43 | if (!TextUtils.equals(user.uid, FirebaseAuth.getInstance().getCurrentUser().getUid())) { 44 | users.add(user); 45 | } 46 | } 47 | mOnGetAllUsersListener.onGetAllUsersSuccess(users); 48 | } 49 | 50 | @Override 51 | public void onCancelled(DatabaseError databaseError) { 52 | mOnGetAllUsersListener.onGetAllUsersFailure(databaseError.getMessage()); 53 | } 54 | }); 55 | } 56 | 57 | @Override 58 | public void getChatUsersFromFirebase() { 59 | /*FirebaseDatabase.getInstance().getReference().child(Constants.ARG_CHAT_ROOMS).addListenerForSingleValueEvent(new ValueEventListener() { 60 | @Override 61 | public void onDataChange(DataSnapshot dataSnapshot) { 62 | Iterator dataSnapshots=dataSnapshot.getChildren().iterator(); 63 | List users=new ArrayList<>(); 64 | while (dataSnapshots.hasNext()){ 65 | DataSnapshot dataSnapshotChild=dataSnapshots.next(); 66 | dataSnapshotChild.getRef(). 67 | Chat chat=dataSnapshotChild.getValue(Chat.class); 68 | if(chat.)4 69 | if(!TextUtils.equals(user.uid,FirebaseAuth.getInstance().getCurrentUser().getUid())) { 70 | users.add(user); 71 | } 72 | } 73 | } 74 | 75 | @Override 76 | public void onCancelled(DatabaseError databaseError) { 77 | 78 | } 79 | });*/ 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/core/users/get/all/GetUsersPresenter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.core.users.get.all; 2 | 3 | import com.crazyhitty.chdev.ks.firebasechat.models.User; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Author: Kartik Sharma 9 | * Created on: 9/2/2016 , 10:05 PM 10 | * Project: FirebaseChat 11 | */ 12 | 13 | public class GetUsersPresenter implements GetUsersContract.Presenter, GetUsersContract.OnGetAllUsersListener { 14 | private GetUsersContract.View mView; 15 | private GetUsersInteractor mGetUsersInteractor; 16 | 17 | public GetUsersPresenter(GetUsersContract.View view) { 18 | this.mView = view; 19 | mGetUsersInteractor = new GetUsersInteractor(this); 20 | } 21 | 22 | @Override 23 | public void getAllUsers() { 24 | mGetUsersInteractor.getAllUsersFromFirebase(); 25 | } 26 | 27 | @Override 28 | public void getChatUsers() { 29 | mGetUsersInteractor.getChatUsersFromFirebase(); 30 | } 31 | 32 | @Override 33 | public void onGetAllUsersSuccess(List users) { 34 | mView.onGetAllUsersSuccess(users); 35 | } 36 | 37 | @Override 38 | public void onGetAllUsersFailure(String message) { 39 | mView.onGetAllUsersFailure(message); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/events/PushNotificationEvent.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.events; 2 | 3 | /** 4 | * Author: Kartik Sharma 5 | * Created on: 10/18/2016 , 10:16 PM 6 | * Project: FirebaseChat 7 | */ 8 | 9 | public class PushNotificationEvent { 10 | private String title; 11 | private String message; 12 | private String username; 13 | private String uid; 14 | private String fcmToken; 15 | 16 | public PushNotificationEvent() { 17 | } 18 | 19 | public PushNotificationEvent(String title, String message, String username, String uid, String fcmToken) { 20 | this.title = title; 21 | this.message = message; 22 | this.username = username; 23 | this.uid = uid; 24 | this.fcmToken = fcmToken; 25 | } 26 | 27 | public String getTitle() { 28 | return title; 29 | } 30 | 31 | public void setTitle(String title) { 32 | this.title = title; 33 | } 34 | 35 | public String getMessage() { 36 | return message; 37 | } 38 | 39 | public void setMessage(String message) { 40 | this.message = message; 41 | } 42 | 43 | public String getUsername() { 44 | return username; 45 | } 46 | 47 | public void setUsername(String username) { 48 | this.username = username; 49 | } 50 | 51 | public String getUid() { 52 | return uid; 53 | } 54 | 55 | public void setUid(String uid) { 56 | this.uid = uid; 57 | } 58 | 59 | public String getFcmToken() { 60 | return fcmToken; 61 | } 62 | 63 | public void setFcmToken(String fcmToken) { 64 | this.fcmToken = fcmToken; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/fcm/FcmNotificationBuilder.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.fcm; 2 | 3 | import android.util.Log; 4 | 5 | import org.json.JSONException; 6 | import org.json.JSONObject; 7 | 8 | import java.io.IOException; 9 | 10 | import okhttp3.Call; 11 | import okhttp3.Callback; 12 | import okhttp3.MediaType; 13 | import okhttp3.OkHttpClient; 14 | import okhttp3.Request; 15 | import okhttp3.RequestBody; 16 | import okhttp3.Response; 17 | 18 | /** 19 | * Author: Kartik Sharma 20 | * Created on: 10/16/2016 , 1:53 PM 21 | * Project: FirebaseChat 22 | */ 23 | 24 | public class FcmNotificationBuilder { 25 | public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8"); 26 | private static final String TAG = "FcmNotificationBuilder"; 27 | private static final String SERVER_API_KEY = "YOUR_SERVER_API_KEY"; 28 | private static final String CONTENT_TYPE = "Content-Type"; 29 | private static final String APPLICATION_JSON = "application/json"; 30 | private static final String AUTHORIZATION = "Authorization"; 31 | private static final String AUTH_KEY = "key=" + SERVER_API_KEY; 32 | private static final String FCM_URL = "https://fcm.googleapis.com/fcm/send"; 33 | // json related keys 34 | private static final String KEY_TO = "to"; 35 | private static final String KEY_NOTIFICATION = "notification"; 36 | private static final String KEY_TITLE = "title"; 37 | private static final String KEY_TEXT = "text"; 38 | private static final String KEY_DATA = "data"; 39 | private static final String KEY_USERNAME = "username"; 40 | private static final String KEY_UID = "uid"; 41 | private static final String KEY_FCM_TOKEN = "fcm_token"; 42 | 43 | private String mTitle; 44 | private String mMessage; 45 | private String mUsername; 46 | private String mUid; 47 | private String mFirebaseToken; 48 | private String mReceiverFirebaseToken; 49 | 50 | private FcmNotificationBuilder() { 51 | 52 | } 53 | 54 | public static FcmNotificationBuilder initialize() { 55 | return new FcmNotificationBuilder(); 56 | } 57 | 58 | public FcmNotificationBuilder title(String title) { 59 | mTitle = title; 60 | return this; 61 | } 62 | 63 | public FcmNotificationBuilder message(String message) { 64 | mMessage = message; 65 | return this; 66 | } 67 | 68 | public FcmNotificationBuilder username(String username) { 69 | mUsername = username; 70 | return this; 71 | } 72 | 73 | public FcmNotificationBuilder uid(String uid) { 74 | mUid = uid; 75 | return this; 76 | } 77 | 78 | public FcmNotificationBuilder firebaseToken(String firebaseToken) { 79 | mFirebaseToken = firebaseToken; 80 | return this; 81 | } 82 | 83 | public FcmNotificationBuilder receiverFirebaseToken(String receiverFirebaseToken) { 84 | mReceiverFirebaseToken = receiverFirebaseToken; 85 | return this; 86 | } 87 | 88 | public void send() { 89 | RequestBody requestBody = null; 90 | try { 91 | requestBody = RequestBody.create(MEDIA_TYPE_JSON, getValidJsonBody().toString()); 92 | } catch (JSONException e) { 93 | e.printStackTrace(); 94 | } 95 | 96 | Request request = new Request.Builder() 97 | .addHeader(CONTENT_TYPE, APPLICATION_JSON) 98 | .addHeader(AUTHORIZATION, AUTH_KEY) 99 | .url(FCM_URL) 100 | .post(requestBody) 101 | .build(); 102 | 103 | Call call = new OkHttpClient().newCall(request); 104 | call.enqueue(new Callback() { 105 | @Override 106 | public void onFailure(Call call, IOException e) { 107 | Log.e(TAG, "onGetAllUsersFailure: " + e.getMessage()); 108 | } 109 | 110 | @Override 111 | public void onResponse(Call call, Response response) throws IOException { 112 | Log.e(TAG, "onResponse: " + response.body().string()); 113 | } 114 | }); 115 | } 116 | 117 | private JSONObject getValidJsonBody() throws JSONException { 118 | JSONObject jsonObjectBody = new JSONObject(); 119 | jsonObjectBody.put(KEY_TO, mReceiverFirebaseToken); 120 | 121 | JSONObject jsonObjectData = new JSONObject(); 122 | jsonObjectData.put(KEY_TITLE, mTitle); 123 | jsonObjectData.put(KEY_TEXT, mMessage); 124 | jsonObjectData.put(KEY_USERNAME, mUsername); 125 | jsonObjectData.put(KEY_UID, mUid); 126 | jsonObjectData.put(KEY_FCM_TOKEN, mFirebaseToken); 127 | jsonObjectBody.put(KEY_DATA, jsonObjectData); 128 | 129 | return jsonObjectBody; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/fcm/MyFirebaseInstanceIDService.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.fcm; 2 | 3 | import android.util.Log; 4 | 5 | import com.crazyhitty.chdev.ks.firebasechat.utils.Constants; 6 | import com.crazyhitty.chdev.ks.firebasechat.utils.SharedPrefUtil; 7 | import com.google.firebase.auth.FirebaseAuth; 8 | import com.google.firebase.database.FirebaseDatabase; 9 | import com.google.firebase.iid.FirebaseInstanceId; 10 | import com.google.firebase.iid.FirebaseInstanceIdService; 11 | 12 | public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService { 13 | private static final String TAG = "MyFirebaseIIDService"; 14 | 15 | /** 16 | * Called if InstanceID token is updated. This may occur if the security of 17 | * the previous token had been compromised. Note that this is called when the InstanceID token 18 | * is initially generated so this is where you would retrieve the token. 19 | */ 20 | // [START refresh_token] 21 | @Override 22 | public void onTokenRefresh() { 23 | // Get updated InstanceID token. 24 | String refreshedToken = FirebaseInstanceId.getInstance().getToken(); 25 | Log.d(TAG, "Refreshed token: " + refreshedToken); 26 | 27 | // If you want to send messages to this application instance or 28 | // manage this apps subscriptions on the server side, send the 29 | // Instance ID token to your app server. 30 | sendRegistrationToServer(refreshedToken); 31 | } 32 | // [END refresh_token] 33 | 34 | /** 35 | * Persist token to third-party servers. 36 | *

37 | * Modify this method to associate the user's FCM InstanceID token with any server-side account 38 | * maintained by your application. 39 | * 40 | * @param token The new token. 41 | */ 42 | private void sendRegistrationToServer(final String token) { 43 | new SharedPrefUtil(getApplicationContext()).saveString(Constants.ARG_FIREBASE_TOKEN, token); 44 | 45 | if (FirebaseAuth.getInstance().getCurrentUser() != null) { 46 | FirebaseDatabase.getInstance() 47 | .getReference() 48 | .child(Constants.ARG_USERS) 49 | .child(FirebaseAuth.getInstance().getCurrentUser().getUid()) 50 | .child(Constants.ARG_FIREBASE_TOKEN) 51 | .setValue(token); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/fcm/MyFirebaseMessagingService.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.fcm; 2 | 3 | import android.app.NotificationManager; 4 | import android.app.PendingIntent; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.media.RingtoneManager; 8 | import android.net.Uri; 9 | import android.support.v4.app.NotificationCompat; 10 | import android.util.Log; 11 | 12 | import com.crazyhitty.chdev.ks.firebasechat.FirebaseChatMainApp; 13 | import com.crazyhitty.chdev.ks.firebasechat.R; 14 | import com.crazyhitty.chdev.ks.firebasechat.events.PushNotificationEvent; 15 | import com.crazyhitty.chdev.ks.firebasechat.ui.activities.ChatActivity; 16 | import com.crazyhitty.chdev.ks.firebasechat.utils.Constants; 17 | import com.google.firebase.messaging.FirebaseMessagingService; 18 | import com.google.firebase.messaging.RemoteMessage; 19 | 20 | import org.greenrobot.eventbus.EventBus; 21 | 22 | public class MyFirebaseMessagingService extends FirebaseMessagingService { 23 | 24 | private static final String TAG = "MyFirebaseMsgService"; 25 | 26 | /** 27 | * Called when message is received. 28 | * 29 | * @param remoteMessage Object representing the message received from Firebase Cloud Messaging. 30 | */ 31 | @Override 32 | public void onMessageReceived(RemoteMessage remoteMessage) { 33 | 34 | // TODO(developer): Handle FCM messages here. 35 | // Not getting messages here? See why this may be: https://goo.gl/39bRNJ 36 | Log.d(TAG, "From: " + remoteMessage.getFrom()); 37 | 38 | // Check if message contains a data payload. 39 | if (remoteMessage.getData().size() > 0) { 40 | Log.d(TAG, "Message data payload: " + remoteMessage.getData()); 41 | 42 | String title = remoteMessage.getData().get("title"); 43 | String message = remoteMessage.getData().get("text"); 44 | String username = remoteMessage.getData().get("username"); 45 | String uid = remoteMessage.getData().get("uid"); 46 | String fcmToken = remoteMessage.getData().get("fcm_token"); 47 | 48 | // Don't show notification if chat activity is open. 49 | if (!FirebaseChatMainApp.isChatActivityOpen()) { 50 | sendNotification(title, 51 | message, 52 | username, 53 | uid, 54 | fcmToken); 55 | } else { 56 | EventBus.getDefault().post(new PushNotificationEvent(title, 57 | message, 58 | username, 59 | uid, 60 | fcmToken)); 61 | } 62 | } 63 | } 64 | 65 | /** 66 | * Create and show a simple notification containing the received FCM message. 67 | */ 68 | private void sendNotification(String title, 69 | String message, 70 | String receiver, 71 | String receiverUid, 72 | String firebaseToken) { 73 | Intent intent = new Intent(this, ChatActivity.class); 74 | intent.putExtra(Constants.ARG_RECEIVER, receiver); 75 | intent.putExtra(Constants.ARG_RECEIVER_UID, receiverUid); 76 | intent.putExtra(Constants.ARG_FIREBASE_TOKEN, firebaseToken); 77 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 78 | PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 79 | PendingIntent.FLAG_ONE_SHOT); 80 | 81 | Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); 82 | NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) 83 | .setSmallIcon(R.drawable.ic_messaging) 84 | .setContentTitle(title) 85 | .setContentText(message) 86 | .setAutoCancel(true) 87 | .setSound(defaultSoundUri) 88 | .setContentIntent(pendingIntent); 89 | 90 | NotificationManager notificationManager = 91 | (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 92 | 93 | notificationManager.notify(0, notificationBuilder.build()); 94 | } 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/models/Chat.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.models; 2 | 3 | import com.google.firebase.database.IgnoreExtraProperties; 4 | 5 | /** 6 | * Author: Kartik Sharma 7 | * Created on: 9/4/2016 , 12:43 PM 8 | * Project: FirebaseChat 9 | */ 10 | 11 | @IgnoreExtraProperties 12 | public class Chat { 13 | public String sender; 14 | public String receiver; 15 | public String senderUid; 16 | public String receiverUid; 17 | public String message; 18 | public long timestamp; 19 | 20 | public Chat() { 21 | } 22 | 23 | public Chat(String sender, String receiver, String senderUid, String receiverUid, String message, long timestamp) { 24 | this.sender = sender; 25 | this.receiver = receiver; 26 | this.senderUid = senderUid; 27 | this.receiverUid = receiverUid; 28 | this.message = message; 29 | this.timestamp = timestamp; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/models/User.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.models; 2 | 3 | import com.google.firebase.database.IgnoreExtraProperties; 4 | 5 | /** 6 | * Author: Kartik Sharma 7 | * Created on: 9/1/2016 , 8:35 PM 8 | * Project: FirebaseChat 9 | */ 10 | 11 | @IgnoreExtraProperties 12 | public class User { 13 | public String uid; 14 | public String email; 15 | public String firebaseToken; 16 | 17 | public User() { 18 | } 19 | 20 | public User(String uid, String email, String firebaseToken) { 21 | this.uid = uid; 22 | this.email = email; 23 | this.firebaseToken = firebaseToken; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/models/Users.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.models; 2 | 3 | /** 4 | * Author: Kartik Sharma 5 | * Created on: 8/28/2016 , 2:25 PM 6 | * Project: FirebaseChat 7 | */ 8 | 9 | public class Users { 10 | private String emailId; 11 | private String lastMessage; 12 | private int notifCount; 13 | 14 | public String getEmailId() { 15 | return emailId; 16 | } 17 | 18 | public void setEmailId(String emailId) { 19 | this.emailId = emailId; 20 | } 21 | 22 | public String getLastMessage() { 23 | return lastMessage; 24 | } 25 | 26 | public void setLastMessage(String lastMessage) { 27 | this.lastMessage = lastMessage; 28 | } 29 | 30 | public int getNotifCount() { 31 | return notifCount; 32 | } 33 | 34 | public void setNotifCount(int notifCount) { 35 | this.notifCount = notifCount; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/activities/ChatActivity.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.activities; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v4.app.FragmentTransaction; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | 10 | import com.crazyhitty.chdev.ks.firebasechat.FirebaseChatMainApp; 11 | import com.crazyhitty.chdev.ks.firebasechat.R; 12 | import com.crazyhitty.chdev.ks.firebasechat.ui.fragments.ChatFragment; 13 | import com.crazyhitty.chdev.ks.firebasechat.utils.Constants; 14 | 15 | public class ChatActivity extends AppCompatActivity { 16 | private Toolbar mToolbar; 17 | 18 | public static void startActivity(Context context, 19 | String receiver, 20 | String receiverUid, 21 | String firebaseToken) { 22 | Intent intent = new Intent(context, ChatActivity.class); 23 | intent.putExtra(Constants.ARG_RECEIVER, receiver); 24 | intent.putExtra(Constants.ARG_RECEIVER_UID, receiverUid); 25 | intent.putExtra(Constants.ARG_FIREBASE_TOKEN, firebaseToken); 26 | context.startActivity(intent); 27 | } 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_chat); 33 | bindViews(); 34 | init(); 35 | } 36 | 37 | private void bindViews() { 38 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 39 | } 40 | 41 | private void init() { 42 | // set the toolbar 43 | setSupportActionBar(mToolbar); 44 | 45 | // set toolbar title 46 | mToolbar.setTitle(getIntent().getExtras().getString(Constants.ARG_RECEIVER)); 47 | 48 | // set the register screen fragment 49 | FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 50 | fragmentTransaction.replace(R.id.frame_layout_content_chat, 51 | ChatFragment.newInstance(getIntent().getExtras().getString(Constants.ARG_RECEIVER), 52 | getIntent().getExtras().getString(Constants.ARG_RECEIVER_UID), 53 | getIntent().getExtras().getString(Constants.ARG_FIREBASE_TOKEN)), 54 | ChatFragment.class.getSimpleName()); 55 | fragmentTransaction.commit(); 56 | } 57 | 58 | @Override 59 | protected void onResume() { 60 | super.onResume(); 61 | FirebaseChatMainApp.setChatActivityOpen(true); 62 | } 63 | 64 | @Override 65 | protected void onPause() { 66 | super.onPause(); 67 | FirebaseChatMainApp.setChatActivityOpen(false); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/activities/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.activities; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v4.app.FragmentTransaction; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | 10 | import com.crazyhitty.chdev.ks.firebasechat.R; 11 | import com.crazyhitty.chdev.ks.firebasechat.ui.fragments.LoginFragment; 12 | 13 | public class LoginActivity extends AppCompatActivity { 14 | private Toolbar mToolbar; 15 | 16 | public static void startIntent(Context context) { 17 | Intent intent = new Intent(context, LoginActivity.class); 18 | context.startActivity(intent); 19 | } 20 | 21 | public static void startIntent(Context context, int flags) { 22 | Intent intent = new Intent(context, LoginActivity.class); 23 | intent.setFlags(flags); 24 | context.startActivity(intent); 25 | } 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_login); 31 | bindViews(); 32 | init(); 33 | } 34 | 35 | private void bindViews() { 36 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 37 | } 38 | 39 | private void init() { 40 | // set the toolbar 41 | setSupportActionBar(mToolbar); 42 | 43 | // set the login screen fragment 44 | FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 45 | fragmentTransaction.replace(R.id.frame_layout_content_login, 46 | LoginFragment.newInstance(), 47 | LoginFragment.class.getSimpleName()); 48 | fragmentTransaction.commit(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/activities/RegisterActivity.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.activities; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v4.app.FragmentTransaction; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | 10 | import com.crazyhitty.chdev.ks.firebasechat.R; 11 | import com.crazyhitty.chdev.ks.firebasechat.ui.fragments.RegisterFragment; 12 | 13 | public class RegisterActivity extends AppCompatActivity { 14 | private Toolbar mToolbar; 15 | 16 | public static void startActivity(Context context) { 17 | Intent intent = new Intent(context, RegisterActivity.class); 18 | context.startActivity(intent); 19 | } 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_register); 25 | bindViews(); 26 | init(); 27 | } 28 | 29 | private void bindViews() { 30 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 31 | } 32 | 33 | private void init() { 34 | // set the toolbar 35 | setSupportActionBar(mToolbar); 36 | 37 | // set the register screen fragment 38 | FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 39 | fragmentTransaction.replace(R.id.frame_layout_content_register, 40 | RegisterFragment.newInstance(), 41 | RegisterFragment.class.getSimpleName()); 42 | fragmentTransaction.commit(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/activities/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.activities; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import com.crazyhitty.chdev.ks.firebasechat.R; 8 | import com.google.firebase.auth.FirebaseAuth; 9 | 10 | public class SplashActivity extends AppCompatActivity { 11 | private static final int SPLASH_TIME_MS = 2000; 12 | private Handler mHandler; 13 | private Runnable mRunnable; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_splash); 19 | 20 | mHandler = new Handler(); 21 | 22 | mRunnable = new Runnable() { 23 | @Override 24 | public void run() { 25 | // check if user is already logged in or not 26 | if (FirebaseAuth.getInstance().getCurrentUser() != null) { 27 | // if logged in redirect the user to user listing activity 28 | UserListingActivity.startActivity(SplashActivity.this); 29 | } else { 30 | // otherwise redirect the user to login activity 31 | LoginActivity.startIntent(SplashActivity.this); 32 | } 33 | finish(); 34 | } 35 | }; 36 | 37 | mHandler.postDelayed(mRunnable, SPLASH_TIME_MS); 38 | } 39 | 40 | /*@Override 41 | protected void onPause() { 42 | super.onPause(); 43 | mHandler.removeCallbacks(mRunnable); 44 | } 45 | 46 | @Override 47 | protected void onResume() { 48 | super.onResume(); 49 | mHandler.postDelayed(mRunnable, SPLASH_TIME_MS); 50 | }*/ 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/activities/UserListingActivity.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.activities; 2 | 3 | import android.content.Context; 4 | import android.content.DialogInterface; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.support.design.widget.TabLayout; 8 | import android.support.v4.view.ViewPager; 9 | import android.support.v7.app.AlertDialog; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.support.v7.widget.Toolbar; 12 | import android.view.Menu; 13 | import android.view.MenuItem; 14 | import android.widget.Toast; 15 | 16 | import com.crazyhitty.chdev.ks.firebasechat.R; 17 | import com.crazyhitty.chdev.ks.firebasechat.core.logout.LogoutContract; 18 | import com.crazyhitty.chdev.ks.firebasechat.core.logout.LogoutPresenter; 19 | import com.crazyhitty.chdev.ks.firebasechat.ui.adapters.UserListingPagerAdapter; 20 | 21 | public class UserListingActivity extends AppCompatActivity implements LogoutContract.View { 22 | private Toolbar mToolbar; 23 | private TabLayout mTabLayoutUserListing; 24 | private ViewPager mViewPagerUserListing; 25 | 26 | private LogoutPresenter mLogoutPresenter; 27 | 28 | public static void startActivity(Context context) { 29 | Intent intent = new Intent(context, UserListingActivity.class); 30 | context.startActivity(intent); 31 | } 32 | 33 | public static void startActivity(Context context, int flags) { 34 | Intent intent = new Intent(context, UserListingActivity.class); 35 | intent.setFlags(flags); 36 | context.startActivity(intent); 37 | } 38 | 39 | @Override 40 | protected void onCreate(Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | setContentView(R.layout.activity_user_listing); 43 | bindViews(); 44 | init(); 45 | } 46 | 47 | private void bindViews() { 48 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 49 | mTabLayoutUserListing = (TabLayout) findViewById(R.id.tab_layout_user_listing); 50 | mViewPagerUserListing = (ViewPager) findViewById(R.id.view_pager_user_listing); 51 | } 52 | 53 | private void init() { 54 | // set the toolbar 55 | setSupportActionBar(mToolbar); 56 | 57 | // set the view pager adapter 58 | UserListingPagerAdapter userListingPagerAdapter = new UserListingPagerAdapter(getSupportFragmentManager()); 59 | mViewPagerUserListing.setAdapter(userListingPagerAdapter); 60 | 61 | // attach tab layout with view pager 62 | mTabLayoutUserListing.setupWithViewPager(mViewPagerUserListing); 63 | 64 | mLogoutPresenter = new LogoutPresenter(this); 65 | } 66 | 67 | @Override 68 | public boolean onCreateOptionsMenu(Menu menu) { 69 | getMenuInflater().inflate(R.menu.menu_user_listing, menu); 70 | return super.onCreateOptionsMenu(menu); 71 | } 72 | 73 | @Override 74 | public boolean onOptionsItemSelected(MenuItem item) { 75 | switch (item.getItemId()) { 76 | case R.id.action_logout: 77 | logout(); 78 | break; 79 | } 80 | return super.onOptionsItemSelected(item); 81 | } 82 | 83 | private void logout() { 84 | new AlertDialog.Builder(this) 85 | .setTitle(R.string.logout) 86 | .setMessage(R.string.are_you_sure) 87 | .setPositiveButton(R.string.logout, new DialogInterface.OnClickListener() { 88 | @Override 89 | public void onClick(DialogInterface dialog, int which) { 90 | dialog.dismiss(); 91 | mLogoutPresenter.logout(); 92 | } 93 | }) 94 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 95 | @Override 96 | public void onClick(DialogInterface dialog, int which) { 97 | dialog.dismiss(); 98 | } 99 | }) 100 | .show(); 101 | } 102 | 103 | @Override 104 | public void onLogoutSuccess(String message) { 105 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); 106 | LoginActivity.startIntent(this, 107 | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); 108 | } 109 | 110 | @Override 111 | public void onLogoutFailure(String message) { 112 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/adapters/ChatRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.adapters; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.text.TextUtils; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import com.crazyhitty.chdev.ks.firebasechat.R; 11 | import com.crazyhitty.chdev.ks.firebasechat.models.Chat; 12 | import com.google.firebase.auth.FirebaseAuth; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * Author: Kartik Sharma 18 | * Created on: 10/16/2016 , 10:36 AM 19 | * Project: FirebaseChat 20 | */ 21 | 22 | public class ChatRecyclerAdapter extends RecyclerView.Adapter { 23 | private static final int VIEW_TYPE_ME = 1; 24 | private static final int VIEW_TYPE_OTHER = 2; 25 | 26 | private List mChats; 27 | 28 | public ChatRecyclerAdapter(List chats) { 29 | mChats = chats; 30 | } 31 | 32 | public void add(Chat chat) { 33 | mChats.add(chat); 34 | notifyItemInserted(mChats.size() - 1); 35 | } 36 | 37 | @Override 38 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 39 | LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); 40 | RecyclerView.ViewHolder viewHolder = null; 41 | switch (viewType) { 42 | case VIEW_TYPE_ME: 43 | View viewChatMine = layoutInflater.inflate(R.layout.item_chat_mine, parent, false); 44 | viewHolder = new MyChatViewHolder(viewChatMine); 45 | break; 46 | case VIEW_TYPE_OTHER: 47 | View viewChatOther = layoutInflater.inflate(R.layout.item_chat_other, parent, false); 48 | viewHolder = new OtherChatViewHolder(viewChatOther); 49 | break; 50 | } 51 | return viewHolder; 52 | } 53 | 54 | @Override 55 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 56 | if (TextUtils.equals(mChats.get(position).senderUid, 57 | FirebaseAuth.getInstance().getCurrentUser().getUid())) { 58 | configureMyChatViewHolder((MyChatViewHolder) holder, position); 59 | } else { 60 | configureOtherChatViewHolder((OtherChatViewHolder) holder, position); 61 | } 62 | } 63 | 64 | private void configureMyChatViewHolder(MyChatViewHolder myChatViewHolder, int position) { 65 | Chat chat = mChats.get(position); 66 | 67 | String alphabet = chat.sender.substring(0, 1); 68 | 69 | myChatViewHolder.txtChatMessage.setText(chat.message); 70 | myChatViewHolder.txtUserAlphabet.setText(alphabet); 71 | } 72 | 73 | private void configureOtherChatViewHolder(OtherChatViewHolder otherChatViewHolder, int position) { 74 | Chat chat = mChats.get(position); 75 | 76 | String alphabet = chat.sender.substring(0, 1); 77 | 78 | otherChatViewHolder.txtChatMessage.setText(chat.message); 79 | otherChatViewHolder.txtUserAlphabet.setText(alphabet); 80 | } 81 | 82 | @Override 83 | public int getItemCount() { 84 | if (mChats != null) { 85 | return mChats.size(); 86 | } 87 | return 0; 88 | } 89 | 90 | @Override 91 | public int getItemViewType(int position) { 92 | if (TextUtils.equals(mChats.get(position).senderUid, 93 | FirebaseAuth.getInstance().getCurrentUser().getUid())) { 94 | return VIEW_TYPE_ME; 95 | } else { 96 | return VIEW_TYPE_OTHER; 97 | } 98 | } 99 | 100 | private static class MyChatViewHolder extends RecyclerView.ViewHolder { 101 | private TextView txtChatMessage, txtUserAlphabet; 102 | 103 | public MyChatViewHolder(View itemView) { 104 | super(itemView); 105 | txtChatMessage = (TextView) itemView.findViewById(R.id.text_view_chat_message); 106 | txtUserAlphabet = (TextView) itemView.findViewById(R.id.text_view_user_alphabet); 107 | } 108 | } 109 | 110 | private static class OtherChatViewHolder extends RecyclerView.ViewHolder { 111 | private TextView txtChatMessage, txtUserAlphabet; 112 | 113 | public OtherChatViewHolder(View itemView) { 114 | super(itemView); 115 | txtChatMessage = (TextView) itemView.findViewById(R.id.text_view_chat_message); 116 | txtUserAlphabet = (TextView) itemView.findViewById(R.id.text_view_user_alphabet); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/adapters/UserListingPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.adapters; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import com.crazyhitty.chdev.ks.firebasechat.ui.fragments.UsersFragment; 8 | 9 | /** 10 | * Author: Kartik Sharma 11 | * Created on: 9/4/2016 , 12:03 PM 12 | * Project: FirebaseChat 13 | */ 14 | 15 | public class UserListingPagerAdapter extends FragmentPagerAdapter { 16 | private static final Fragment[] sFragments = new Fragment[]{/*UsersFragment.newInstance(UsersFragment.TYPE_CHATS),*/ 17 | UsersFragment.newInstance(UsersFragment.TYPE_ALL)}; 18 | private static final String[] sTitles = new String[]{/*"Chats",*/ 19 | "All Users"}; 20 | 21 | public UserListingPagerAdapter(FragmentManager fm) { 22 | super(fm); 23 | } 24 | 25 | @Override 26 | public Fragment getItem(int position) { 27 | return sFragments[position]; 28 | } 29 | 30 | @Override 31 | public int getCount() { 32 | return sFragments.length; 33 | } 34 | 35 | @Override 36 | public CharSequence getPageTitle(int position) { 37 | return sTitles[position]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/adapters/UserListingRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.adapters; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import com.crazyhitty.chdev.ks.firebasechat.R; 10 | import com.crazyhitty.chdev.ks.firebasechat.models.User; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * Author: Kartik Sharma 16 | * Created on: 8/28/2016 , 2:23 PM 17 | * Project: FirebaseChat 18 | */ 19 | 20 | public class UserListingRecyclerAdapter extends RecyclerView.Adapter { 21 | private List mUsers; 22 | 23 | public UserListingRecyclerAdapter(List users) { 24 | this.mUsers = users; 25 | } 26 | 27 | public void add(User user) { 28 | mUsers.add(user); 29 | notifyItemInserted(mUsers.size() - 1); 30 | } 31 | 32 | @Override 33 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 34 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_all_user_listing, parent, false); 35 | return new ViewHolder(view); 36 | } 37 | 38 | @Override 39 | public void onBindViewHolder(ViewHolder holder, int position) { 40 | User user = mUsers.get(position); 41 | 42 | String alphabet = user.email.substring(0, 1); 43 | 44 | holder.txtUsername.setText(user.email); 45 | holder.txtUserAlphabet.setText(alphabet); 46 | } 47 | 48 | @Override 49 | public int getItemCount() { 50 | if (mUsers != null) { 51 | return mUsers.size(); 52 | } 53 | return 0; 54 | } 55 | 56 | public User getUser(int position) { 57 | return mUsers.get(position); 58 | } 59 | 60 | static class ViewHolder extends RecyclerView.ViewHolder { 61 | private TextView txtUserAlphabet, txtUsername; 62 | 63 | ViewHolder(View itemView) { 64 | super(itemView); 65 | txtUserAlphabet = (TextView) itemView.findViewById(R.id.text_view_user_alphabet); 66 | txtUsername = (TextView) itemView.findViewById(R.id.text_view_username); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/fragments/ChatFragment.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.fragments; 2 | 3 | import android.app.ProgressDialog; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.KeyEvent; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.view.inputmethod.EditorInfo; 13 | import android.widget.EditText; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.crazyhitty.chdev.ks.firebasechat.R; 18 | import com.crazyhitty.chdev.ks.firebasechat.core.chat.ChatContract; 19 | import com.crazyhitty.chdev.ks.firebasechat.core.chat.ChatPresenter; 20 | import com.crazyhitty.chdev.ks.firebasechat.events.PushNotificationEvent; 21 | import com.crazyhitty.chdev.ks.firebasechat.models.Chat; 22 | import com.crazyhitty.chdev.ks.firebasechat.ui.adapters.ChatRecyclerAdapter; 23 | import com.crazyhitty.chdev.ks.firebasechat.utils.Constants; 24 | import com.google.firebase.auth.FirebaseAuth; 25 | 26 | import org.greenrobot.eventbus.EventBus; 27 | import org.greenrobot.eventbus.Subscribe; 28 | 29 | import java.util.ArrayList; 30 | 31 | /** 32 | * Author: Kartik Sharma 33 | * Created on: 8/28/2016 , 10:36 AM 34 | * Project: FirebaseChat 35 | */ 36 | 37 | public class ChatFragment extends Fragment implements ChatContract.View, TextView.OnEditorActionListener { 38 | private RecyclerView mRecyclerViewChat; 39 | private EditText mETxtMessage; 40 | 41 | private ProgressDialog mProgressDialog; 42 | 43 | private ChatRecyclerAdapter mChatRecyclerAdapter; 44 | 45 | private ChatPresenter mChatPresenter; 46 | 47 | public static ChatFragment newInstance(String receiver, 48 | String receiverUid, 49 | String firebaseToken) { 50 | Bundle args = new Bundle(); 51 | args.putString(Constants.ARG_RECEIVER, receiver); 52 | args.putString(Constants.ARG_RECEIVER_UID, receiverUid); 53 | args.putString(Constants.ARG_FIREBASE_TOKEN, firebaseToken); 54 | ChatFragment fragment = new ChatFragment(); 55 | fragment.setArguments(args); 56 | return fragment; 57 | } 58 | 59 | @Override 60 | public void onStart() { 61 | super.onStart(); 62 | EventBus.getDefault().register(this); 63 | } 64 | 65 | @Override 66 | public void onStop() { 67 | super.onStop(); 68 | EventBus.getDefault().unregister(this); 69 | } 70 | 71 | @Nullable 72 | @Override 73 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 74 | View fragmentView = inflater.inflate(R.layout.fragment_chat, container, false); 75 | bindViews(fragmentView); 76 | return fragmentView; 77 | } 78 | 79 | private void bindViews(View view) { 80 | mRecyclerViewChat = (RecyclerView) view.findViewById(R.id.recycler_view_chat); 81 | mETxtMessage = (EditText) view.findViewById(R.id.edit_text_message); 82 | } 83 | 84 | @Override 85 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 86 | super.onActivityCreated(savedInstanceState); 87 | init(); 88 | } 89 | 90 | private void init() { 91 | mProgressDialog = new ProgressDialog(getActivity()); 92 | mProgressDialog.setTitle(getString(R.string.loading)); 93 | mProgressDialog.setMessage(getString(R.string.please_wait)); 94 | mProgressDialog.setIndeterminate(true); 95 | 96 | mETxtMessage.setOnEditorActionListener(this); 97 | 98 | mChatPresenter = new ChatPresenter(this); 99 | mChatPresenter.getMessage(FirebaseAuth.getInstance().getCurrentUser().getUid(), 100 | getArguments().getString(Constants.ARG_RECEIVER_UID)); 101 | } 102 | 103 | @Override 104 | public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 105 | if (actionId == EditorInfo.IME_ACTION_SEND) { 106 | sendMessage(); 107 | return true; 108 | } 109 | return false; 110 | } 111 | 112 | private void sendMessage() { 113 | String message = mETxtMessage.getText().toString(); 114 | String receiver = getArguments().getString(Constants.ARG_RECEIVER); 115 | String receiverUid = getArguments().getString(Constants.ARG_RECEIVER_UID); 116 | String sender = FirebaseAuth.getInstance().getCurrentUser().getEmail(); 117 | String senderUid = FirebaseAuth.getInstance().getCurrentUser().getUid(); 118 | String receiverFirebaseToken = getArguments().getString(Constants.ARG_FIREBASE_TOKEN); 119 | Chat chat = new Chat(sender, 120 | receiver, 121 | senderUid, 122 | receiverUid, 123 | message, 124 | System.currentTimeMillis()); 125 | mChatPresenter.sendMessage(getActivity().getApplicationContext(), 126 | chat, 127 | receiverFirebaseToken); 128 | } 129 | 130 | @Override 131 | public void onSendMessageSuccess() { 132 | mETxtMessage.setText(""); 133 | Toast.makeText(getActivity(), "Message sent", Toast.LENGTH_SHORT).show(); 134 | } 135 | 136 | @Override 137 | public void onSendMessageFailure(String message) { 138 | Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); 139 | } 140 | 141 | @Override 142 | public void onGetMessagesSuccess(Chat chat) { 143 | if (mChatRecyclerAdapter == null) { 144 | mChatRecyclerAdapter = new ChatRecyclerAdapter(new ArrayList()); 145 | mRecyclerViewChat.setAdapter(mChatRecyclerAdapter); 146 | } 147 | mChatRecyclerAdapter.add(chat); 148 | mRecyclerViewChat.smoothScrollToPosition(mChatRecyclerAdapter.getItemCount() - 1); 149 | } 150 | 151 | @Override 152 | public void onGetMessagesFailure(String message) { 153 | Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); 154 | } 155 | 156 | @Subscribe 157 | public void onPushNotificationEvent(PushNotificationEvent pushNotificationEvent) { 158 | if (mChatRecyclerAdapter == null || mChatRecyclerAdapter.getItemCount() == 0) { 159 | mChatPresenter.getMessage(FirebaseAuth.getInstance().getCurrentUser().getUid(), 160 | pushNotificationEvent.getUid()); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/fragments/LoginFragment.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.fragments; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.Button; 12 | import android.widget.EditText; 13 | import android.widget.Toast; 14 | 15 | import com.crazyhitty.chdev.ks.firebasechat.R; 16 | import com.crazyhitty.chdev.ks.firebasechat.core.login.LoginContract; 17 | import com.crazyhitty.chdev.ks.firebasechat.core.login.LoginPresenter; 18 | import com.crazyhitty.chdev.ks.firebasechat.ui.activities.RegisterActivity; 19 | import com.crazyhitty.chdev.ks.firebasechat.ui.activities.UserListingActivity; 20 | 21 | /** 22 | * Author: Kartik Sharma 23 | * Created on: 8/28/2016 , 10:36 AM 24 | * Project: FirebaseChat 25 | */ 26 | 27 | public class LoginFragment extends Fragment implements View.OnClickListener, LoginContract.View { 28 | private LoginPresenter mLoginPresenter; 29 | 30 | private EditText mETxtEmail, mETxtPassword; 31 | private Button mBtnLogin, mBtnRegister; 32 | 33 | private ProgressDialog mProgressDialog; 34 | 35 | public static LoginFragment newInstance() { 36 | Bundle args = new Bundle(); 37 | LoginFragment fragment = new LoginFragment(); 38 | fragment.setArguments(args); 39 | return fragment; 40 | } 41 | 42 | @Nullable 43 | @Override 44 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 45 | View fragmentView = inflater.inflate(R.layout.fragment_login, container, false); 46 | bindViews(fragmentView); 47 | return fragmentView; 48 | } 49 | 50 | private void bindViews(View view) { 51 | mETxtEmail = (EditText) view.findViewById(R.id.edit_text_email_id); 52 | mETxtPassword = (EditText) view.findViewById(R.id.edit_text_password); 53 | mBtnLogin = (Button) view.findViewById(R.id.button_login); 54 | mBtnRegister = (Button) view.findViewById(R.id.button_register); 55 | } 56 | 57 | @Override 58 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 59 | super.onActivityCreated(savedInstanceState); 60 | init(); 61 | } 62 | 63 | private void init() { 64 | mLoginPresenter = new LoginPresenter(this); 65 | 66 | mProgressDialog = new ProgressDialog(getActivity()); 67 | mProgressDialog.setTitle(getString(R.string.loading)); 68 | mProgressDialog.setMessage(getString(R.string.please_wait)); 69 | mProgressDialog.setIndeterminate(true); 70 | 71 | mBtnLogin.setOnClickListener(this); 72 | mBtnRegister.setOnClickListener(this); 73 | 74 | setDummyCredentials(); 75 | } 76 | 77 | private void setDummyCredentials() { 78 | mETxtEmail.setText("test@test.com"); 79 | mETxtPassword.setText("123456"); 80 | } 81 | 82 | @Override 83 | public void onClick(View view) { 84 | int viewId = view.getId(); 85 | 86 | switch (viewId) { 87 | case R.id.button_login: 88 | onLogin(view); 89 | break; 90 | case R.id.button_register: 91 | onRegister(view); 92 | break; 93 | } 94 | } 95 | 96 | private void onLogin(View view) { 97 | String emailId = mETxtEmail.getText().toString(); 98 | String password = mETxtPassword.getText().toString(); 99 | 100 | mLoginPresenter.login(getActivity(), emailId, password); 101 | mProgressDialog.show(); 102 | } 103 | 104 | private void onRegister(View view) { 105 | RegisterActivity.startActivity(getActivity()); 106 | } 107 | 108 | @Override 109 | public void onLoginSuccess(String message) { 110 | mProgressDialog.dismiss(); 111 | Toast.makeText(getActivity(), "Logged in successfully", Toast.LENGTH_SHORT).show(); 112 | UserListingActivity.startActivity(getActivity(), 113 | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); 114 | } 115 | 116 | @Override 117 | public void onLoginFailure(String message) { 118 | mProgressDialog.dismiss(); 119 | Toast.makeText(getActivity(), "Error: " + message, Toast.LENGTH_SHORT).show(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/fragments/RegisterFragment.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.fragments; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.Button; 13 | import android.widget.EditText; 14 | import android.widget.Toast; 15 | 16 | import com.crazyhitty.chdev.ks.firebasechat.R; 17 | import com.crazyhitty.chdev.ks.firebasechat.core.registration.RegisterContract; 18 | import com.crazyhitty.chdev.ks.firebasechat.core.registration.RegisterPresenter; 19 | import com.crazyhitty.chdev.ks.firebasechat.core.users.add.AddUserContract; 20 | import com.crazyhitty.chdev.ks.firebasechat.core.users.add.AddUserPresenter; 21 | import com.crazyhitty.chdev.ks.firebasechat.ui.activities.UserListingActivity; 22 | import com.google.firebase.auth.FirebaseUser; 23 | 24 | /** 25 | * Author: Kartik Sharma 26 | * Created on: 8/28/2016 , 10:36 AM 27 | * Project: FirebaseChat 28 | */ 29 | 30 | public class RegisterFragment extends Fragment implements View.OnClickListener, RegisterContract.View, AddUserContract.View { 31 | private static final String TAG = RegisterFragment.class.getSimpleName(); 32 | 33 | private RegisterPresenter mRegisterPresenter; 34 | private AddUserPresenter mAddUserPresenter; 35 | 36 | private EditText mETxtEmail, mETxtPassword; 37 | private Button mBtnRegister; 38 | 39 | private ProgressDialog mProgressDialog; 40 | 41 | public static RegisterFragment newInstance() { 42 | Bundle args = new Bundle(); 43 | RegisterFragment fragment = new RegisterFragment(); 44 | fragment.setArguments(args); 45 | return fragment; 46 | } 47 | 48 | @Nullable 49 | @Override 50 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 51 | View fragmentView = inflater.inflate(R.layout.fragment_register, container, false); 52 | bindViews(fragmentView); 53 | return fragmentView; 54 | } 55 | 56 | private void bindViews(View view) { 57 | mETxtEmail = (EditText) view.findViewById(R.id.edit_text_email_id); 58 | mETxtPassword = (EditText) view.findViewById(R.id.edit_text_password); 59 | mBtnRegister = (Button) view.findViewById(R.id.button_register); 60 | } 61 | 62 | @Override 63 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 64 | super.onActivityCreated(savedInstanceState); 65 | init(); 66 | } 67 | 68 | private void init() { 69 | mRegisterPresenter = new RegisterPresenter(this); 70 | mAddUserPresenter = new AddUserPresenter(this); 71 | 72 | mProgressDialog = new ProgressDialog(getActivity()); 73 | mProgressDialog.setTitle(getString(R.string.loading)); 74 | mProgressDialog.setMessage(getString(R.string.please_wait)); 75 | mProgressDialog.setIndeterminate(true); 76 | 77 | mBtnRegister.setOnClickListener(this); 78 | } 79 | 80 | @Override 81 | public void onClick(View view) { 82 | int viewId = view.getId(); 83 | 84 | switch (viewId) { 85 | case R.id.button_register: 86 | onRegister(view); 87 | break; 88 | } 89 | } 90 | 91 | private void onRegister(View view) { 92 | String emailId = mETxtEmail.getText().toString(); 93 | String password = mETxtPassword.getText().toString(); 94 | 95 | mRegisterPresenter.register(getActivity(), emailId, password); 96 | mProgressDialog.show(); 97 | } 98 | 99 | @Override 100 | public void onRegistrationSuccess(FirebaseUser firebaseUser) { 101 | mProgressDialog.setMessage(getString(R.string.adding_user_to_db)); 102 | Toast.makeText(getActivity(), "Registration Successful!", Toast.LENGTH_SHORT).show(); 103 | mAddUserPresenter.addUser(getActivity().getApplicationContext(), firebaseUser); 104 | } 105 | 106 | @Override 107 | public void onRegistrationFailure(String message) { 108 | mProgressDialog.dismiss(); 109 | mProgressDialog.setMessage(getString(R.string.please_wait)); 110 | Log.e(TAG, "onRegistrationFailure: " + message); 111 | Toast.makeText(getActivity(), "Registration failed!+\n" + message, Toast.LENGTH_LONG).show(); 112 | } 113 | 114 | @Override 115 | public void onAddUserSuccess(String message) { 116 | mProgressDialog.dismiss(); 117 | Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); 118 | UserListingActivity.startActivity(getActivity(), 119 | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); 120 | } 121 | 122 | @Override 123 | public void onAddUserFailure(String message) { 124 | mProgressDialog.dismiss(); 125 | Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/ui/fragments/UsersFragment.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.ui.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.widget.SwipeRefreshLayout; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.text.TextUtils; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.Toast; 13 | 14 | import com.crazyhitty.chdev.ks.firebasechat.R; 15 | import com.crazyhitty.chdev.ks.firebasechat.core.users.get.all.GetUsersContract; 16 | import com.crazyhitty.chdev.ks.firebasechat.core.users.get.all.GetUsersPresenter; 17 | import com.crazyhitty.chdev.ks.firebasechat.models.User; 18 | import com.crazyhitty.chdev.ks.firebasechat.ui.activities.ChatActivity; 19 | import com.crazyhitty.chdev.ks.firebasechat.ui.adapters.UserListingRecyclerAdapter; 20 | import com.crazyhitty.chdev.ks.firebasechat.utils.ItemClickSupport; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * Author: Kartik Sharma 26 | * Created on: 8/28/2016 , 10:36 AM 27 | * Project: FirebaseChat 28 | */ 29 | 30 | public class UsersFragment extends Fragment implements GetUsersContract.View, ItemClickSupport.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener { 31 | public static final String ARG_TYPE = "type"; 32 | public static final String TYPE_CHATS = "type_chats"; 33 | public static final String TYPE_ALL = "type_all"; 34 | 35 | private SwipeRefreshLayout mSwipeRefreshLayout; 36 | private RecyclerView mRecyclerViewAllUserListing; 37 | 38 | private UserListingRecyclerAdapter mUserListingRecyclerAdapter; 39 | 40 | private GetUsersPresenter mGetUsersPresenter; 41 | 42 | public static UsersFragment newInstance(String type) { 43 | Bundle args = new Bundle(); 44 | args.putString(ARG_TYPE, type); 45 | UsersFragment fragment = new UsersFragment(); 46 | fragment.setArguments(args); 47 | return fragment; 48 | } 49 | 50 | @Nullable 51 | @Override 52 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 53 | View fragmentView = inflater.inflate(R.layout.fragment_users, container, false); 54 | bindViews(fragmentView); 55 | return fragmentView; 56 | } 57 | 58 | private void bindViews(View view) { 59 | mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh_layout); 60 | mRecyclerViewAllUserListing = (RecyclerView) view.findViewById(R.id.recycler_view_all_user_listing); 61 | } 62 | 63 | @Override 64 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 65 | super.onActivityCreated(savedInstanceState); 66 | init(); 67 | } 68 | 69 | private void init() { 70 | mGetUsersPresenter = new GetUsersPresenter(this); 71 | getUsers(); 72 | mSwipeRefreshLayout.post(new Runnable() { 73 | @Override 74 | public void run() { 75 | mSwipeRefreshLayout.setRefreshing(true); 76 | } 77 | }); 78 | 79 | ItemClickSupport.addTo(mRecyclerViewAllUserListing) 80 | .setOnItemClickListener(this); 81 | 82 | mSwipeRefreshLayout.setOnRefreshListener(this); 83 | } 84 | 85 | @Override 86 | public void onRefresh() { 87 | getUsers(); 88 | } 89 | 90 | private void getUsers() { 91 | if (TextUtils.equals(getArguments().getString(ARG_TYPE), TYPE_CHATS)) { 92 | 93 | } else if (TextUtils.equals(getArguments().getString(ARG_TYPE), TYPE_ALL)) { 94 | mGetUsersPresenter.getAllUsers(); 95 | } 96 | } 97 | 98 | @Override 99 | public void onItemClicked(RecyclerView recyclerView, int position, View v) { 100 | ChatActivity.startActivity(getActivity(), 101 | mUserListingRecyclerAdapter.getUser(position).email, 102 | mUserListingRecyclerAdapter.getUser(position).uid, 103 | mUserListingRecyclerAdapter.getUser(position).firebaseToken); 104 | } 105 | 106 | @Override 107 | public void onGetAllUsersSuccess(List users) { 108 | mSwipeRefreshLayout.post(new Runnable() { 109 | @Override 110 | public void run() { 111 | mSwipeRefreshLayout.setRefreshing(false); 112 | } 113 | }); 114 | mUserListingRecyclerAdapter = new UserListingRecyclerAdapter(users); 115 | mRecyclerViewAllUserListing.setAdapter(mUserListingRecyclerAdapter); 116 | mUserListingRecyclerAdapter.notifyDataSetChanged(); 117 | } 118 | 119 | @Override 120 | public void onGetAllUsersFailure(String message) { 121 | mSwipeRefreshLayout.post(new Runnable() { 122 | @Override 123 | public void run() { 124 | mSwipeRefreshLayout.setRefreshing(false); 125 | } 126 | }); 127 | Toast.makeText(getActivity(), "Error: " + message, Toast.LENGTH_SHORT).show(); 128 | } 129 | 130 | @Override 131 | public void onGetChatUsersSuccess(List users) { 132 | 133 | } 134 | 135 | @Override 136 | public void onGetChatUsersFailure(String message) { 137 | 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/utils/Constants.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.utils; 2 | 3 | /** 4 | * Author: Kartik Sharma 5 | * Created on: 9/2/2016 , 10:12 PM 6 | * Project: FirebaseChat 7 | */ 8 | 9 | public class Constants { 10 | public static final String ARG_USERS = "users"; 11 | public static final String ARG_RECEIVER = "receiver"; 12 | public static final String ARG_RECEIVER_UID = "receiver_uid"; 13 | public static final String ARG_CHAT_ROOMS = "chat_rooms"; 14 | public static final String ARG_FIREBASE_TOKEN = "firebaseToken"; 15 | public static final String ARG_FRIENDS = "friends"; 16 | public static final String ARG_UID = "uid"; 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/utils/ItemClickSupport.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.utils; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | 6 | import com.crazyhitty.chdev.ks.firebasechat.R; 7 | 8 | public class ItemClickSupport { 9 | private final RecyclerView mRecyclerView; 10 | private OnItemClickListener mOnItemClickListener; 11 | private OnItemLongClickListener mOnItemLongClickListener; 12 | private View.OnClickListener mOnClickListener = new View.OnClickListener() { 13 | @Override 14 | public void onClick(View v) { 15 | if (mOnItemClickListener != null) { 16 | RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v); 17 | mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v); 18 | } 19 | } 20 | }; 21 | private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() { 22 | @Override 23 | public boolean onLongClick(View v) { 24 | if (mOnItemLongClickListener != null) { 25 | RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v); 26 | return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v); 27 | } 28 | return false; 29 | } 30 | }; 31 | private RecyclerView.OnChildAttachStateChangeListener mAttachListener 32 | = new RecyclerView.OnChildAttachStateChangeListener() { 33 | @Override 34 | public void onChildViewAttachedToWindow(View view) { 35 | if (mOnItemClickListener != null) { 36 | view.setOnClickListener(mOnClickListener); 37 | } 38 | if (mOnItemLongClickListener != null) { 39 | view.setOnLongClickListener(mOnLongClickListener); 40 | } 41 | } 42 | 43 | @Override 44 | public void onChildViewDetachedFromWindow(View view) { 45 | 46 | } 47 | }; 48 | 49 | private ItemClickSupport(RecyclerView recyclerView) { 50 | mRecyclerView = recyclerView; 51 | mRecyclerView.setTag(R.id.item_click_support, this); 52 | mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener); 53 | } 54 | 55 | public static ItemClickSupport addTo(RecyclerView view) { 56 | ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support); 57 | if (support == null) { 58 | support = new ItemClickSupport(view); 59 | } 60 | return support; 61 | } 62 | 63 | public static ItemClickSupport removeFrom(RecyclerView view) { 64 | ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support); 65 | if (support != null) { 66 | support.detach(view); 67 | } 68 | return support; 69 | } 70 | 71 | public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) { 72 | mOnItemClickListener = listener; 73 | return this; 74 | } 75 | 76 | public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) { 77 | mOnItemLongClickListener = listener; 78 | return this; 79 | } 80 | 81 | private void detach(RecyclerView view) { 82 | view.removeOnChildAttachStateChangeListener(mAttachListener); 83 | view.setTag(R.id.item_click_support, null); 84 | } 85 | 86 | public interface OnItemClickListener { 87 | 88 | void onItemClicked(RecyclerView recyclerView, int position, View v); 89 | } 90 | 91 | public interface OnItemLongClickListener { 92 | 93 | boolean onItemLongClicked(RecyclerView recyclerView, int position, View v); 94 | } 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/utils/NetworkConnectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.utils; 2 | 3 | import android.content.Context; 4 | import android.content.DialogInterface; 5 | import android.content.Intent; 6 | import android.net.ConnectivityManager; 7 | import android.net.NetworkInfo; 8 | import android.provider.Settings; 9 | import android.support.v7.app.AlertDialog; 10 | 11 | import com.crazyhitty.chdev.ks.firebasechat.R; 12 | 13 | /** 14 | * Utility class for network related queries. 15 | *
16 | * Author Kartik Sharma 17 | * Created on: 8/7/2016 , 9:15 AM 18 | * Project: FinalProject 19 | */ 20 | 21 | public class NetworkConnectionUtil { 22 | public static final String ERR_DIALOG_TITLE = "No internet connection detected !"; 23 | private static final String ERR_DIALOG_MSG = "Looks like our application is not able to detect an active internet connection, " + 24 | "please check your device's network settings."; 25 | private static final String ERR_DIALOG_POSITIVE_BTN = "Settings"; 26 | private static final String ERR_DIALOG_NEGATIVE_BTN = "Dismiss"; 27 | 28 | /** 29 | * Check if the device is connected to internet or not. 30 | * 31 | * @param context Current context of the application 32 | * @return true if device is connected to internet, otherwise false 33 | */ 34 | public static boolean isConnectedToInternet(Context context) { 35 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 36 | NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); 37 | return networkInfo != null && networkInfo.isConnectedOrConnecting(); 38 | } 39 | 40 | /** 41 | * Check if the device is connected to internet via wifi or not. 42 | * 43 | * @param context Current context of the application 44 | * @return true if device is connected to internet via wifi, otherwise false 45 | */ 46 | public static boolean isConnectedToWifi(Context context) { 47 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 48 | NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); 49 | return networkInfo != null && 50 | networkInfo.isConnectedOrConnecting() && 51 | networkInfo.getType() == ConnectivityManager.TYPE_WIFI; 52 | } 53 | 54 | /** 55 | * Check if the device is connected to internet via mobile network or not. 56 | * 57 | * @param context Current context of the application 58 | * @return true if device is connected to internet via mobile network, otherwise false 59 | */ 60 | public static boolean isConnectedToMobileNetwork(Context context) { 61 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 62 | NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); 63 | return networkInfo != null && 64 | networkInfo.isConnectedOrConnecting() && 65 | networkInfo.getType() == ConnectivityManager.TYPE_MOBILE; 66 | } 67 | 68 | /** 69 | * Show a error dialog representing that no internet connection is available currently. 70 | * 71 | * @param context Current context of the application 72 | */ 73 | public static void showNoInternetAvailableErrorDialog(final Context context) { 74 | new AlertDialog.Builder(context) 75 | .setTitle(ERR_DIALOG_TITLE) 76 | .setMessage(ERR_DIALOG_MSG) 77 | .setIcon(R.drawable.ic_error_24dp) 78 | .setPositiveButton(ERR_DIALOG_POSITIVE_BTN, new DialogInterface.OnClickListener() { 79 | @Override 80 | public void onClick(DialogInterface dialogInterface, int i) { 81 | dialogInterface.dismiss(); 82 | Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); 83 | context.startActivity(intent); 84 | } 85 | }) 86 | .setNegativeButton(ERR_DIALOG_NEGATIVE_BTN, new DialogInterface.OnClickListener() { 87 | @Override 88 | public void onClick(DialogInterface dialogInterface, int i) { 89 | dialogInterface.dismiss(); 90 | } 91 | }) 92 | .show(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/crazyhitty/chdev/ks/firebasechat/utils/SharedPrefUtil.java: -------------------------------------------------------------------------------- 1 | package com.crazyhitty.chdev.ks.firebasechat.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | /** 7 | * Simple util class for easing the use of shared preference. 8 | *

9 | * Created by Kartik_ch on 2/13/2016. 10 | */ 11 | public class SharedPrefUtil { 12 | /** 13 | * Name of the preference file 14 | */ 15 | private static final String APP_PREFS = "application_preferences"; 16 | 17 | private Context mContext; 18 | private SharedPreferences mSharedPreferences; 19 | private SharedPreferences.Editor mEditor; 20 | 21 | public SharedPrefUtil(Context mContext) { 22 | this.mContext = mContext; 23 | } 24 | 25 | /** 26 | * Save a string into shared preference 27 | * 28 | * @param key The name of the preference to modify 29 | * @param value The new value for the preference 30 | */ 31 | public void saveString(String key, String value) { 32 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 33 | mEditor = mSharedPreferences.edit(); 34 | mEditor.putString(key, value); 35 | mEditor.commit(); 36 | } 37 | 38 | /** 39 | * Save a int into shared preference 40 | * 41 | * @param key The name of the preference to modify 42 | * @param value The new value for the preference 43 | */ 44 | public void saveInt(String key, int value) { 45 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 46 | mEditor = mSharedPreferences.edit(); 47 | mEditor.putInt(key, value); 48 | mEditor.commit(); 49 | } 50 | 51 | /** 52 | * Save a boolean into shared preference 53 | * 54 | * @param key The name of the preference to modify 55 | * @param value The new value for the preference 56 | */ 57 | public void saveBoolean(String key, boolean value) { 58 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 59 | mEditor = mSharedPreferences.edit(); 60 | mEditor.putBoolean(key, value); 61 | mEditor.commit(); 62 | } 63 | 64 | /** 65 | * Retrieve a String value from the preferences. 66 | * 67 | * @param key The name of the preference to retrieve. 68 | * @return Returns the preference value if it exists, or null. 69 | * Throws ClassCastException if there is a preference with this name that is not a String. 70 | */ 71 | public String getString(String key) { 72 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 73 | return mSharedPreferences.getString(key, null); 74 | } 75 | 76 | /** 77 | * Retrieve a String value from the preferences. 78 | * 79 | * @param key The name of the preference to retrieve. 80 | * @param defaultValue Value to return if this preference does not exist. 81 | * @return Returns the preference value if it exists, or defaultValue. 82 | * Throws ClassCastException if there is a preference with this name that is not a String. 83 | */ 84 | public String getString(String key, String defaultValue) { 85 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 86 | return mSharedPreferences.getString(key, defaultValue); 87 | } 88 | 89 | /** 90 | * Retrieve a int value from the preferences. 91 | * 92 | * @param key The name of the preference to retrieve. 93 | * @return Returns the preference value if it exists, or 0. 94 | * Throws ClassCastException if there is a preference with this name that is not a int. 95 | */ 96 | public int getInt(String key) { 97 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 98 | return mSharedPreferences.getInt(key, 0); 99 | } 100 | 101 | /** 102 | * Retrieve a int value from the preferences. 103 | * 104 | * @param key The name of the preference to retrieve. 105 | * @param defaultValue Value to return if this preference does not exist. 106 | * @return Returns the preference value if it exists, or defaultValue. 107 | * Throws ClassCastException if there is a preference with this name that is not a int. 108 | */ 109 | public int getInt(String key, int defaultValue) { 110 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 111 | return mSharedPreferences.getInt(key, defaultValue); 112 | } 113 | 114 | /** 115 | * Retrieve a boolean value from the preferences. 116 | * 117 | * @param key The name of the preference to retrieve. 118 | * @return Returns the preference value if it exists, or false. 119 | * Throws ClassCastException if there is a preference with this name that is not a boolean. 120 | */ 121 | public boolean getBoolean(String key) { 122 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 123 | return mSharedPreferences.getBoolean(key, false); 124 | } 125 | 126 | /** 127 | * Retrieve a boolean value from the preferences. 128 | * 129 | * @param key The name of the preference to retrieve. 130 | * @param defaultValue Value to return if this preference does not exist. 131 | * @return Returns the preference value if it exists, or defaultValue. 132 | * Throws ClassCastException if there is a preference with this name that is not a boolean. 133 | */ 134 | public boolean getBoolean(String key, boolean defaultValue) { 135 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 136 | return mSharedPreferences.getBoolean(key, defaultValue); 137 | } 138 | 139 | /** 140 | * Clears the shared preference file 141 | */ 142 | public void clear() { 143 | mSharedPreferences = mContext.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE); 144 | mSharedPreferences.edit().clear().apply(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi-v11/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-hdpi-v11/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-hdpi/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi-v11/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-mdpi-v11/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-mdpi/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/firebase_chat_splash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-nodpi/firebase_chat_splash.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi-v11/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-xhdpi-v11/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-xhdpi/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi-v11/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-xxhdpi-v11/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-xxhdpi/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi-v11/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-xxxhdpi-v11/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_messaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyhitty/firebase-chat/1ac7bf79bba308c49f8dbffac0eee2e65d97fec1/app/src/main/res/drawable-xxxhdpi/ic_messaging.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/chat_rounded_rect_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_accent.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_error_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rounded_rect_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_chat.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_register.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_user_listing.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 24 | 25 | 26 | 27 | 32 | 33 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_chat.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 21 | 22 | 25 | 26 | 29 | 30 |