diff --git a/README.md b/README.md new file mode 100644 index 0000000..7a14dc0 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ + +# Messenger # + +If you want a APK then create an issue, i'll send the link.. +
ChatApp is a real time one to one chat application with Push Notifications made using Firebase... + +Add yours google-services.json +
Change Authorization:key with your key from firebase project + +
Implementation Guide +
1 - Project +
1 - Open the Project in your android studio; +
2 - *IMPORTANT* Change the Package Name. (https://stackoverflow.com/questions/16804093/android-studio-rename-package) + +
2 - Firebase Panel +
- Create Firebase Project (https://console.firebase.google.com/); +
- Import the file google-service.json into your project +
- Connect to firebase console authentication and database from your IDE +
- in firebase Storage Rules, change value of "allow read, write:" from "if request.auth != null" to "if true;" +
- For sending notification, paste your Firebase project key into your project APIService.java +
- When you change database settings, you likely will need to uninstall and reinstall apps to avoid app crashes due to app caches. + +Check out the design... +# Welcome, Login, Signup, Forgot Password + + +# Chats, Users, Profile Screens + + +# Chat Screen, Friend Profile, Logout Menu + + + + + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..4c00904 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,50 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "com.saharsh.chatapp" + minSdkVersion 16 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support.constraint:constraint-layout:1.1.2' + + //libraries we need for now + implementation 'com.android.support:support-v4:27.1.1' + implementation 'com.android.support:design:27.1.1' + implementation 'com.google.firebase:firebase-auth:16.0.2' + implementation 'com.google.firebase:firebase-database:16.0.1' + implementation 'com.google.firebase:firebase-core:16.0.1' + //add this + implementation 'com.google.firebase:firebase-storage:16.0.1' + implementation 'com.android.support:cardview-v7:27.1.1' + implementation 'com.rengwuxian.materialedittext:library:2.1.4' + //add this library and this + implementation 'de.hdodenhof:circleimageview:2.2.0' + implementation 'com.github.bumptech.glide:glide:4.8.0' + + //add these libraries + implementation 'com.squareup.retrofit2:retrofit:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.3.0' + implementation 'com.google.firebase:firebase-messaging:17.3.1' + + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} + +apply plugin: 'com.google.gms.google-services' diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/saharsh/chatapp/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/saharsh/chatapp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..9b5ef8d --- /dev/null +++ b/app/src/androidTest/java/com/saharsh/chatapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.saharsh.chatapp; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.koddev.chatapp", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..040fc5d --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/fonts/myriad.ttf b/app/src/main/assets/fonts/myriad.ttf new file mode 100644 index 0000000..ff3bddd Binary files /dev/null and b/app/src/main/assets/fonts/myriad.ttf differ diff --git a/app/src/main/assets/fonts/myriadregular.ttf b/app/src/main/assets/fonts/myriadregular.ttf new file mode 100644 index 0000000..57a953b Binary files /dev/null and b/app/src/main/assets/fonts/myriadregular.ttf differ diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..3943aa3 Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/com/saharsh/chatapp/Adapter/MessageAdapter.java b/app/src/main/java/com/saharsh/chatapp/Adapter/MessageAdapter.java new file mode 100644 index 0000000..31703f6 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Adapter/MessageAdapter.java @@ -0,0 +1,124 @@ +package com.saharsh.chatapp.Adapter; + +import android.content.Context; +import android.graphics.Typeface; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.saharsh.chatapp.Model.Chat; +import com.saharsh.chatapp.R; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +public class MessageAdapter extends RecyclerView.Adapter { + + public static final int MSG_TYPE_LEFT = 0; + public static final int MSG_TYPE_RIGHT = 1; + Typeface MR,MRR; + + + private Context mContext; + private List mChat; + private String imageurl; + + FirebaseUser fuser; + + public MessageAdapter(Context mContext, List mChat, String imageurl){ + this.mChat = mChat; + this.mContext = mContext; + this.imageurl = imageurl; + + MRR = Typeface.createFromAsset(mContext.getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(mContext.getAssets(), "fonts/myriad.ttf"); + + } + + @NonNull + @Override + public MessageAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == MSG_TYPE_RIGHT) { + View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_right, parent, false); + return new MessageAdapter.ViewHolder(view); + } else { + View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_left, parent, false); + return new MessageAdapter.ViewHolder(view); + } + } + + @Override + public void onBindViewHolder(@NonNull MessageAdapter.ViewHolder holder, int position) { + + Chat chat = mChat.get(position); + holder.show_message.setTypeface(MRR); + holder.txt_seen.setTypeface(MRR); + + holder.show_message.setText(chat.getMessage()); + if(chat.getTime()!=null && !chat.getTime().trim().equals("")) { + holder.time_tv.setText(holder.convertTime(chat.getTime())); + } + + if (imageurl.equals("default")){ + holder.profile_image.setImageResource(R.drawable.profile_img); + } else { + Glide.with(mContext).load(imageurl).into(holder.profile_image); + } + + if (position == mChat.size()-1){ + if (chat.isIsseen()){ + holder.txt_seen.setText("Seen"); + } else { + holder.txt_seen.setText("Delivered"); + } + } else { + holder.txt_seen.setVisibility(View.GONE); + } + + } + + @Override + public int getItemCount() { + return mChat.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder{ + + public TextView show_message; + public ImageView profile_image; + public TextView txt_seen; + public TextView time_tv; + public ViewHolder(View itemView) { + super(itemView); + + show_message = itemView.findViewById(R.id.show_message); + profile_image = itemView.findViewById(R.id.profile_image); + txt_seen = itemView.findViewById(R.id.txt_seen); + time_tv = itemView.findViewById(R.id.time_tv); + } + + public String convertTime(String time){ + SimpleDateFormat formatter = new SimpleDateFormat("h:mm a"); + String dateString = formatter.format(new Date(Long.parseLong(time))); + return dateString; + } + } + + @Override + public int getItemViewType(int position) { + fuser = FirebaseAuth.getInstance().getCurrentUser(); + if (mChat.get(position).getSender().equals(fuser.getUid())){ + return MSG_TYPE_RIGHT; + } else { + return MSG_TYPE_LEFT; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/saharsh/chatapp/Adapter/OnItemClick.java b/app/src/main/java/com/saharsh/chatapp/Adapter/OnItemClick.java new file mode 100644 index 0000000..e0aa8c4 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Adapter/OnItemClick.java @@ -0,0 +1,7 @@ +package com.saharsh.chatapp.Adapter; + +import android.view.View; + +public interface OnItemClick { + public void onItemCLick(String uid, View view); +} diff --git a/app/src/main/java/com/saharsh/chatapp/Adapter/UserAdapter.java b/app/src/main/java/com/saharsh/chatapp/Adapter/UserAdapter.java new file mode 100644 index 0000000..2a6c031 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Adapter/UserAdapter.java @@ -0,0 +1,176 @@ +package com.saharsh.chatapp.Adapter; + +import android.app.FragmentTransaction; +import android.content.Context; +import android.content.Intent; +import android.graphics.Typeface; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.MainActivity; +import com.saharsh.chatapp.MessageActivity; +import com.saharsh.chatapp.Model.Chat; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.R; +import com.saharsh.chatapp.ViewProfileActivity; + +import java.util.List; + +public class UserAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List mUsers; + private boolean ischat; + private OnItemClick onItemClick; + + Typeface MR,MRR; + String theLastMessage; + + public UserAdapter(Context mContext, OnItemClick onItemClick, List mUsers, boolean ischat){ + this.onItemClick = onItemClick; + this.mUsers = mUsers; + this.mContext = mContext; + this.ischat = ischat; + + if(mContext!=null) { + MRR = Typeface.createFromAsset(mContext.getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(mContext.getAssets(), "fonts/myriad.ttf"); + } + + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.user_item, parent, false); + return new UserAdapter.ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + + final User user = mUsers.get(position); + holder.username.setTypeface(MR); + holder.last_msg.setTypeface(MRR); + + holder.username.setText(user.getUsername()); + if (user.getImageURL().equals("default")){ + holder.profile_image.setImageResource(R.drawable.profile_img); + } else { + Glide.with(mContext).load(user.getImageURL()).into(holder.profile_image); + } + + if (ischat){ + lastMessage(user.getId(), holder.last_msg); + } else { + holder.last_msg.setVisibility(View.GONE); + } + + if (ischat){ + if (user.getStatus().equals("online")){ + holder.img_on.setVisibility(View.VISIBLE); + holder.img_off.setVisibility(View.GONE); + } else { + holder.img_on.setVisibility(View.GONE); + holder.img_off.setVisibility(View.GONE); + } + } else { + holder.img_on.setVisibility(View.GONE); + holder.img_off.setVisibility(View.GONE); + } + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(mContext, MessageActivity.class); + intent.putExtra("userid", user.getId()); + mContext.startActivity(intent); + } + }); + + + holder.profile_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onItemClick.onItemCLick(user.getId(),view); + } + }); + } + + @Override + public int getItemCount() { + return mUsers.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder{ + + public TextView username; + public ImageView profile_image; + private ImageView img_on; + private ImageView img_off; + private TextView last_msg; + + public ViewHolder(View itemView) { + super(itemView); + + username = itemView.findViewById(R.id.username); + profile_image = itemView.findViewById(R.id.profile_image); + img_on = itemView.findViewById(R.id.img_on); + img_off = itemView.findViewById(R.id.img_off); + last_msg = itemView.findViewById(R.id.last_msg); + } + } + + //check for last message + private void lastMessage(final String userid, final TextView last_msg){ + theLastMessage = "default"; + final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Chats"); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chat chat = snapshot.getValue(Chat.class); + if (firebaseUser != null && chat != null) { + if (chat.getReceiver().equals(firebaseUser.getUid()) && chat.getSender().equals(userid) || + chat.getReceiver().equals(userid) && chat.getSender().equals(firebaseUser.getUid())) { + theLastMessage = chat.getMessage(); + } + } + } + + switch (theLastMessage){ + case "default": + last_msg.setText("No Message"); + break; + + default: + last_msg.setText(theLastMessage); + break; + } + + theLastMessage = "default"; + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/BaseActivity.java b/app/src/main/java/com/saharsh/chatapp/BaseActivity.java new file mode 100644 index 0000000..30c1185 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/BaseActivity.java @@ -0,0 +1,110 @@ +package com.saharsh.chatapp; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.view.Window; +import android.widget.Toast; + +public class BaseActivity extends AppCompatActivity{ + + public final String TAG = this.getClass().getSimpleName(); + private ProgressDialog progressDialog; + public Dialog dialog; +// LottieAnimationView lottieAnimationView; + + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + dialog = new Dialog(this, R.style.DimDisabled); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setCancelable(false); + + + } + + public void showLoader(String msg) { + try { + dialog.show(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void showLoader() { + try { + dialog.show(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void hideLoader() { + if (dialog != null) { + try { + dialog.dismiss(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + + public void showToast(String msg) { + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + + public void showErrorState() { + + } + + public void showEmptyState() { + + } + + + + + + +// public void showSnackbar(String msg){ +// Snackbar snackbar = Snackbar +// .make(getCurrentFocus(), "Try again!", Snackbar.LENGTH_LONG) +// .setAction("RETRY", new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// } +// }); +// snackbar.setActionTextColor(getResources().getColor(R.color.outreach_background_color)); +// View sbView = snackbar.getView(); +// TextView textView = (TextView) sbView.findViewById(android.support.design.R.id.snackbar_text); +// textView.setTextColor(Color.YELLOW); +// snackbar.show(); +// } + + public void showAlert(String title, String msg) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(title); + builder.setMessage(msg); + builder.setCancelable(false); + builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.dismiss(); + finish(); + } + }); + AlertDialog alertDialog = builder.create(); + alertDialog.setTitle(title); + alertDialog.show(); + } + + +} diff --git a/app/src/main/java/com/saharsh/chatapp/Fragments/APIService.java b/app/src/main/java/com/saharsh/chatapp/Fragments/APIService.java new file mode 100644 index 0000000..9181d7e --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Fragments/APIService.java @@ -0,0 +1,21 @@ +package com.saharsh.chatapp.Fragments; + +import com.saharsh.chatapp.Notifications.MyResponse; +import com.saharsh.chatapp.Notifications.Sender; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.Headers; +import retrofit2.http.POST; + +public interface APIService { + @Headers( + { + "Content-Type:application/json", + "Authorization:key=AAAAxNjVIwY:APA91bGFerYPN56D0NJRXKUK1eOgij3Yb_N0XuBgs4efT2b4U9Qdq2hqbpHloHIjMNhZxhaWaMv8k9n-kAGff5TndZnkk1jj3PYGLbmt6jsuWJoXbM8VFIGRj-EcmnJCQfQpriSrMsTN" + } + ) + + @POST("fcm/send") + Call sendNotification(@Body Sender body); +} diff --git a/app/src/main/java/com/saharsh/chatapp/Fragments/ChatsFragment.java b/app/src/main/java/com/saharsh/chatapp/Fragments/ChatsFragment.java new file mode 100644 index 0000000..f7ece28 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Fragments/ChatsFragment.java @@ -0,0 +1,157 @@ +package com.saharsh.chatapp.Fragments; + +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v7.widget.DividerItemDecoration; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.google.firebase.iid.FirebaseInstanceId; +import com.saharsh.chatapp.Adapter.OnItemClick; +import com.saharsh.chatapp.Adapter.UserAdapter; +import com.saharsh.chatapp.MainActivity; +import com.saharsh.chatapp.Model.Chatlist; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.Notifications.Token; +import com.saharsh.chatapp.R; + +import java.util.ArrayList; +import java.util.List; + + +public class ChatsFragment extends Fragment { + + private RecyclerView recyclerView; + + Typeface MR, MRR; + private UserAdapter userAdapter; + private List mUsers; + FrameLayout frameLayout; + TextView es_descp, es_title; + + FirebaseUser fuser; + DatabaseReference reference; + + private List usersList; + static OnItemClick onItemClick; + + + public static ChatsFragment newInstance(OnItemClick click) { + + onItemClick = click; + Bundle args = new Bundle(); + + ChatsFragment fragment = new ChatsFragment(); + fragment.setArguments(args); + return fragment; + } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_chats, container, false); + + MRR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriad.ttf"); + + recyclerView = view.findViewById(R.id.recycler_view); + frameLayout = view.findViewById(R.id.es_layout); + es_descp = view.findViewById(R.id.es_descp); + es_title = view.findViewById(R.id.es_title); + + es_descp.setTypeface(MR); + es_title.setTypeface(MRR); + + + + + recyclerView.setHasFixedSize(true); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL); + recyclerView.addItemDecoration(dividerItemDecoration); + + + fuser = FirebaseAuth.getInstance().getCurrentUser(); + + usersList = new ArrayList<>(); + + reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser.getUid()); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + usersList.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chatlist chatlist = snapshot.getValue(Chatlist.class); + usersList.add(chatlist); + } + if(usersList.size()==0){ + frameLayout.setVisibility(View.VISIBLE); + } + else{ + frameLayout.setVisibility(View.GONE); + } + + chatList(); + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + updateToken(FirebaseInstanceId.getInstance().getToken()); + + + return view; + } + + private void updateToken(String token){ + DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Tokens"); + Token token1 = new Token(token); + reference.child(fuser.getUid()).setValue(token1); + } + + private void chatList() { + mUsers = new ArrayList<>(); + reference = FirebaseDatabase.getInstance().getReference("Users"); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + mUsers.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + User user = snapshot.getValue(User.class); + for (Chatlist chatlist : usersList){ + if (user!= null && user.getId()!=null && chatlist!=null && chatlist.getId()!= null && + user.getId().equals(chatlist.getId())){ + mUsers.add(user); + } + } + } + + + userAdapter = new UserAdapter(getContext(), onItemClick,mUsers, true); + recyclerView.setAdapter(userAdapter); + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + +} diff --git a/app/src/main/java/com/saharsh/chatapp/Fragments/ProfileFragment.java b/app/src/main/java/com/saharsh/chatapp/Fragments/ProfileFragment.java new file mode 100644 index 0000000..2744e2a --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Fragments/ProfileFragment.java @@ -0,0 +1,253 @@ +package com.saharsh.chatapp.Fragments; + +import android.app.ProgressDialog; +import android.content.ContentResolver; +import android.content.Intent; +import android.graphics.Typeface; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.MimeTypeMap; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.bumptech.glide.Glide; +import com.google.android.gms.tasks.Continuation; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.StorageReference; +import com.google.firebase.storage.StorageTask; +import com.google.firebase.storage.UploadTask; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.R; + +import java.util.HashMap; + +import de.hdodenhof.circleimageview.CircleImageView; + +import static android.app.Activity.RESULT_OK; + + +public class ProfileFragment extends Fragment { + + CircleImageView image_profile; + TextView profile_tv; + EditText username, bio_et; + ImageView edit_img; + Button save; + DatabaseReference reference; + FirebaseUser fuser; + Typeface MR,MRR; + + StorageReference storageReference; + private static final int IMAGE_REQUEST = 1; + private Uri imageUri; + private StorageTask uploadTask; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_profile, container, false); + MRR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriad.ttf"); + + + image_profile = view.findViewById(R.id.profile_image); + username = view.findViewById(R.id.username); + profile_tv = view.findViewById(R.id.profile_tv); + bio_et = view.findViewById(R.id.bio_et); + edit_img = view.findViewById(R.id.edit_image); + save = view.findViewById(R.id.save_btn); + + + username.setTypeface(MR); + profile_tv.setTypeface(MR); + bio_et.setTypeface(MRR); + save.setTypeface(MR); + + storageReference = FirebaseStorage.getInstance().getReference("uploads"); + + fuser = FirebaseAuth.getInstance().getCurrentUser(); + reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); + + edit_img.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + save.setVisibility(View.VISIBLE); + username.setEnabled(true); + bio_et.setEnabled(true); + username.setSelection(username.getText().length()); + } + }); + + save.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + username.setEnabled(false); + bio_et.setEnabled(false); + + + reference.child("bio").setValue(bio_et.getText().toString().trim()).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + // Toast.makeText(getContext(),"Profile Updated...", Toast.LENGTH_SHORT); + } + else{ + // Toast.makeText(getContext(),"Unable to Save...", Toast.LENGTH_SHORT); + + } + } + }); + + + + reference.child("username").setValue(username.getText().toString().trim()).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Toast.makeText(getContext(),"Profile Updated...", Toast.LENGTH_SHORT); + } + else{ + Toast.makeText(getContext(),"Unable to Save...", Toast.LENGTH_SHORT); + + } + } + }); + + save.setVisibility(View.GONE); + } + + }); + + + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + if(isAdded()){ + User user = dataSnapshot.getValue(User.class); + username.setText(user.getUsername()); + bio_et.setText(user.getBio()); + if (user.getImageURL().equals("default")){ + image_profile.setImageResource(R.drawable.profile_img); + } else { + Glide.with(getContext()).load(user.getImageURL()).into(image_profile); + } + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + image_profile.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openImage(); + } + }); + + return view; + } + + private void openImage() { + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(intent, IMAGE_REQUEST); + } + + private String getFileExtension(Uri uri){ + ContentResolver contentResolver = getContext().getContentResolver(); + MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); + return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri)); + } + + private void uploadImage(){ + final ProgressDialog pd = new ProgressDialog(getContext()); + pd.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ic_picture)); + + pd.setMessage("Uploading..."); + pd.show(); + + if (imageUri != null){ + final StorageReference fileReference = storageReference.child(System.currentTimeMillis() + +"."+getFileExtension(imageUri)); + + uploadTask = fileReference.putFile(imageUri); + uploadTask.continueWithTask(new Continuation>() { + @Override + public Task then(@NonNull Task task) throws Exception { + if (!task.isSuccessful()){ + throw task.getException(); + } + + return fileReference.getDownloadUrl(); + } + }).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Uri downloadUri = task.getResult(); + String mUri = downloadUri.toString(); + + reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); + HashMap map = new HashMap<>(); + map.put("imageURL", ""+mUri); + reference.updateChildren(map); + + pd.dismiss(); + } else { + Toast.makeText(getContext(), "Failed!", Toast.LENGTH_SHORT).show(); + pd.dismiss(); + } + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); + pd.dismiss(); + } + }); + } else { + Toast.makeText(getContext(), "No image selected", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == IMAGE_REQUEST && resultCode == RESULT_OK + && data != null && data.getData() != null){ + imageUri = data.getData(); + + if (uploadTask != null && uploadTask.isInProgress()){ + Toast.makeText(getContext(), "Upload in progress", Toast.LENGTH_SHORT).show(); + } else { + uploadImage(); + } + } + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Fragments/UsersFragment.java b/app/src/main/java/com/saharsh/chatapp/Fragments/UsersFragment.java new file mode 100644 index 0000000..6a5a8dd --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Fragments/UsersFragment.java @@ -0,0 +1,176 @@ +package com.saharsh.chatapp.Fragments; + +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v7.widget.DividerItemDecoration; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.Query; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.Adapter.OnItemClick; +import com.saharsh.chatapp.Adapter.UserAdapter; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.R; + +import java.util.ArrayList; +import java.util.List; + + +public class UsersFragment extends Fragment { + + private RecyclerView recyclerView; + + Typeface MR, MRR; + FrameLayout frameLayout; + TextView es_descp, es_title; + + private UserAdapter userAdapter; + private List mUsers; + static OnItemClick onItemClick; + + EditText search_users; + + public static UsersFragment newInstance(OnItemClick click) { + onItemClick = click; + Bundle args = new Bundle(); + + UsersFragment fragment = new UsersFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + View view = inflater.inflate(R.layout.fragment_users, container, false); + + + MRR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getContext().getAssets(), "fonts/myriad.ttf"); + + recyclerView = view.findViewById(R.id.recycler_view); + frameLayout = view.findViewById(R.id.es_layout); + es_descp = view.findViewById(R.id.es_descp); + es_title = view.findViewById(R.id.es_title); + + es_descp.setTypeface(MR); + es_title.setTypeface(MRR); + + recyclerView.setHasFixedSize(true); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL); + recyclerView.addItemDecoration(dividerItemDecoration); + + mUsers = new ArrayList<>(); + + readUsers(); + + search_users = view.findViewById(R.id.search_users); + search_users.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + searchUsers(charSequence.toString().toLowerCase()); + } + + @Override + public void afterTextChanged(Editable editable) { + + } + }); + + return view; + } + + private void searchUsers(String s) { + + final FirebaseUser fuser = FirebaseAuth.getInstance().getCurrentUser(); + Query query = FirebaseDatabase.getInstance().getReference("Users").orderByChild("search") + .startAt(s) + .endAt(s+"\uf8ff"); + + query.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + mUsers.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + User user = snapshot.getValue(User.class); + + assert user != null; + assert fuser != null; + if (!user.getId().equals(fuser.getUid())){ + mUsers.add(user); + } + } + + userAdapter = new UserAdapter(getContext(),onItemClick, mUsers, false); + recyclerView.setAdapter(userAdapter); + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + } + + private void readUsers() { + + final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users"); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + if (search_users.getText().toString().equals("")) { + mUsers.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()) { + User user = snapshot.getValue(User.class); + + if (user!= null && user.getId()!=null && firebaseUser!=null && !user.getId().equals(firebaseUser.getUid())) { + mUsers.add(user); + } + } + + if(mUsers.size()==0){ + frameLayout.setVisibility(View.VISIBLE); + } + else{ + frameLayout.setVisibility(View.GONE); + } + + userAdapter = new UserAdapter(getContext(), onItemClick,mUsers, false); + recyclerView.setAdapter(userAdapter); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/LoginActivity.java b/app/src/main/java/com/saharsh/chatapp/LoginActivity.java new file mode 100644 index 0000000..1ee89eb --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/LoginActivity.java @@ -0,0 +1,106 @@ +package com.saharsh.chatapp; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; + +public class LoginActivity extends AppCompatActivity { + + EditText email, password; + Button btn_login; + Typeface MR,MRR; + ProgressDialog dialog; + + FirebaseAuth auth; + TextView forgot_password, login_tv, msg_tv; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle("Login"); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + auth = FirebaseAuth.getInstance(); + + login_tv = findViewById(R.id.login_tv); + email = findViewById(R.id.email); + password = findViewById(R.id.password); + btn_login = findViewById(R.id.btn_login); + forgot_password = findViewById(R.id.forgot_password); + msg_tv = findViewById(R.id.msg_tv); + + msg_tv.setTypeface(MRR); + login_tv.setTypeface(MR); + email.setTypeface(MRR); + password.setTypeface(MRR); + btn_login.setTypeface(MRR); + forgot_password.setTypeface(MRR); + + forgot_password.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(LoginActivity.this, ResetPasswordActivity.class)); + } + }); + + btn_login.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + String txt_email = email.getText().toString(); + String txt_password = password.getText().toString(); + + Utils.hideKeyboard(LoginActivity.this); + + if (TextUtils.isEmpty(txt_email) || TextUtils.isEmpty(txt_password)){ + Toast.makeText(LoginActivity.this, "All fields are required", Toast.LENGTH_SHORT).show(); + } else { + + dialog = Utils.showLoader(LoginActivity.this); + auth.signInWithEmailAndPassword(txt_email, txt_password) + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Intent intent = new Intent(LoginActivity.this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + if(dialog!=null){ + dialog.dismiss(); + } + startActivity(intent); + finish(); + } else { + if(dialog!=null){ + dialog.dismiss(); + } + Toast.makeText(LoginActivity.this, "Authentication failed!", Toast.LENGTH_SHORT).show(); + + } + } + }); + } + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/MainActivity.java b/app/src/main/java/com/saharsh/chatapp/MainActivity.java new file mode 100644 index 0000000..6e06679 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/MainActivity.java @@ -0,0 +1,251 @@ +package com.saharsh.chatapp; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.bumptech.glide.Glide; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.Adapter.OnItemClick; +import com.saharsh.chatapp.Fragments.ChatsFragment; +import com.saharsh.chatapp.Fragments.ProfileFragment; +import com.saharsh.chatapp.Fragments.UsersFragment; +import com.saharsh.chatapp.Model.Chat; +import com.saharsh.chatapp.Model.User; + +import java.util.ArrayList; +import java.util.HashMap; + +import de.hdodenhof.circleimageview.CircleImageView; + +public class MainActivity extends AppCompatActivity implements OnItemClick { + + boolean doubleBackToExitPressedOnce = false; + CircleImageView profile_image; + TextView username; + ProgressDialog dialog; + Typeface MR,MRR; + + FirebaseUser firebaseUser; + DatabaseReference reference; + OnItemClick onItemClick; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + this.onItemClick = this; + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle(""); + + profile_image = findViewById(R.id.profile_image); + final TabLayout tabLayout = findViewById(R.id.tab_layout); + final ViewPager viewPager = findViewById(R.id.view_pager); + + profile_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + TabLayout.Tab tab = tabLayout.getTabAt(2); + tab.select(); + + } + }); + username = findViewById(R.id.username); + username.setTypeface(MR); + + firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser.getUid()); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + User user = dataSnapshot.getValue(User.class); + username.setText(user.getUsername()); + if (user.getImageURL().equals("default")){ + profile_image.setImageResource(R.drawable.profile_img); + } else { + //change this + Glide.with(getApplicationContext()).load(user.getImageURL()).into(profile_image); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + + reference = FirebaseDatabase.getInstance().getReference("Chats"); + dialog = Utils.showLoader(MainActivity.this); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager()); + int unread = 0; + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chat chat = snapshot.getValue(Chat.class); + if (chat.getReceiver().equals(firebaseUser.getUid()) && !chat.isIsseen()){ + unread++; + } + } + + if (unread == 0){ + viewPagerAdapter.addFragment(ChatsFragment.newInstance(onItemClick), "Chats"); + } else { + viewPagerAdapter.addFragment(ChatsFragment.newInstance(onItemClick), "("+unread+") Chats"); + } + + viewPagerAdapter.addFragment(UsersFragment.newInstance(onItemClick), "Users"); + viewPagerAdapter.addFragment(new ProfileFragment(), "Profile"); + + viewPager.setAdapter(viewPagerAdapter); + + tabLayout.setupWithViewPager(viewPager); + if(dialog!=null){ + dialog.dismiss(); + } + + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()){ + + case R.id.logout: + FirebaseAuth.getInstance().signOut(); + // change this code beacuse your app will crash + startActivity(new Intent(MainActivity.this, StartActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); + return true; + } + + return false; + } + + @Override + public void onItemCLick(String uid, View view) { + + ViewProfileActivity viewProfileActivity = + ViewProfileActivity.newInstance(uid,this); + viewProfileActivity.show(getSupportFragmentManager(), + "view_profile"); + + } + + class ViewPagerAdapter extends FragmentPagerAdapter { + + private ArrayList fragments; + private ArrayList titles; + + ViewPagerAdapter(FragmentManager fm){ + super(fm); + this.fragments = new ArrayList<>(); + this.titles = new ArrayList<>(); + } + + @Override + public Fragment getItem(int position) { + return fragments.get(position); + } + + @Override + public int getCount() { + return fragments.size(); + } + + public void addFragment(Fragment fragment, String title){ + fragments.add(fragment); + titles.add(title); + } + + // Ctrl + O + + @Nullable + @Override + public CharSequence getPageTitle(int position) { + return titles.get(position); + } + } + + private void status(String status){ + reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser.getUid()); + + HashMap hashMap = new HashMap<>(); + hashMap.put("status", status); + + reference.updateChildren(hashMap); + } + + @Override + protected void onResume() { + super.onResume(); + status("online"); + } + + @Override + protected void onPause() { + super.onPause(); + status("offline"); + } + + @Override + public void onBackPressed() { + if (doubleBackToExitPressedOnce) { + super.onBackPressed(); + return; + } + + this.doubleBackToExitPressedOnce = true; + Toast.makeText(this, "Please click Back again to exit", Toast.LENGTH_SHORT).show(); + + new Handler().postDelayed(new Runnable() { + + @Override + public void run() { + doubleBackToExitPressedOnce=false; + } + }, 2000); } +} diff --git a/app/src/main/java/com/saharsh/chatapp/MessageActivity.java b/app/src/main/java/com/saharsh/chatapp/MessageActivity.java new file mode 100644 index 0000000..9118575 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/MessageActivity.java @@ -0,0 +1,332 @@ +package com.saharsh.chatapp; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; + +import com.bumptech.glide.Glide; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.Query; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.Adapter.MessageAdapter; +import com.saharsh.chatapp.Fragments.APIService; +import com.saharsh.chatapp.Model.Chat; +import com.saharsh.chatapp.Model.User; +import com.saharsh.chatapp.Notifications.Client; +import com.saharsh.chatapp.Notifications.Data; +import com.saharsh.chatapp.Notifications.MyResponse; +import com.saharsh.chatapp.Notifications.Token; +import com.saharsh.chatapp.Notifications.Sender; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import de.hdodenhof.circleimageview.CircleImageView; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public class MessageActivity extends AppCompatActivity { + + CircleImageView profile_image; + TextView username; + + Typeface MR, MRR; + + FirebaseUser fuser; + DatabaseReference reference; + + ImageButton btn_send; + EditText text_send; + + MessageAdapter messageAdapter; + List mchat; + + RecyclerView recyclerView; + + Intent intent; + + ValueEventListener seenListener; + + String userid; + + APIService apiService; + + boolean notify = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_message); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle(""); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + // and this + startActivity(new Intent(MessageActivity.this, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); + } + }); + + apiService = Client.getClient("https://fcm.googleapis.com/").create(APIService.class); + + recyclerView = findViewById(R.id.recycler_view); + recyclerView.setHasFixedSize(true); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext()); + linearLayoutManager.setStackFromEnd(true); + recyclerView.setLayoutManager(linearLayoutManager); + + profile_image = findViewById(R.id.profile_image); + username = findViewById(R.id.username); + btn_send = findViewById(R.id.btn_send); + text_send = findViewById(R.id.text_send); + + username.setTypeface(MR); + text_send.setTypeface(MRR); + + + intent = getIntent(); + userid = intent.getStringExtra("userid"); + fuser = FirebaseAuth.getInstance().getCurrentUser(); + + btn_send.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + notify = true; + String msg = text_send.getText().toString(); + String time = String.valueOf(System.currentTimeMillis()); + if (!msg.equals("")){ + sendMessage(fuser.getUid(), userid, msg, time); + } else { + Toast.makeText(MessageActivity.this, "You can't send empty message", Toast.LENGTH_SHORT).show(); + } + text_send.setText(""); + } + }); + + + reference = FirebaseDatabase.getInstance().getReference("Users").child(userid); + + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + User user = dataSnapshot.getValue(User.class); + username.setText(user.getUsername()); + if (user.getImageURL().equals("default")){ + profile_image.setImageResource(R.drawable.profile_img); + } else { + //and this + Glide.with(getApplicationContext()).load(user.getImageURL()).into(profile_image); + } + + readMesagges(fuser.getUid(), userid, user.getImageURL()); + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + seenMessage(userid); + } + + private void seenMessage(final String userid){ + reference = FirebaseDatabase.getInstance().getReference("Chats"); + seenListener = reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chat chat = snapshot.getValue(Chat.class); + if (chat.getReceiver().equals(fuser.getUid()) && chat.getSender().equals(userid)){ + HashMap hashMap = new HashMap<>(); + hashMap.put("isseen", true); + snapshot.getRef().updateChildren(hashMap); + } + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + private void sendMessage(String sender, final String receiver, String message, String time){ + + DatabaseReference reference = FirebaseDatabase.getInstance().getReference(); + + HashMap hashMap = new HashMap<>(); + hashMap.put("sender", sender); + hashMap.put("receiver", receiver); + hashMap.put("message", message); + hashMap.put("isseen", false); + hashMap.put("time", time); + + reference.child("Chats").push().setValue(hashMap); + + + // add user to chat fragment + final DatabaseReference chatRef = FirebaseDatabase.getInstance().getReference("Chatlist") + .child(fuser.getUid()) + .child(userid); + + chatRef.addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + if (!dataSnapshot.exists()){ + chatRef.child("id").setValue(userid); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + + final DatabaseReference chatRefReceiver = FirebaseDatabase.getInstance().getReference("Chatlist") + .child(userid) + .child(fuser.getUid()); + chatRefReceiver.child("id").setValue(fuser.getUid()); + + final String msg = message; + + reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + User user = dataSnapshot.getValue(User.class); + if (notify) { + sendNotifiaction(receiver, user.getUsername(), msg); + } + notify = false; + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + private void sendNotifiaction(String receiver, final String username, final String message){ + DatabaseReference tokens = FirebaseDatabase.getInstance().getReference("Tokens"); + Query query = tokens.orderByKey().equalTo(receiver); + query.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Token token = snapshot.getValue(Token.class); + Data data = new Data(fuser.getUid(), R.drawable.profile_img, username+": "+message, "New Message", + userid); + + Sender sender = new Sender(data, token.getToken()); + + apiService.sendNotification(sender) + .enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.code() == 200){ + if (response.body().success != 1){ + //Toast.makeText(MessageActivity.this, "Failed!", Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + + } + }); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + private void readMesagges(final String myid, final String userid, final String imageurl){ + mchat = new ArrayList<>(); + + reference = FirebaseDatabase.getInstance().getReference("Chats"); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + mchat.clear(); + for (DataSnapshot snapshot : dataSnapshot.getChildren()){ + Chat chat = snapshot.getValue(Chat.class); + if (chat.getReceiver().equals(myid) && chat.getSender().equals(userid) || + chat.getReceiver().equals(userid) && chat.getSender().equals(myid)){ + mchat.add(chat); + } + + messageAdapter = new MessageAdapter(MessageActivity.this, mchat, imageurl); + recyclerView.setAdapter(messageAdapter); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + private void currentUser(String userid){ + SharedPreferences.Editor editor = getSharedPreferences("PREFS", MODE_PRIVATE).edit(); + editor.putString("currentuser", userid); + editor.apply(); + } + + private void status(String status){ + reference = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid()); + + HashMap hashMap = new HashMap<>(); + hashMap.put("status", status); + + reference.updateChildren(hashMap); + } + + @Override + protected void onResume() { + super.onResume(); + status("online"); + currentUser(userid); + } + + @Override + protected void onPause() { + super.onPause(); + reference.removeEventListener(seenListener); + status("offline"); + currentUser("none"); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Model/Chat.java b/app/src/main/java/com/saharsh/chatapp/Model/Chat.java new file mode 100644 index 0000000..c73b9e5 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Model/Chat.java @@ -0,0 +1,61 @@ +package com.saharsh.chatapp.Model; + +public class Chat { + + private String sender; + private String receiver; + private String message; + private boolean isseen; + private String time; + + public Chat(String sender, String receiver, String message, boolean isseen, String time) { + this.sender = sender; + this.receiver = receiver; + this.message = message; + this.isseen = isseen; + this.time = time; + } + + public Chat() { + } + + public String getSender() { + return sender; + } + + public void setSender(String sender) { + this.sender = sender; + } + + public String getReceiver() { + return receiver; + } + + public void setReceiver(String receiver) { + this.receiver = receiver; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isIsseen() { + return isseen; + } + + public void setIsseen(boolean isseen) { + this.isseen = isseen; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Model/Chatlist.java b/app/src/main/java/com/saharsh/chatapp/Model/Chatlist.java new file mode 100644 index 0000000..9ae68c2 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Model/Chatlist.java @@ -0,0 +1,20 @@ +package com.saharsh.chatapp.Model; + +public class Chatlist { + public String id; + + public Chatlist(String id) { + this.id = id; + } + + public Chatlist() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Model/User.java b/app/src/main/java/com/saharsh/chatapp/Model/User.java new file mode 100644 index 0000000..de70900 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Model/User.java @@ -0,0 +1,73 @@ +package com.saharsh.chatapp.Model; + +public class User { + + private String id; + private String username; + private String imageURL; + private String status; + private String search; + private String bio; + + + public User(String id, String username, String imageURL, String status, String search, String bio) { + this.id = id; + this.username = username; + this.imageURL = imageURL; + this.status = status; + this.search = search; + this.bio = bio; + } + + public User() { + + } + + public String getBio() { + return bio; + } + + public void setBio(String bio) { + this.bio = bio; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getImageURL() { + return imageURL; + } + + public void setImageURL(String imageURL) { + this.imageURL = imageURL; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getSearch() { + return search; + } + + public void setSearch(String search) { + this.search = search; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/Client.java b/app/src/main/java/com/saharsh/chatapp/Notifications/Client.java new file mode 100644 index 0000000..245f5ae --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/Client.java @@ -0,0 +1,19 @@ +package com.saharsh.chatapp.Notifications; + +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class Client { + + private static Retrofit retrofit = null; + + public static Retrofit getClient(String url){ + if (retrofit == null){ + retrofit = new Retrofit.Builder() + .baseUrl(url) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + } + return retrofit; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/Data.java b/app/src/main/java/com/saharsh/chatapp/Notifications/Data.java new file mode 100644 index 0000000..c0e479f --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/Data.java @@ -0,0 +1,60 @@ +package com.saharsh.chatapp.Notifications; + +public class Data { + private String user; + private int icon; + private String body; + private String title; + private String sented; + + public Data(String user, int icon, String body, String title, String sented) { + this.user = user; + this.icon = icon; + this.body = body; + this.title = title; + this.sented = sented; + } + + public Data() { + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public int getIcon() { + return icon; + } + + public void setIcon(int icon) { + this.icon = icon; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSented() { + return sented; + } + + public void setSented(String sented) { + this.sented = sented; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseIdService.java b/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseIdService.java new file mode 100644 index 0000000..6228d46 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseIdService.java @@ -0,0 +1,30 @@ +package com.saharsh.chatapp.Notifications; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.FirebaseInstanceIdService; + +public class MyFirebaseIdService extends FirebaseInstanceIdService { + + @Override + public void onTokenRefresh() { + super.onTokenRefresh(); + FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + + String refreshToken = FirebaseInstanceId.getInstance().getToken(); + if (firebaseUser != null){ + updateToken(refreshToken); + } + } + + private void updateToken(String refreshToken) { + FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + + DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Tokens"); + Token token = new Token(refreshToken); + reference.child(firebaseUser.getUid()).setValue(token); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseMessaging.java b/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseMessaging.java new file mode 100644 index 0000000..6e8b78d --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/MyFirebaseMessaging.java @@ -0,0 +1,108 @@ +package com.saharsh.chatapp.Notifications; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.NotificationCompat; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; +import com.saharsh.chatapp.MessageActivity; + +public class MyFirebaseMessaging extends FirebaseMessagingService { + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + super.onMessageReceived(remoteMessage); + + String sented = remoteMessage.getData().get("sented"); + String user = remoteMessage.getData().get("user"); + + SharedPreferences preferences = getSharedPreferences("PREFS", MODE_PRIVATE); + String currentUser = preferences.getString("currentuser", "none"); + + FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + + if (firebaseUser != null && sented.equals(firebaseUser.getUid())){ + if (!currentUser.equals(user)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + sendOreoNotification(remoteMessage); + } else { + sendNotification(remoteMessage); + } + } + } + } + + private void sendOreoNotification(RemoteMessage remoteMessage){ + String user = remoteMessage.getData().get("user"); + String icon = remoteMessage.getData().get("icon"); + String title = remoteMessage.getData().get("title"); + String body = remoteMessage.getData().get("body"); + + RemoteMessage.Notification notification = remoteMessage.getNotification(); + int j = Integer.parseInt(user.replaceAll("[\\D]", "")); + Intent intent = new Intent(this, MessageActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("userid", user); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + PendingIntent pendingIntent = PendingIntent.getActivity(this, j, intent, PendingIntent.FLAG_ONE_SHOT); + Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + + com.saharsh.chatapp.Notifications.OreoNotification oreoNotification = new com.saharsh.chatapp.Notifications.OreoNotification(this); + Notification.Builder builder = oreoNotification.getOreoNotification(title, body, pendingIntent, + defaultSound, icon); + + int i = 0; + if (j > 0){ + i = j; + } + + oreoNotification.getManager().notify(i, builder.build()); + + } + + private void sendNotification(RemoteMessage remoteMessage) { + + String user = remoteMessage.getData().get("user"); + String icon = remoteMessage.getData().get("icon"); + String title = remoteMessage.getData().get("title"); + String body = remoteMessage.getData().get("body"); + + RemoteMessage.Notification notification = remoteMessage.getNotification(); + int j = Integer.parseInt(user.replaceAll("[\\D]", "")); + Intent intent = new Intent(this, MessageActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("userid", user); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + PendingIntent pendingIntent = PendingIntent.getActivity(this, j, intent, PendingIntent.FLAG_ONE_SHOT); + + Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + NotificationCompat.Builder builder = new NotificationCompat.Builder(this) + .setSmallIcon(Integer.parseInt(icon)) + .setContentTitle(title) + .setContentText(body) + .setAutoCancel(true) + .setSound(defaultSound) + .setContentIntent(pendingIntent); + NotificationManager noti = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); + + int i = 0; + if (j > 0){ + i = j; + } + + noti.notify(i, builder.build()); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/MyResponse.java b/app/src/main/java/com/saharsh/chatapp/Notifications/MyResponse.java new file mode 100644 index 0000000..766dbe4 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/MyResponse.java @@ -0,0 +1,6 @@ +package com.saharsh.chatapp.Notifications; + +public class MyResponse { + + public int success; +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/OreoNotification.java b/app/src/main/java/com/saharsh/chatapp/Notifications/OreoNotification.java new file mode 100644 index 0000000..a802e66 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/OreoNotification.java @@ -0,0 +1,60 @@ +package com.saharsh.chatapp.Notifications; + +import android.annotation.TargetApi; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.ContextWrapper; +import android.net.Uri; +import android.os.Build; + +public class OreoNotification extends ContextWrapper { + + private static final String CHANNEL_ID = "com.koddev.chatapp"; + private static final String CHANNEL_NAME = "chatapp"; + + private NotificationManager notificationManager; + + public OreoNotification(Context base) { + super(base); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + createChannel(); + } + } + + @TargetApi(Build.VERSION_CODES.O) + private void createChannel() { + + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + CHANNEL_NAME, + NotificationManager.IMPORTANCE_DEFAULT); + channel.enableLights(false); + channel.enableVibration(true); + channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); + + getManager().createNotificationChannel(channel); + } + + public NotificationManager getManager(){ + if (notificationManager == null){ + notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); + } + + return notificationManager; + } + + @TargetApi(Build.VERSION_CODES.O) + public Notification.Builder getOreoNotification(String title, String body, + PendingIntent pendingIntent, Uri soundUri, String icon){ + return new Notification.Builder(getApplicationContext(), CHANNEL_ID) + .setContentIntent(pendingIntent) + .setContentTitle(title) + .setContentText(body) + .setSmallIcon(Integer.parseInt(icon)) + .setSound(soundUri) + .setAutoCancel(true); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/Sender.java b/app/src/main/java/com/saharsh/chatapp/Notifications/Sender.java new file mode 100644 index 0000000..51b6bd4 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/Sender.java @@ -0,0 +1,11 @@ +package com.saharsh.chatapp.Notifications; + +public class Sender { + public Data data; + public String to; + + public Sender(Data data, String to) { + this.data = data; + this.to = to; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Notifications/Token.java b/app/src/main/java/com/saharsh/chatapp/Notifications/Token.java new file mode 100644 index 0000000..3a09527 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Notifications/Token.java @@ -0,0 +1,20 @@ +package com.saharsh.chatapp.Notifications; + +public class Token { + private String token; + + public Token(String token) { + this.token = token; + } + + public Token() { + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/RegisterActivity.java b/app/src/main/java/com/saharsh/chatapp/RegisterActivity.java new file mode 100644 index 0000000..f5dad86 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/RegisterActivity.java @@ -0,0 +1,131 @@ +package com.saharsh.chatapp; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.rengwuxian.materialedittext.MaterialEditText; + +import java.util.HashMap; + +public class RegisterActivity extends AppCompatActivity { + + EditText username, email, password; + TextView register_tv, msg_reg_tv; + Button btn_register; + Typeface MR, MRR; + FirebaseAuth auth; + DatabaseReference reference; + ProgressDialog dialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_register); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle("Register"); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + username = findViewById(R.id.username); + email = findViewById(R.id.email); + password = findViewById(R.id.password); + btn_register = findViewById(R.id.btn_register); + register_tv = findViewById(R.id.register_tv); + msg_reg_tv = findViewById(R.id.msg_reg_tv); + + msg_reg_tv.setTypeface(MRR); + username.setTypeface(MRR); + email.setTypeface(MRR); + password.setTypeface(MRR); + btn_register.setTypeface(MR); + register_tv.setTypeface(MR); + + auth = FirebaseAuth.getInstance(); + + btn_register.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + String txt_username = username.getText().toString(); + String txt_email = email.getText().toString(); + String txt_password = password.getText().toString(); + Utils.hideKeyboard(RegisterActivity.this); + + if (TextUtils.isEmpty(txt_username) || TextUtils.isEmpty(txt_email) || TextUtils.isEmpty(txt_password)){ + Toast.makeText(RegisterActivity.this, "All fileds are required", Toast.LENGTH_SHORT).show(); + } else if (txt_password.length() < 6 ){ + Toast.makeText(RegisterActivity.this, "password must be at least 6 characters", Toast.LENGTH_SHORT).show(); + } else { + register(txt_username, txt_email, txt_password); + } + } + }); + } + + private void register(final String username, String email, String password){ + + dialog = Utils.showLoader(RegisterActivity.this); + + auth.createUserWithEmailAndPassword(email, password) + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + FirebaseUser firebaseUser = auth.getCurrentUser(); + assert firebaseUser != null; + String userid = firebaseUser.getUid(); + + reference = FirebaseDatabase.getInstance().getReference("Users").child(userid); + + HashMap hashMap = new HashMap<>(); + hashMap.put("id", userid); + hashMap.put("username", username); + hashMap.put("imageURL", "default"); + hashMap.put("status", "offline"); + hashMap.put("bio", ""); + hashMap.put("search", username.toLowerCase()); + if(dialog!=null){ + dialog.dismiss(); + } + reference.setValue(hashMap).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Intent intent = new Intent(RegisterActivity.this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); + } + } + }); + } else { + Toast.makeText(RegisterActivity.this, "You can't register woth this email or password", Toast.LENGTH_SHORT).show(); + if(dialog!=null){ + dialog.dismiss(); + } + } + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/ResetPasswordActivity.java b/app/src/main/java/com/saharsh/chatapp/ResetPasswordActivity.java new file mode 100644 index 0000000..648df08 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/ResetPasswordActivity.java @@ -0,0 +1,76 @@ +package com.saharsh.chatapp; + +import android.content.Intent; +import android.graphics.Typeface; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.FirebaseAuth; + +public class ResetPasswordActivity extends AppCompatActivity { + + EditText send_email; + Button btn_reset; + Typeface MR, MRR; + TextView hint_tv; + FirebaseAuth firebaseAuth; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_reset_password); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle("Reset Password"); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + send_email = findViewById(R.id.send_email); + btn_reset = findViewById(R.id.btn_reset); + hint_tv = findViewById(R.id.hint_tv); + + send_email.setTypeface(MRR); + btn_reset.setTypeface(MR); + hint_tv.setTypeface(MR); + + firebaseAuth = FirebaseAuth.getInstance(); + + btn_reset.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + String email = send_email.getText().toString(); + Utils.hideKeyboard(ResetPasswordActivity.this); + + if (email.equals("")){ + Toast.makeText(ResetPasswordActivity.this, "All fileds are required!", Toast.LENGTH_SHORT).show(); + } else { + firebaseAuth.sendPasswordResetEmail(email).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()){ + Toast.makeText(ResetPasswordActivity.this, "Please check you Email", Toast.LENGTH_SHORT).show(); + startActivity(new Intent(ResetPasswordActivity.this, LoginActivity.class)); + } else { + String error = task.getException().getMessage(); + Toast.makeText(ResetPasswordActivity.this, error, Toast.LENGTH_SHORT).show(); + } + } + }); + } + } + }); + + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/StartActivity.java b/app/src/main/java/com/saharsh/chatapp/StartActivity.java new file mode 100644 index 0000000..0d3752e --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/StartActivity.java @@ -0,0 +1,69 @@ +package com.saharsh.chatapp; + +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +public class StartActivity extends AppCompatActivity { + + Button login, register; + TextView chat_title_tv; + Typeface MR, MRR; + + FirebaseUser firebaseUser; + + @Override + protected void onStart() { + super.onStart(); + + + firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + + //check if user is null + if (firebaseUser != null){ + Intent intent = new Intent(StartActivity.this, MainActivity.class); + startActivity(intent); + finish(); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_start); + + MRR = Typeface.createFromAsset(getAssets(), "fonts/myriadregular.ttf"); + MR = Typeface.createFromAsset(getAssets(), "fonts/myriad.ttf"); + + + + login = findViewById(R.id.login); + register = findViewById(R.id.register); + chat_title_tv = findViewById(R.id.chat_title_tv); + + login.setTypeface(MR); + register.setTypeface(MR); + chat_title_tv.setTypeface(MR); + + login.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(StartActivity.this, LoginActivity.class)); + } + }); + + register.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(StartActivity.this, RegisterActivity.class)); + } + }); + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/Utils.java b/app/src/main/java/com/saharsh/chatapp/Utils.java new file mode 100644 index 0000000..d06dd49 --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/Utils.java @@ -0,0 +1,46 @@ +package com.saharsh.chatapp; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.ProgressBar; + +public class Utils { + + public static ProgressDialog showLoader(Context context){ + ProgressDialog dialog = new ProgressDialog(context); + try { + dialog.show(); + } catch (WindowManager.BadTokenException e) { + + } + dialog.setCancelable(false); + dialog.getWindow() + .setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); + dialog.setContentView(R.layout.progressdialog); + return dialog; + // dialog.setMessage(Message); + } + + public static void hideKeyboard(Activity activity) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); + //Find the currently focused view, so we can grab the correct window token from it. + View view = activity.getCurrentFocus(); + //If no view currently has focus, create a new one, just so we can grab a window token from it + if (view == null) { + view = new View(activity); + } + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + + public static void hideLoader(ProgressDialog dialog){ + // To dismiss the dialog + if(dialog!=null){ + dialog.dismiss(); + } + } +} diff --git a/app/src/main/java/com/saharsh/chatapp/ViewProfileActivity.java b/app/src/main/java/com/saharsh/chatapp/ViewProfileActivity.java new file mode 100644 index 0000000..b91546d --- /dev/null +++ b/app/src/main/java/com/saharsh/chatapp/ViewProfileActivity.java @@ -0,0 +1,87 @@ +package com.saharsh.chatapp; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.BottomSheetDialogFragment; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.saharsh.chatapp.Model.User; + +public class ViewProfileActivity extends BottomSheetDialogFragment { + + String uid; + DatabaseReference reference; + TextView username, bio_et; + ImageView profile_img; + static Context mContext; + + + public ViewProfileActivity() { + + } + + public static ViewProfileActivity newInstance(String uid, Context context) { + + Bundle args = new Bundle(); + args.putString("uid",uid); + mContext = context; + ViewProfileActivity fragment = new ViewProfileActivity(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.activity_view_profile,container,false); + if(getArguments()!=null){ + uid = getArguments().getString("uid"); + profile_img = view.findViewById(R.id.view_profile_image); + username = view.findViewById(R.id.view_username); + bio_et = view.findViewById(R.id.view_bio_et); + + reference = FirebaseDatabase.getInstance().getReference("Users").child(uid); + reference.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + User user = dataSnapshot.getValue(User.class); + username.setText(user.getUsername()); + bio_et.setText(user.getBio()); + if (user.getImageURL().equals("default")){ + profile_img.setImageResource(R.drawable.profile_img); + } else { + //change this + Glide.with(mContext.getApplicationContext()).load(user.getImageURL()).into(profile_img); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError databaseError) { + + } + }); + } + + return view; + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_action_name.png b/app/src/main/res/drawable-hdpi/ic_action_name.png new file mode 100644 index 0000000..36190ec Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_name.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_name.png b/app/src/main/res/drawable-mdpi/ic_action_name.png new file mode 100644 index 0000000..e6fbd46 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_name.png differ diff --git a/app/src/main/res/drawable-mdpi/rounded_dialog.xml b/app/src/main/res/drawable-mdpi/rounded_dialog.xml new file mode 100644 index 0000000..e095b8a --- /dev/null +++ b/app/src/main/res/drawable-mdpi/rounded_dialog.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/ic_action_name.png b/app/src/main/res/drawable-xhdpi/ic_action_name.png new file mode 100644 index 0000000..a92e695 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_name.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_name.png b/app/src/main/res/drawable-xxhdpi/ic_action_name.png new file mode 100644 index 0000000..86bc64e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_name.png differ diff --git a/app/src/main/res/drawable/background_left.xml b/app/src/main/res/drawable/background_left.xml new file mode 100644 index 0000000..ddd6486 --- /dev/null +++ b/app/src/main/res/drawable/background_left.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_right.xml b/app/src/main/res/drawable/background_right.xml new file mode 100644 index 0000000..5e80d63 --- /dev/null +++ b/app/src/main/res/drawable/background_right.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/button_bg.xml b/app/src/main/res/drawable/button_bg.xml new file mode 100644 index 0000000..540bc76 --- /dev/null +++ b/app/src/main/res/drawable/button_bg.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/edittext_bg.xml b/app/src/main/res/drawable/edittext_bg.xml new file mode 100644 index 0000000..f0b9c02 --- /dev/null +++ b/app/src/main/res/drawable/edittext_bg.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/es_image.xml b/app/src/main/res/drawable/es_image.xml new file mode 100644 index 0000000..93983c0 --- /dev/null +++ b/app/src/main/res/drawable/es_image.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_arrow_img.xml b/app/src/main/res/drawable/ic_arrow_img.xml new file mode 100644 index 0000000..744ffcf --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_img.xml @@ -0,0 +1,21 @@ + + + + diff --git a/app/src/main/res/drawable/ic_chevron_right.xml b/app/src/main/res/drawable/ic_chevron_right.xml new file mode 100644 index 0000000..1ba00ab --- /dev/null +++ b/app/src/main/res/drawable/ic_chevron_right.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/ic_cool_background.xml b/app/src/main/res/drawable/ic_cool_background.xml new file mode 100644 index 0000000..d64b13e --- /dev/null +++ b/app/src/main/res/drawable/ic_cool_background.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml new file mode 100644 index 0000000..46462b5 --- /dev/null +++ b/app/src/main/res/drawable/ic_edit.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_forgot_password.xml b/app/src/main/res/drawable/ic_forgot_password.xml new file mode 100644 index 0000000..fbe20f3 --- /dev/null +++ b/app/src/main/res/drawable/ic_forgot_password.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..ecfe93a --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_login.xml b/app/src/main/res/drawable/ic_login.xml new file mode 100644 index 0000000..dae0d44 --- /dev/null +++ b/app/src/main/res/drawable/ic_login.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_login_vector.xml b/app/src/main/res/drawable/ic_login_vector.xml new file mode 100644 index 0000000..69d0a85 --- /dev/null +++ b/app/src/main/res/drawable/ic_login_vector.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_next.xml b/app/src/main/res/drawable/ic_next.xml new file mode 100644 index 0000000..042c734 --- /dev/null +++ b/app/src/main/res/drawable/ic_next.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_picture.xml b/app/src/main/res/drawable/ic_picture.xml new file mode 100644 index 0000000..126a16b --- /dev/null +++ b/app/src/main/res/drawable/ic_picture.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_plus.xml b/app/src/main/res/drawable/ic_plus.xml new file mode 100644 index 0000000..d057a1f --- /dev/null +++ b/app/src/main/res/drawable/ic_plus.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/ic_send.xml b/app/src/main/res/drawable/ic_send.xml new file mode 100644 index 0000000..9951f35 --- /dev/null +++ b/app/src/main/res/drawable/ic_send.xml @@ -0,0 +1,21 @@ + + + + diff --git a/app/src/main/res/drawable/ic_signup_vector.xml b/app/src/main/res/drawable/ic_signup_vector.xml new file mode 100644 index 0000000..e84c9f0 --- /dev/null +++ b/app/src/main/res/drawable/ic_signup_vector.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_vector_chatapp.xml b/app/src/main/res/drawable/ic_vector_chatapp.xml new file mode 100644 index 0000000..0932ca3 --- /dev/null +++ b/app/src/main/res/drawable/ic_vector_chatapp.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/profile_img.xml b/app/src/main/res/drawable/profile_img.xml new file mode 100644 index 0000000..d87a573 --- /dev/null +++ b/app/src/main/res/drawable/profile_img.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rounded_edittext.xml b/app/src/main/res/drawable/rounded_edittext.xml new file mode 100644 index 0000000..06577cc --- /dev/null +++ b/app/src/main/res/drawable/rounded_edittext.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/search_bg.xml b/app/src/main/res/drawable/search_bg.xml new file mode 100644 index 0000000..0947372 --- /dev/null +++ b/app/src/main/res/drawable/search_bg.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..bb2a029 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + +