items){
27 | super(context, resourceId, items);
28 | this.context = context;
29 | this.items = items;
30 |
31 |
32 | }
33 |
34 | /**
35 | * Populate the item_message with user in the current position
36 | *
37 | * Changes the message aspect if it is from the current user or the match
38 | *
39 | * @param position - position of the list
40 | */
41 | public View getView(int position, View convertView, ViewGroup parent){
42 | RideObject card_item = getItem(position);
43 |
44 | if (convertView == null){
45 | convertView = LayoutInflater.from(getContext()).inflate(R.layout.item__card_request, parent, false);
46 | }
47 |
48 | TextView mDistance = convertView.findViewById(R.id.distance);
49 | TextView mTime = convertView.findViewById(R.id.time);
50 | TextView mRatingText = convertView.findViewById(R.id.ratingText);
51 |
52 | CircularProgressBar mProgressBar = convertView.findViewById(R.id.circularProgressBar);
53 |
54 |
55 | if (card_item != null) {
56 | mDistance.setText(card_item.getCalculatedRideDistance());
57 | mTime.setText(card_item.getCalculatedTime() + " min");
58 | mRatingText.setText(card_item.getCustomer().getRatingString() );
59 | }
60 |
61 |
62 | final Handler ha=new Handler();
63 | ha.postDelayed(new Runnable() {
64 |
65 | @Override
66 | public void run() {
67 | //call function
68 | if (card_item != null) {
69 | card_item.setTimePassed(card_item.getTimePassed() + (float)0.5);
70 | }
71 | if (card_item != null) {
72 | mProgressBar.setProgress(card_item.getTimePassed());
73 | }
74 |
75 | if (card_item != null && card_item.getTimePassed() > 100) {
76 | items.remove(card_item);
77 |
78 | notifyDataSetChanged();
79 | }
80 |
81 | ha.postDelayed(this, 25);
82 |
83 | }
84 | }, 25);
85 |
86 | return convertView;
87 |
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Login/AuthenticationActivity.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Login;
2 |
3 | import android.content.Intent;
4 |
5 | import androidx.fragment.app.FragmentManager;
6 | import androidx.appcompat.app.AppCompatActivity;
7 |
8 | import android.os.Bundle;
9 |
10 | import com.google.firebase.auth.FirebaseAuth;
11 | import com.google.firebase.auth.FirebaseUser;
12 | import com.simcoder.uber.R;
13 |
14 | /**
15 | * This Activity controls the display of auth fragments of the app:
16 | * -MenuFragment
17 | * -LoginFragment
18 | * -RegisterFragment
19 | *
20 | * It is also responsible for taking the user to the main activity if the login or register process is successful
21 | */
22 | public class AuthenticationActivity extends AppCompatActivity {
23 |
24 | FragmentManager fm = getSupportFragmentManager();
25 |
26 | MenuFragment menuFragment = new MenuFragment();
27 |
28 | private FirebaseAuth.AuthStateListener firebaseAuthListener;
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_authentication);
34 |
35 |
36 | //Listens for changes in the auth state
37 | firebaseAuthListener = firebaseAuth -> {
38 | FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
39 | if (user != null) {
40 | Intent intent = new Intent(AuthenticationActivity.this, LauncherActivity.class);
41 | startActivity(intent);
42 | finish();
43 | }
44 | };
45 |
46 | fm.beginTransaction()
47 | .replace(R.id.container, menuFragment, "StartFragment")
48 | .addToBackStack(null)
49 | .commit();
50 | }
51 |
52 | /**
53 | * Displays the RegisterFragment
54 | */
55 | public void registrationClick() {
56 | fm.beginTransaction()
57 | .replace(R.id.container, new RegisterFragment(), "RegisterFragment")
58 | .addToBackStack(null)
59 | .commit();
60 | }
61 |
62 | /**
63 | * Displays the LoginFragment
64 | */
65 | public void loginClick() {
66 | fm.beginTransaction()
67 | .replace(R.id.container, new LoginFragment(), "RegisterFragment")
68 | .addToBackStack(null)
69 | .commit();
70 | }
71 |
72 | @Override
73 | public void onBackPressed() {
74 | if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
75 | getSupportFragmentManager().popBackStack();
76 | } else {
77 | finish();
78 | }
79 | }
80 |
81 | @Override
82 | protected void onStart() {
83 | super.onStart();
84 | FirebaseAuth.getInstance().addAuthStateListener(firebaseAuthListener);
85 | }
86 |
87 | @Override
88 | protected void onStop() {
89 | super.onStop();
90 | FirebaseAuth.getInstance().removeAuthStateListener(firebaseAuthListener);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/dialog_ride_review.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
13 |
23 |
24 |
25 |
31 |
41 |
42 |
52 |
53 |
64 |
65 |
66 |
67 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Objects/CustomerObject.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Objects;
2 |
3 | import com.google.firebase.database.DataSnapshot;
4 |
5 | import java.text.DecimalFormat;
6 |
7 |
8 | /**
9 | * Customer object, it contains all the relevant info of the customer user
10 | */
11 | public class CustomerObject {
12 |
13 |
14 | private String id = "",
15 | name = "",
16 | phone = "",
17 | profileImage = "default",
18 | notificationKey = "";
19 | private float ratingsAvg = 0;
20 |
21 | public CustomerObject(String id) {
22 | this.id = id;
23 | }
24 |
25 | /**
26 | * CustomerObject constructor
27 | * Creates an empty object
28 | */
29 | public CustomerObject() {
30 | }
31 |
32 |
33 | /**
34 | * Parse datasnapshot into this object
35 | *
36 | * @param dataSnapshot - customer info fetched from the database
37 | */
38 | public void parseData(DataSnapshot dataSnapshot) {
39 | id = dataSnapshot.getKey();
40 | if (dataSnapshot.child("name").getValue() != null) {
41 | name = dataSnapshot.child("name").getValue().toString();
42 | }
43 | if (dataSnapshot.child("phone").getValue() != null) {
44 | phone = dataSnapshot.child("phone").getValue().toString();
45 | }
46 | if (dataSnapshot.child("profileImageUrl").getValue() != null) {
47 | profileImage = dataSnapshot.child("profileImageUrl").getValue().toString();
48 | }
49 | if(dataSnapshot.child("notificationKey").getValue()!=null){
50 | notificationKey = dataSnapshot.child("notificationKey").getValue().toString();
51 | }
52 | int ratingSum = 0;
53 | float ratingsTotal = 0;
54 | for (DataSnapshot child : dataSnapshot.child("rating").getChildren()) {
55 | ratingSum = ratingSum + Integer.valueOf(child.getValue().toString());
56 | ratingsTotal++;
57 | }
58 | if (ratingsTotal != 0) {
59 | ratingsAvg = ratingSum / ratingsTotal;
60 | }
61 | }
62 |
63 |
64 |
65 | public String getRatingString(){
66 | DecimalFormat df = new DecimalFormat("#.#");
67 | return df.format(ratingsAvg);
68 | }
69 |
70 | public String getId() {
71 | return id;
72 | }
73 |
74 |
75 | public String getName() {
76 | return name;
77 | }
78 |
79 | public void setName(String name) {
80 | this.name = name;
81 | }
82 |
83 | public String getPhone() {
84 | return phone;
85 | }
86 |
87 | public void setPhone(String phone) {
88 | this.phone = phone;
89 | }
90 |
91 | public String getProfileImage() {
92 | return profileImage;
93 | }
94 |
95 | public void setProfileImage(String profileImage) {
96 | this.profileImage = profileImage;
97 | }
98 |
99 | public String getNotificationKey() {
100 | return notificationKey;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Login/DetailsActivity.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Login;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 |
6 | import com.addisonelliott.segmentedbutton.SegmentedButtonGroup;
7 | import com.google.android.gms.tasks.OnCompleteListener;
8 |
9 | import androidx.appcompat.app.AppCompatActivity;
10 |
11 | import android.view.View;
12 | import android.widget.Button;
13 | import android.widget.EditText;
14 |
15 | import com.google.firebase.auth.FirebaseAuth;
16 | import com.google.firebase.database.FirebaseDatabase;
17 | import com.simcoder.uber.R;
18 |
19 | import java.util.HashMap;
20 | import java.util.Map;
21 |
22 |
23 | /**
24 | * Fragment Responsible for registering a new user
25 | */
26 | public class DetailsActivity extends AppCompatActivity implements View.OnClickListener {
27 |
28 | private EditText mName;
29 |
30 | private SegmentedButtonGroup mRadioGroup;
31 |
32 | @Override
33 | public void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_details);
36 | initializeObjects();
37 | }
38 |
39 |
40 | /**
41 | * Register the user, but before that check if every field is correct.
42 | * After that registers the user and creates an entry for it oin the database
43 | */
44 | private void register() {
45 | if (mName.getText().length() == 0) {
46 | mName.setError("please fill this field");
47 | return;
48 | }
49 |
50 |
51 | final String name = mName.getText().toString();
52 | final String accountType;
53 | int selectId = mRadioGroup.getPosition();
54 |
55 | if (selectId == 1) {
56 | accountType = "Drivers";
57 | } else {
58 | accountType = "Customers";
59 | }
60 |
61 | String user_id = FirebaseAuth.getInstance().getCurrentUser().getUid();
62 | Map newUserMap = new HashMap<>();
63 | newUserMap.put("name", name);
64 | newUserMap.put("profileImageUrl", "default");
65 | if (accountType.equals("Drivers")) {
66 | newUserMap.put("service", "type_1");
67 | newUserMap.put("activated", true);
68 | }
69 | FirebaseDatabase.getInstance().getReference().child("Users").child(accountType).child(user_id).updateChildren(newUserMap).addOnCompleteListener((OnCompleteListener) task -> {
70 | Intent intent = new Intent(DetailsActivity.this, LauncherActivity.class);
71 | startActivity(intent);
72 | finish();
73 | });
74 | }
75 |
76 |
77 | /**
78 | * Initializes the design Elements and calls clickListeners for them
79 | */
80 | private void initializeObjects() {
81 | mName = findViewById(R.id.name);
82 | Button mRegister = findViewById(R.id.register);
83 | mRadioGroup = findViewById(R.id.radioRealButtonGroup);
84 |
85 | mRadioGroup.setPosition(0, false);
86 | mRegister.setOnClickListener(this);
87 | }
88 |
89 | @Override
90 | public void onClick(View view) {
91 | if (view.getId() == R.id.register) {
92 | register();
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Login/RegisterFragment.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Login;
2 |
3 | import android.os.Bundle;
4 |
5 | import androidx.annotation.Nullable;
6 |
7 | import com.google.android.material.snackbar.Snackbar;
8 | import androidx.fragment.app.Fragment;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.Button;
13 | import android.widget.EditText;
14 |
15 | import com.google.firebase.auth.FirebaseAuth;
16 | import com.simcoder.uber.R;
17 |
18 | import org.jetbrains.annotations.NotNull;
19 |
20 |
21 | /**
22 | * Fragment Responsible for registering a new user
23 | */
24 | public class RegisterFragment extends Fragment implements View.OnClickListener {
25 |
26 | private EditText mEmail,
27 | mPassword;
28 |
29 | private View view;
30 |
31 | @Override
32 | public void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | }
35 |
36 | @Override
37 | public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container,
38 | Bundle savedInstanceState) {
39 | if (view == null)
40 | view = inflater.inflate(R.layout.fragment_registration, container, false);
41 | else
42 | container.removeView(view);
43 |
44 |
45 | return view;
46 | }
47 | @Override
48 | public void onViewCreated(@NotNull View view, @Nullable Bundle savedInstanceState) {
49 | super.onViewCreated(view, savedInstanceState);
50 |
51 | initializeObjects();
52 | }
53 |
54 |
55 |
56 | /**
57 | * Register the user, but before that check if every field is correct.
58 | * After that registers the user and creates an entry for it oin the database
59 | */
60 | private void register(){
61 | if(mEmail.getText().length()==0) {
62 | mEmail.setError("please fill this field");
63 | return;
64 | }
65 | if(mPassword.getText().length()==0) {
66 | mPassword.setError("please fill this field");
67 | return;
68 | }
69 | if(mPassword.getText().length()< 6) {
70 | mPassword.setError("password must have at least 6 characters");
71 | return;
72 | }
73 |
74 |
75 |
76 | final String email = mEmail.getText().toString();
77 | final String password = mPassword.getText().toString();
78 |
79 |
80 | FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password).addOnCompleteListener(getActivity(), task -> {
81 | if(!task.isSuccessful()){
82 | Snackbar.make(view.findViewById(R.id.layout), "sign up error", Snackbar.LENGTH_SHORT).show();
83 | }
84 | });
85 |
86 | }
87 |
88 |
89 | /**
90 | * Initializes the design Elements and calls clickListeners for them
91 | */
92 | private void initializeObjects(){
93 | mEmail = view.findViewById(R.id.email);
94 | mPassword = view.findViewById(R.id.password);
95 | Button mRegister = view.findViewById(R.id.register);
96 |
97 | mRegister.setOnClickListener(this);
98 | }
99 | @Override
100 | public void onClick(View view) {
101 | if (view.getId() == R.id.register) {
102 | register();
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Driver/DriverChooseTypeActivity.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Driver;
2 |
3 | import androidx.appcompat.app.ActionBar;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import androidx.appcompat.widget.Toolbar;
6 | import androidx.recyclerview.widget.LinearLayoutManager;
7 | import androidx.recyclerview.widget.RecyclerView;
8 |
9 | import android.app.Activity;
10 | import android.content.Intent;
11 | import android.os.Bundle;
12 | import android.widget.ImageView;
13 |
14 | import com.simcoder.uber.Adapters.TypeAdapter;
15 | import com.simcoder.uber.Objects.TypeObject;
16 | import com.simcoder.uber.R;
17 | import com.simcoder.uber.Utils.Utils;
18 |
19 | import java.util.ArrayList;
20 |
21 | /**
22 | * Activity responsible for letting the driver chose the service type
23 | * they offer.
24 | *
25 | * It displays a recyclerView with the possible service type options
26 | */
27 | public class DriverChooseTypeActivity extends AppCompatActivity {
28 |
29 | private TypeAdapter mAdapter;
30 |
31 | ArrayList typeArrayList = new ArrayList<>();
32 |
33 | ImageView mConfirm;
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | setContentView(R.layout.activity_driver_choose_type);
39 |
40 | setupToolbar();
41 |
42 | mConfirm = findViewById(R.id.confirm);
43 | mConfirm.setOnClickListener(view -> confirmEntry());
44 |
45 | initRecyclerView();
46 |
47 |
48 |
49 | String service = getIntent().getStringExtra("service");
50 | for(TypeObject mType : typeArrayList){
51 | if(mType.getId().equals(service)){
52 | mAdapter.setSelectedItem(mType);
53 | }
54 | }
55 |
56 | mAdapter.notifyDataSetChanged();
57 | }
58 |
59 | /**
60 | * Sets up toolbar with custom text and a listener
61 | * to go back to the previous activity
62 | */
63 | private void setupToolbar() {
64 | Toolbar myToolbar = findViewById(R.id.my_toolbar);
65 | setSupportActionBar(myToolbar);
66 | getSupportActionBar().setTitle(getString(R.string.type));
67 | myToolbar.setTitleTextColor(getResources().getColor(R.color.white));
68 | ActionBar ab = getSupportActionBar();
69 | assert ab != null;
70 | ab.setDisplayHomeAsUpEnabled(true);
71 | myToolbar.setNavigationOnClickListener(v -> finish());
72 | }
73 |
74 | private void confirmEntry() {
75 | Intent returnIntent = new Intent();
76 | returnIntent.putExtra("result", mAdapter.getSelectedItem().getId());
77 | setResult(Activity.RESULT_OK,returnIntent);
78 | finish();
79 | }
80 |
81 |
82 | /**
83 | * Initializes the recyclerview that shows the costumer the
84 | * available car types
85 | */
86 | private void initRecyclerView() {
87 | typeArrayList = Utils.getTypeList(DriverChooseTypeActivity.this);
88 |
89 | RecyclerView mRecyclerView = findViewById(R.id.recyclerView);
90 | mRecyclerView.setNestedScrollingEnabled(false);
91 | mRecyclerView.setHasFixedSize(true);
92 | RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(DriverChooseTypeActivity.this);
93 | mRecyclerView.setLayoutManager(mLayoutManager);
94 | mAdapter = new TypeAdapter(typeArrayList, DriverChooseTypeActivity.this, null);
95 | mRecyclerView.setAdapter(mAdapter);
96 | }
97 |
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/activity_customer_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
16 |
17 |
22 |
28 |
32 |
33 |
38 |
46 |
47 |
48 |
53 |
60 |
61 |
62 |
69 |
70 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/activity_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
18 |
29 |
30 |
31 |
49 |
50 |
63 |
64 |
76 |
77 |
78 |
79 |
87 |
88 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/ic_type_1.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Adapters/TypeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Adapters;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ImageView;
8 | import android.widget.LinearLayout;
9 | import android.widget.TextView;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.recyclerview.widget.RecyclerView;
13 |
14 | import com.simcoder.uber.Objects.TypeObject;
15 | import com.simcoder.uber.R;
16 |
17 | import org.jetbrains.annotations.NotNull;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 |
23 | /**
24 | * Adapter responsible for displaying type of cars in the CustomerActivity.class
25 | */
26 |
27 | public class TypeAdapter extends RecyclerView.Adapter {
28 |
29 | private Context context;
30 | private TypeObject selectedItem;
31 | private List itemArrayList;
32 | private ArrayList data;
33 |
34 | public TypeAdapter(List itemArrayList, Context context, ArrayList data) {
35 | this.itemArrayList = itemArrayList;
36 | selectedItem = itemArrayList.get(0);
37 | this.context = context;
38 | this.data = data;
39 | }
40 |
41 | @NotNull
42 | @Override
43 | public TypeAdapter.viewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
44 |
45 | View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_type, null, false);
46 | RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
47 | layoutView.setLayoutParams(lp);
48 | return new viewHolders(layoutView);
49 | }
50 |
51 | /**
52 | * Bind view to holder, setting the text to
53 | * the design elements
54 | * @param position - current position of the recyclerView
55 | */
56 | @Override
57 | public void onBindViewHolder(final @NonNull viewHolders holder, int position) {
58 | holder.mName.setText(itemArrayList.get(position).getName());
59 | holder.mPeople.setText(String.valueOf(itemArrayList.get(position).getPeople()));
60 | holder.mImage.setImageDrawable(itemArrayList.get(position).getImage());
61 |
62 | if(selectedItem.equals(itemArrayList.get(position))){
63 | holder.mLayout.setBackgroundColor(context.getResources().getColor(R.color.lightGrey));
64 | }else{
65 | holder.mLayout.setBackgroundColor(context.getResources().getColor(R.color.white));
66 | }
67 |
68 | holder.mLayout.setOnClickListener(v -> {
69 | selectedItem = itemArrayList.get(holder.getAdapterPosition());
70 | notifyDataSetChanged();
71 | });
72 |
73 | }
74 |
75 | public TypeObject getSelectedItem() {
76 | return selectedItem;
77 | }
78 |
79 | public void setSelectedItem(TypeObject selectedItem) {
80 | this.selectedItem = selectedItem;
81 | }
82 |
83 | @Override
84 | public int getItemCount() {
85 | return this.itemArrayList.size();
86 | }
87 |
88 |
89 | public void setData(ArrayList data) {
90 | this.data = data;
91 | }
92 |
93 |
94 | /**
95 | * Responsible for handling the data of each view
96 | */
97 | static class viewHolders extends RecyclerView.ViewHolder {
98 |
99 | TextView mName;
100 | TextView mPeople;
101 | ImageView mImage;
102 | LinearLayout mLayout;
103 | viewHolders(View itemView) {
104 | super(itemView);
105 | mImage = itemView.findViewById(R.id.image);
106 | mPeople = itemView.findViewById(R.id.people);
107 | mName = itemView.findViewById(R.id.name);
108 | mLayout = itemView.findViewById(R.id.layout);
109 | }
110 | }
111 | }
--------------------------------------------------------------------------------
/Firebase_Functions/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Payouts - Connected
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
93 |
94 |
95 |
96 |
101 |
102 |
103 |
133 |
134 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Login/LoginFragment.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Login;
2 |
3 | import android.os.Bundle;
4 |
5 | import androidx.annotation.Nullable;
6 |
7 | import com.google.android.material.snackbar.Snackbar;
8 |
9 | import androidx.fragment.app.Fragment;
10 |
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.Button;
15 | import android.widget.EditText;
16 | import android.widget.TextView;
17 |
18 | import com.google.firebase.auth.FirebaseAuth;
19 | import com.simcoder.uber.R;
20 |
21 | import org.jetbrains.annotations.NotNull;
22 |
23 | /**
24 | * Fragment Responsible for Logging in an existing user
25 | */
26 | public class LoginFragment extends Fragment implements View.OnClickListener {
27 |
28 | private EditText mEmail, mPassword;
29 |
30 |
31 | private View view;
32 |
33 | @Override
34 | public void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | }
37 |
38 | @Override
39 | public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container,
40 | Bundle savedInstanceState) {
41 | if (view == null)
42 | view = inflater.inflate(R.layout.fragment_login, container, false);
43 | else
44 | container.removeView(view);
45 |
46 |
47 | return view;
48 | }
49 |
50 | @Override
51 | public void onViewCreated(@NotNull View view, @Nullable Bundle savedInstanceState) {
52 | super.onViewCreated(view, savedInstanceState);
53 |
54 | initializeObjects();
55 | }
56 |
57 | /**
58 | * Sends an email to the email that's on the email input for the user to reset the password
59 | */
60 | private void forgotPassword() {
61 | if (mEmail.getText().toString().trim().length() > 0)
62 | FirebaseAuth.getInstance().sendPasswordResetEmail(mEmail.getText().toString())
63 | .addOnCompleteListener(task -> {
64 | if (task.isSuccessful()) {
65 | Snackbar.make(view.findViewById(R.id.layout), "Email Sent", Snackbar.LENGTH_LONG).show();
66 | } else
67 | Snackbar.make(view.findViewById(R.id.layout), "Something went wrong", Snackbar.LENGTH_LONG).show();
68 | });
69 | }
70 |
71 | /**
72 | * Logs in the user
73 | */
74 | private void login() {
75 | final String email = mEmail.getText().toString();
76 | final String password = mPassword.getText().toString();
77 |
78 | if(mEmail.getText().length()==0) {
79 | mEmail.setError("please fill this field");
80 | return;
81 | }
82 | if(mPassword.getText().length()==0) {
83 | mPassword.setError("please fill this field");
84 | return;
85 | }
86 |
87 | FirebaseAuth.getInstance().signInWithEmailAndPassword(email, password).addOnCompleteListener(getActivity(), task -> {
88 | if (!task.isSuccessful()) {
89 | Snackbar.make(view.findViewById(R.id.layout), "sign in error", Snackbar.LENGTH_SHORT).show();
90 | }
91 | });
92 | }
93 |
94 |
95 | @Override
96 | public void onClick(View view) {
97 | switch (view.getId()) {
98 | case R.id.forgotButton:
99 | forgotPassword();
100 | break;
101 | case R.id.login:
102 | login();
103 | break;
104 | }
105 | }
106 |
107 |
108 | /**
109 | * Initializes the design Elements and calls clickListeners for them
110 | */
111 | private void initializeObjects() {
112 | mEmail = view.findViewById(R.id.email);
113 | mPassword = view.findViewById(R.id.password);
114 | TextView mForgotButton = view.findViewById(R.id.forgotButton);
115 | Button mLogin = view.findViewById(R.id.login);
116 |
117 |
118 | mForgotButton.setOnClickListener(this);
119 | mLogin.setOnClickListener(this);
120 |
121 | }
122 | }
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Payment/PaymentActivity.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Payment;
2 |
3 | import androidx.appcompat.app.ActionBar;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import androidx.appcompat.widget.Toolbar;
6 | import androidx.recyclerview.widget.LinearLayoutManager;
7 | import androidx.recyclerview.widget.RecyclerView;
8 |
9 | import android.content.Intent;
10 | import android.os.Bundle;
11 | import android.view.View;
12 | import android.widget.ImageView;
13 |
14 | import com.google.android.material.bottomsheet.BottomSheetDialog;
15 | import com.simcoder.uber.Adapters.CardAdapter;
16 | import com.simcoder.uber.Objects.CardObject;
17 | import com.simcoder.uber.R;
18 |
19 | import java.util.ArrayList;
20 |
21 | public class PaymentActivity extends AppCompatActivity {
22 |
23 | ArrayList cardArrayList = new ArrayList<>();
24 | ImageView mAddCard;
25 |
26 | PaymentUtils.CardListCallback cb;
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_payment);
32 |
33 | cb = cardArrayList -> {
34 | this.cardArrayList = cardArrayList;
35 | runOnUiThread(this::initializeRecyclerView);
36 | };
37 |
38 | setupToolbar();
39 |
40 | mAddCard = findViewById(R.id.add_card_image);
41 | mAddCard.setOnClickListener(v -> {
42 | Intent intent = new Intent(PaymentActivity.this, AddPaymentActivity.class);
43 | startActivity(intent);
44 | });
45 | }
46 |
47 | /**
48 | * Initialize the bottom sheet dialog which will handle what happens
49 | * when the user clicks a card.
50 | * When it happens it will be given the option to either remove the card,
51 | * set as default and cancel all together.
52 | * @param mCard - object of the card that was clicked
53 | */
54 | public void initializeBottomSheetDialog(CardObject mCard){
55 |
56 | View dialogView = getLayoutInflater().inflate(R.layout.dialog_card, null);
57 | BottomSheetDialog dialog = new BottomSheetDialog(this);
58 | dialog.setContentView(dialogView);
59 | dialog.findViewById(R.id.cancel_button).setOnClickListener(v -> dialog.dismiss());
60 | dialog.findViewById(R.id.default_button).setOnClickListener(v -> {
61 | new PaymentUtils().setDefaultCard(mCard.getId(), cb, getApplicationContext());
62 | dialog.dismiss();
63 | });
64 | dialog.findViewById(R.id.delete_button).setOnClickListener(v -> {
65 | new PaymentUtils().removeCard(mCard.getId(), cb, getApplicationContext());
66 | dialog.dismiss();
67 | });
68 | dialog.show();
69 |
70 | }
71 | /**
72 | * Sets up toolbar with custom text and a listener
73 | * to go back to the previous activity
74 | */
75 | private void setupToolbar() {
76 | Toolbar myToolbar = findViewById(R.id.my_toolbar);
77 | setSupportActionBar(myToolbar);
78 | getSupportActionBar().setTitle(getString(R.string.payment));
79 | myToolbar.setTitleTextColor(getResources().getColor(R.color.white));
80 | ActionBar ab = getSupportActionBar();
81 | assert ab != null;
82 | ab.setDisplayHomeAsUpEnabled(true);
83 | myToolbar.setNavigationOnClickListener(v -> finish());
84 | }
85 |
86 | /**
87 | * init recyclerview with all the relevant calls
88 | */
89 | public void initializeRecyclerView(){
90 | RecyclerView mRecyclerView = findViewById(R.id.recyclerView);
91 | mRecyclerView.setNestedScrollingEnabled(false);
92 | mRecyclerView.setHasFixedSize(true);
93 | RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
94 | mRecyclerView.setLayoutManager(mLayoutManager);
95 | RecyclerView.Adapter mAdapter = new CardAdapter(cardArrayList, PaymentActivity.this);
96 | mRecyclerView.setAdapter(mAdapter);
97 | }
98 |
99 | @Override
100 | protected void onResume() {
101 | super.onResume();
102 |
103 | new PaymentUtils().fetchCardsList(cb, getApplicationContext());
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
30 |
31 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
52 |
53 |
54 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
66 |
69 |
72 |
75 |
78 |
81 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/item_history.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
25 |
26 |
33 |
34 |
40 |
41 |
49 |
50 |
54 |
55 |
63 |
64 |
65 |
74 |
75 |
83 |
84 |
91 |
92 |
93 |
94 |
95 |
96 |
100 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Adapters/CardAdapter.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Adapters;
2 |
3 | import android.app.Activity;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ImageView;
8 | import android.widget.LinearLayout;
9 | import android.widget.TextView;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.recyclerview.widget.RecyclerView;
13 |
14 | import com.simcoder.uber.Objects.CardObject;
15 | import com.simcoder.uber.Payment.PaymentActivity;
16 | import com.simcoder.uber.R;
17 |
18 | import java.util.List;
19 |
20 |
21 | /**
22 | * Adapter responsible for displaying type of cars in the CustomerActivity.class
23 | */
24 |
25 | public class CardAdapter extends RecyclerView.Adapter {
26 |
27 | private Activity activity;
28 | private List itemArrayList;
29 |
30 | public CardAdapter(List itemArrayList, Activity activity) {
31 | this.itemArrayList = itemArrayList;
32 | this.activity = activity;
33 | }
34 |
35 | @Override
36 | public CardAdapter.viewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
37 |
38 | View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card, null, false);
39 | RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
40 | layoutView.setLayoutParams(lp);
41 | return new viewHolders(layoutView);
42 | }
43 |
44 | /**
45 | * Bind view to holder, setting the text to
46 | * the design elements
47 | *
48 | * @param position - current position of the recyclerView
49 | */
50 | @Override
51 | public void onBindViewHolder(final @NonNull viewHolders holder, int position) {
52 | holder.mName.setText(itemArrayList.get(position).getName());
53 | holder.mNumber.setText("**** **** **** " + itemArrayList.get(position).getLastDigits());
54 | holder.mDate.setText(itemArrayList.get(position).getExpMonth() + "/" + itemArrayList.get(position).getExpYear());
55 |
56 | switch (itemArrayList.get(position).getBrand()) {
57 | case "visa":
58 | holder.mCard.setImageDrawable(activity.getDrawable(R.drawable.ic_visa));
59 | break;
60 | case "American Express":
61 | holder.mCard.setImageDrawable(activity.getDrawable(R.drawable.ic_amex));
62 | break;
63 | case "mastercard":
64 | holder.mCard.setImageDrawable(activity.getDrawable(R.drawable.ic_mastercard));
65 | break;
66 | case "discover":
67 | holder.mCard.setImageDrawable(activity.getDrawable(R.drawable.ic_discover));
68 | break;
69 | case "jcb":
70 | holder.mCard.setImageDrawable(activity.getDrawable(R.drawable.cio_ic_jcb));
71 | break;
72 | default:
73 | holder.mCard.setImageDrawable(activity.getDrawable(R.drawable.ic_credit_card_black_24dp));
74 | break;
75 | }
76 |
77 | if(itemArrayList.get(position).getDefaultCard()){
78 | holder.mDefault.setVisibility(View.VISIBLE);
79 | }else{
80 | holder.mDefault.setVisibility(View.INVISIBLE);
81 | }
82 |
83 | holder.mLayout.setOnClickListener(v -> {
84 | ((PaymentActivity)activity).initializeBottomSheetDialog(itemArrayList.get(position));
85 | });
86 | }
87 |
88 | @Override
89 | public int getItemCount() {
90 | return this.itemArrayList.size();
91 | }
92 |
93 |
94 | /**
95 | * Responsible for handling the data of each view
96 | */
97 | static class viewHolders extends RecyclerView.ViewHolder {
98 |
99 | TextView mName,
100 | mNumber, mDate;
101 | ImageView mCard, mDefault;
102 | LinearLayout mLayout;
103 |
104 | viewHolders(View itemView) {
105 | super(itemView);
106 | mCard = itemView.findViewById(R.id.card_image);
107 | mNumber = itemView.findViewById(R.id.number_text);
108 | mName = itemView.findViewById(R.id.name_text);
109 | mDate = itemView.findViewById(R.id.date_text);
110 | mLayout = itemView.findViewById(R.id.card_layout);
111 | mDefault = itemView.findViewById(R.id.default_image);
112 | }
113 | }
114 | }
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/item__card_request.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
22 |
23 |
24 |
30 |
31 |
37 |
48 |
55 |
56 |
66 |
75 |
76 |
80 |
81 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | [](https://opensource.org/licenses/MIT)
3 | [](https://twitter.com/simcoder_here)
4 | [](https://www.instagram.com/simcoder_here/)
5 | [](https://www.youtube.com/channel/UCQ5xY26cw5Noh6poIE-VBog)
6 | [](https://www.buymeacoffee.com/simcoder)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Uber Clone
16 |
17 |
18 | A Uber clone app made with android native (java) and firebase
19 |
20 | Explore the docs »
21 |
22 |
23 | Report Bug
24 | ·
25 | Request Feature
26 |
27 |
28 |
29 |
30 |
31 | Table of Contents
32 |
33 | -
34 | About The Project
35 |
38 |
39 | -
40 | Getting Started
41 |
45 |
46 | - Roadmap
47 | - Contributing
48 | - Support
49 | - License
50 | - Contact
51 |
52 |
53 |
54 |
55 |
56 | ## ℹ️ About The Project
57 |
58 | 
59 |
60 | This repo contains the project made in my youtube chanel called simcoder. This project is a clone of the Uber android app.
61 |
62 | It is made using android native with java and some firebase services (authentication, real time database and storage).
63 |
64 | In the [master](https://github.com/SimCoderYoutube/UberClone/tree/master) branch you have the redesign project which I was previously selling in my website, however you still have access to the youtube series repo in the [youtube_series](https://github.com/SimCoderYoutube/UberClone/tree/youtube_series)
65 |
66 | You can follow the youtube series in the following [link](https://www.youtube.com/watch?v=7HbQx0lwRww&list=PLxabZQCAe5fgXx8cn2iKOtt0VFJrf5bOd&ab_channel=SimCoder)
67 |
68 | ## 🆕 Getting Started
69 |
70 | - ### **Prerequisites**
71 |
72 | - [Android Studio](https://developer.android.com/)
73 | - [Firebase](https://firebase.google.com/)
74 |
75 |
76 |
77 | - ### **Installation**
78 |
79 | In order to deploy the project you'll need to follow the [wiki page](https://github.com/SimCoderYoutube/UberClone/wiki/Setup-your-project) dedicated to this effect.
80 |
81 | ## 🚧 Roadmap
82 |
83 | See the [open issues](https://github.com/SimCoderYoutube/UberClone/issues) for a list of proposed features (and known issues).
84 |
85 |
86 |
87 | ## ➕ Contributing
88 |
89 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. Please check the [Wiki](https://github.com/SimCoderYoutube/UberClone/wiki/How-to-Contribute)
90 |
91 | ## 🌟 Show your support
92 |
93 | Give a ⭐️ if this project helped you!
94 |
95 | And don't forget to subscribe to the [youtube chanel](https://www.youtube.com/c/SimpleCoder?sub_confirmation=1)
96 |
97 | ## 📝 License
98 |
99 | Copyright © 2021 [SimCoder](https://github.com/simcoderYoutube).
100 |
101 | This project is [MIT](https://github.com/SimCoderYoutube/UberClone/blob/master/LICENSE) licensed. Some of the dependencies are licensed differently.
102 |
103 |
104 |
105 | ## 👤 Contact
106 |
107 | **SimCoder**
108 |
109 | - Website: www.simcoder.com
110 | - Twitter: [@simcoder_here](https://twitter.com/simcoder_here)
111 | - Github: [@simcoderYoutube](https://github.com/simcoderYoutube)
112 | - Youtube: [SimCoder](https://www.youtube.com/channel/UCQ5xY26cw5Noh6poIE-VBog)
113 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.onesignal.androidsdk.onesignal-gradle-plugin'
3 | }
4 | apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin'
5 |
6 | apply plugin: 'com.android.application'
7 |
8 | android {
9 | compileSdkVersion 30
10 | buildToolsVersion '30.0.3'
11 | defaultConfig {
12 | applicationId "com.simcoder.uber"
13 | minSdkVersion 21
14 | //noinspection OldTargetApi
15 | targetSdkVersion 29
16 | versionCode 1
17 | versionName "2.0"
18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19 | multiDexEnabled true
20 | useLibrary 'org.apache.http.legacy'
21 | manifestPlaceholders = [onesignal_app_id : 'onesignal_app_id',
22 | onesignal_google_project_number: 'REMOTE']
23 | }
24 | buildTypes {
25 | release {
26 |
27 | multiDexKeepFile file('multidex-config.txt')
28 | minifyEnabled true
29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
30 | }
31 | }
32 |
33 | compileOptions {
34 | sourceCompatibility '1.8'
35 | targetCompatibility '1.8'
36 | }
37 | buildFeatures {
38 | viewBinding true
39 | }
40 | }
41 | dependencies {
42 | implementation fileTree(dir: 'libs', include: ['*.jar'])
43 | androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
44 | exclude group: 'com.android.support', module: 'support-annotations'
45 | })
46 |
47 | //noinspection GradleCompatible
48 | implementation 'androidx.appcompat:appcompat:1.3.0'
49 | implementation 'androidx.constraintlayout:constraintlayout:2.1.0-beta02'
50 | implementation 'com.google.firebase:firebase-database:20.0.0'
51 | implementation 'com.google.firebase:firebase-auth:21.0.1'
52 | implementation 'com.google.firebase:firebase-storage:20.0.0'
53 | implementation 'com.firebase:geofire-android:3.0.0'
54 | implementation 'com.google.android.gms:play-services-maps:17.0.1'
55 | implementation 'com.google.android.gms:play-services-places:17.0.0'
56 | implementation 'com.google.android.gms:play-services-location:18.0.0'
57 | implementation 'com.google.android.gms:play-services-gcm:17.0.0'
58 | implementation 'com.google.android.gms:play-services-auth:19.0.0'
59 | implementation 'com.facebook.android:facebook-login:8.1.0'
60 |
61 | implementation 'androidx.recyclerview:recyclerview:1.2.0'
62 | implementation 'androidx.cardview:cardview:1.0.0'
63 | implementation 'com.stripe:stripe-android:16.1.1'
64 |
65 | implementation 'com.github.bumptech.glide:glide:4.11.0'
66 | implementation 'com.google.android.material:material:1.3.0'
67 | implementation 'androidx.cardview:cardview:1.0.0'
68 | implementation 'com.akexorcist:googledirectionlibrary:1.1.1'
69 |
70 | implementation 'com.onesignal:OneSignal:3.15.4'
71 | implementation 'com.google.android.libraries.places:places:2.4.0'
72 |
73 | implementation "com.github.addisonelliott:SegmentedButton:3.1.5"
74 |
75 | implementation 'com.paypal.sdk:paypal-android-sdk:2.16.0'
76 | implementation 'com.google.android.libraries.places:places:2.4.0'
77 | implementation 'com.github.rtchagas:pingplacepicker:1.1.2'
78 |
79 | implementation 'com.github.ybq:Android-SpinKit:1.4.0'
80 |
81 |
82 | implementation 'androidx.multidex:multidex:2.0.1'
83 |
84 |
85 | /* Needed for RxAndroid */
86 | implementation 'io.reactivex:rxandroid:1.2.1'
87 | implementation 'io.reactivex:rxjava:1.3.8'
88 | implementation 'io.reactivex.rxjava2:rxjava:2.2.10'
89 |
90 |
91 | /* Needed for Rx Bindings on views */
92 | implementation 'com.jakewharton.rxbinding:rxbinding:1.0.1'
93 |
94 |
95 | annotationProcessor 'com.jakewharton:butterknife:10.2.3'
96 |
97 | implementation 'com.squareup.retrofit2:retrofit:2.9.0' //Proguard
98 | implementation 'com.squareup.retrofit2:converter-gson:2.9.0' //Proguard
99 | implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' //Proguard
100 |
101 | /* Used for server calls */
102 | implementation 'com.squareup.okio:okio:2.9.0'
103 | implementation 'com.squareup.retrofit2:retrofit:2.9.0'
104 |
105 | /* Used to make Retrofit easier and GSON & Rx-compatible*/
106 | implementation 'com.google.code.gson:gson:2.8.6'
107 | implementation 'com.squareup.retrofit2:adapter-rxjava:2.9.0'
108 | implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
109 |
110 | /* Used to debug your Retrofit connections */
111 | implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
112 |
113 | implementation "com.yuyakaido.android:card-stack-view:2.3.4"
114 | implementation 'com.lorentzos.swipecards:library:1.0.9'
115 | implementation 'com.mikhaellopez:circularprogressbar:3.0.3'
116 | implementation 'com.github.tintinscorpion:Dual-color-Polyline-Animation:1.0'
117 |
118 | implementation 'com.shreyaspatil:MaterialDialog:2.1'
119 |
120 | // Material Design Library
121 | implementation 'com.google.android.material:material:1.3.0'
122 |
123 | implementation 'com.ncorti:slidetoact:0.7.0'
124 |
125 | testImplementation 'junit:junit:4.13.2'
126 | }
127 |
128 | apply plugin: 'com.google.gms.google-services'
129 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/History/HistoryActivity.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.History;
2 |
3 | import android.annotation.SuppressLint;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import androidx.appcompat.app.ActionBar;
8 | import androidx.appcompat.app.AppCompatActivity;
9 | import android.os.Bundle;
10 |
11 | import androidx.appcompat.widget.Toolbar;
12 | import androidx.recyclerview.widget.LinearLayoutManager;
13 | import androidx.recyclerview.widget.RecyclerView;
14 |
15 | import android.view.View;
16 | import android.widget.LinearLayout;
17 |
18 | import com.google.firebase.auth.FirebaseAuth;
19 | import com.google.firebase.database.ChildEventListener;
20 | import com.google.firebase.database.DataSnapshot;
21 | import com.google.firebase.database.DatabaseError;
22 | import com.google.firebase.database.FirebaseDatabase;
23 | import com.google.firebase.database.Query;
24 | import com.simcoder.uber.Objects.RideObject;
25 | import com.simcoder.uber.Adapters.HistoryAdapter;
26 | import com.simcoder.uber.R;
27 |
28 | import org.jetbrains.annotations.NotNull;
29 |
30 | import java.util.ArrayList;
31 |
32 |
33 | /**
34 | * This activity displays a list of all the previous drives made
35 | * by the user.
36 | *
37 | * If the current user is a driver then it also displays a space with the
38 | * current money available for payout and a space for the user to place
39 | * the paypal email to which it is sent
40 | */
41 | public class HistoryActivity extends AppCompatActivity {
42 |
43 | private RecyclerView.Adapter mHistoryAdapter;
44 |
45 | LinearLayout mEmpty;
46 |
47 | String idRef = "";
48 | @Override
49 | protected void onCreate(Bundle savedInstanceState) {
50 | super.onCreate(savedInstanceState);
51 | setContentView(R.layout.activity_history);
52 |
53 | RecyclerView mHistoryRecyclerView = findViewById(R.id.historyRecyclerView);
54 | mHistoryRecyclerView.setNestedScrollingEnabled(false);
55 | mHistoryRecyclerView.setHasFixedSize(true);
56 | RecyclerView.LayoutManager mHistoryLayoutManager = new LinearLayoutManager(HistoryActivity.this);
57 | mHistoryRecyclerView.setLayoutManager(mHistoryLayoutManager);
58 | mHistoryAdapter = new HistoryAdapter(resultsHistory, HistoryActivity.this);
59 | mHistoryRecyclerView.setAdapter(mHistoryAdapter);
60 |
61 | mEmpty = findViewById(R.id.empty_layout);
62 |
63 | String customerOrDriver = getIntent().getExtras().getString("customerOrDriver");
64 | String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
65 |
66 | if(customerOrDriver.equals("Drivers")){
67 | idRef = "driverId";
68 | }else{
69 | idRef = "customerId";
70 | }
71 |
72 |
73 | getUserHistoryIds();
74 | setupToolbar();
75 | }
76 |
77 | /**
78 | * Sets up toolbar with custom text and a listener
79 | * to go back to the previous activity
80 | */
81 | private void setupToolbar() {
82 | Toolbar myToolbar = findViewById(R.id.my_toolbar);
83 | setSupportActionBar(myToolbar);
84 | getSupportActionBar().setTitle(getString(R.string.your_trips));
85 | myToolbar.setTitleTextColor(getResources().getColor(R.color.white));
86 | ActionBar ab = getSupportActionBar();
87 | assert ab != null;
88 | ab.setDisplayHomeAsUpEnabled(true);
89 | myToolbar.setNavigationOnClickListener(v -> finish());
90 | }
91 |
92 |
93 | /**
94 | * Fetch all of the rides that are completed and populate the
95 | * design elements
96 | */
97 | private void getUserHistoryIds() {
98 |
99 | String driverId = FirebaseAuth.getInstance().getCurrentUser().getUid();
100 | Query query = FirebaseDatabase.getInstance().getReference().child("ride_info").orderByChild(idRef).equalTo(driverId);
101 |
102 | query.addChildEventListener(new ChildEventListener() {
103 |
104 | @SuppressLint("SetTextI18n")
105 | @Override
106 | public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
107 | if(!dataSnapshot.exists()){return;}
108 |
109 | RideObject mRide = new RideObject();
110 | mRide.parseData(dataSnapshot);
111 |
112 | if(mRide.getCancelled()){
113 | return;
114 | }
115 | mEmpty.setVisibility(View.GONE);
116 | resultsHistory.add(0, mRide);
117 | mHistoryAdapter.notifyDataSetChanged();
118 | }
119 |
120 | @Override
121 | public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
122 |
123 | }
124 |
125 | @Override
126 | public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
127 |
128 | }
129 |
130 | @Override
131 | public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
132 |
133 | }
134 |
135 | @Override
136 | public void onCancelled(@NotNull DatabaseError databaseError) {
137 | }
138 | });
139 |
140 |
141 | }
142 | private ArrayList resultsHistory = new ArrayList<>();
143 |
144 |
145 | }
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Login/LauncherActivity.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Login;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 |
6 | import androidx.appcompat.app.AppCompatActivity;
7 |
8 | import com.google.firebase.auth.FirebaseAuth;
9 | import com.google.firebase.database.DataSnapshot;
10 | import com.google.firebase.database.DatabaseError;
11 | import com.google.firebase.database.DatabaseReference;
12 | import com.google.firebase.database.FirebaseDatabase;
13 | import com.google.firebase.database.ValueEventListener;
14 | import com.onesignal.OneSignal;
15 | import com.simcoder.uber.Customer.CustomerMapActivity;
16 | import com.simcoder.uber.Driver.DriverMapActivity;
17 | import com.simcoder.uber.R;
18 | import com.stripe.android.PaymentConfiguration;
19 |
20 | import org.jetbrains.annotations.NotNull;
21 |
22 | /**
23 | * First activity of the app.
24 | *
25 | * Responsible for checking if the user is logged in or not and call
26 | * the AuthenticationActivity or MainActivity depending on that.
27 | */
28 | public class LauncherActivity extends AppCompatActivity {
29 |
30 | int triedTypes = 0;
31 |
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 |
37 | FirebaseAuth mAuth = FirebaseAuth.getInstance();
38 | if (mAuth.getCurrentUser() != null) {
39 | checkUserAccType();
40 | } else {
41 | Intent intent = new Intent(LauncherActivity.this, AuthenticationActivity.class);
42 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
43 | startActivity(intent);
44 | finish();
45 | }
46 | }
47 |
48 |
49 | /**
50 | * Check user account type, either customer or driver.
51 | * If it doesn't have a type then start the DetailsActivity for the
52 | * user to be able to pick one.
53 | */
54 | private void checkUserAccType() {
55 | String userID;
56 |
57 | userID = FirebaseAuth.getInstance().getCurrentUser().getUid();
58 | DatabaseReference mCustomerDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child("Customers").child(userID);
59 | mCustomerDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
60 | @Override
61 | public void onDataChange(@NotNull DataSnapshot dataSnapshot) {
62 | if (dataSnapshot.exists() && dataSnapshot.getChildrenCount() > 0) {
63 | startApis("Customers");
64 | Intent intent = new Intent(getApplication(), CustomerMapActivity.class);
65 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
66 | startActivity(intent);
67 | finish();
68 | } else {
69 | checkNoType();
70 | }
71 | }
72 |
73 | @Override
74 | public void onCancelled(@NotNull DatabaseError databaseError) {
75 | }
76 | });
77 | DatabaseReference mDriverDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child("Drivers").child(userID);
78 | mDriverDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
79 | @Override
80 | public void onDataChange(@NotNull DataSnapshot dataSnapshot) {
81 | if (dataSnapshot.exists() && dataSnapshot.getChildrenCount() > 0) {
82 | startApis("Drivers");
83 | Intent intent = new Intent(getApplication(), DriverMapActivity.class);
84 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
85 | startActivity(intent);
86 | finish();
87 | } else {
88 | checkNoType();
89 | }
90 | }
91 |
92 | @Override
93 | public void onCancelled(@NotNull DatabaseError databaseError) {
94 | }
95 | });
96 | }
97 |
98 | /**
99 | * checks if both types have not been fetched meaning the DetailsActivity must be called
100 | */
101 | void checkNoType() {
102 | triedTypes++;
103 | if (triedTypes == 2) {
104 | Intent intent = new Intent(getApplication(), DetailsActivity.class);
105 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
106 | startActivity(intent);
107 | finish();
108 | }
109 | }
110 |
111 | /**
112 | * starts up onesignal and stripe apis
113 | * @param type - type of the user (customer, driver)
114 | */
115 | void startApis(String type) {
116 | OneSignal.startInit(this).init();
117 | OneSignal.sendTag("User_ID", FirebaseAuth.getInstance().getCurrentUser().getUid());
118 | OneSignal.setEmail(FirebaseAuth.getInstance().getCurrentUser().getEmail());
119 | //OneSignal.setInFocusDisplaying(OneSignal.OSInFocusDisplayOption.Notification);
120 | OneSignal.idsAvailable((userId, registrationId) -> FirebaseDatabase.getInstance().getReference().child("Users").child(type).child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("notificationKey").setValue(userId));
121 | PaymentConfiguration.init(
122 | getApplicationContext(),
123 | getResources().getString(R.string.publishablekey)
124 | );
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/item_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
21 |
22 |
27 |
28 |
33 |
34 |
38 |
42 |
43 |
48 |
49 |
50 |
60 |
61 |
62 |
67 |
68 |
74 |
75 |
81 |
82 |
89 |
90 |
98 |
99 |
100 |
108 |
109 |
110 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/simcoder/uber/Objects/DriverObject.java:
--------------------------------------------------------------------------------
1 | package com.simcoder.uber.Objects;
2 |
3 | import com.google.firebase.database.DataSnapshot;
4 |
5 | import java.text.DecimalFormat;
6 |
7 | public class DriverObject {
8 |
9 |
10 | private String id = "",
11 | name = "",
12 | phone = "",
13 | car = "",
14 | profileImage = "default",
15 | service,
16 | notificationKey = "",
17 | license = "";
18 |
19 | private Boolean connect = false;
20 |
21 | private float ratingsAvg = 0, payoutAmount = 0;
22 |
23 | private LocationObject mLocation;
24 |
25 | private Boolean active = true;
26 |
27 | public DriverObject(String id) {
28 | this.id = id;
29 | }
30 |
31 | /**
32 | * DriverObject constructor
33 | * Creates an empty object
34 | */
35 | public DriverObject() {}
36 |
37 |
38 | /**
39 | * Parse datasnapshot into this object
40 | *
41 | * @param dataSnapshot - customer info fetched from the database
42 | */
43 | public void parseData(DataSnapshot dataSnapshot) {
44 |
45 | id = dataSnapshot.getKey();
46 |
47 | if (dataSnapshot.child("name").getValue() != null) {
48 | name = dataSnapshot.child("name").getValue().toString();
49 | }
50 | if (dataSnapshot.child("phone").getValue() != null) {
51 | phone = dataSnapshot.child("phone").getValue().toString();
52 | }
53 | if (dataSnapshot.child("car").getValue() != null) {
54 | car = dataSnapshot.child("car").getValue().toString();
55 | }
56 | if (dataSnapshot.child("license").getValue() != null) {
57 | license = dataSnapshot.child("license").getValue().toString();
58 | }
59 | if (dataSnapshot.child("profileImageUrl").getValue() != null) {
60 | profileImage = dataSnapshot.child("profileImageUrl").getValue().toString();
61 | }
62 | if (dataSnapshot.child("activated").getValue() != null) {
63 | active = Boolean.parseBoolean(dataSnapshot.child("activated").getValue().toString());
64 | }
65 | if (dataSnapshot.child("connect_set").getValue() != null) {
66 | connect = Boolean.parseBoolean(dataSnapshot.child("connect_set").getValue().toString());
67 | }
68 | if (dataSnapshot.child("payout_amount").getValue() != null) {
69 | payoutAmount = Float.parseFloat(dataSnapshot.child("payout_amount").getValue().toString());
70 | }
71 | if (dataSnapshot.child("service").getValue() != null) {
72 | service = dataSnapshot.child("service").getValue().toString();
73 | }
74 |
75 | if (dataSnapshot.child("notificationKey").getValue() != null) {
76 | notificationKey = dataSnapshot.child("notificationKey").getValue().toString();
77 | }
78 | int ratingSum = 0;
79 | float ratingsTotal = 0;
80 | for (DataSnapshot child : dataSnapshot.child("rating").getChildren()) {
81 | ratingSum = ratingSum + Integer.valueOf(child.getValue().toString());
82 | ratingsTotal++;
83 | }
84 | if (ratingsTotal != 0) {
85 | ratingsAvg = ratingSum / ratingsTotal;
86 | }
87 | }
88 |
89 |
90 | public String getService() {
91 | return service;
92 | }
93 |
94 | public String getId() {
95 | return id;
96 | }
97 |
98 | public String getName() {
99 | return name;
100 | }
101 |
102 | public void setName(String name) {
103 | this.name = name;
104 | }
105 |
106 | public String getPhone() {
107 | return phone;
108 | }
109 |
110 | public void setPhone(String phone) {
111 | this.phone = phone;
112 | }
113 |
114 | public String getCar() {
115 | return car;
116 | }
117 |
118 | public String getLicense() {
119 | return license;
120 | }
121 |
122 |
123 |
124 | public String getServiceDash() {
125 | if(service.isEmpty()){
126 | return "--";
127 | }
128 | return service;
129 | }
130 | public String getNameDash() {
131 | if(name.isEmpty()){
132 | return "--";
133 | }
134 | return name;
135 | }
136 | public String getPhoneDash() {
137 | if(phone.isEmpty()){
138 | return "--";
139 | }
140 | return phone;
141 | }
142 | public String getCarDash() {
143 | if(car.isEmpty()){
144 | return "--";
145 | }
146 | return car;
147 | }
148 | public String getLicenseDash() {
149 | if(license.isEmpty()){
150 | return "--";
151 | }
152 | return license;
153 | }
154 |
155 |
156 |
157 | public String getDriverRatingString(){
158 | DecimalFormat df = new DecimalFormat("#.#");
159 | return df.format(ratingsAvg);
160 | }
161 |
162 | public void setCar(String car) {
163 | this.car = car;
164 | }
165 |
166 | public String getProfileImage() {
167 | return profileImage;
168 | }
169 |
170 | public void setProfileImage(String profileImage) {
171 | this.profileImage = profileImage;
172 | }
173 |
174 | public float getRatingsAvg() {
175 | return ratingsAvg;
176 | }
177 |
178 | public void setRatingsAvg(float ratingsAvg) {
179 | this.ratingsAvg = ratingsAvg;
180 | }
181 |
182 | public LocationObject getLocation() {
183 | return mLocation;
184 | }
185 |
186 | public void setLocation(LocationObject mLocation) {
187 | this.mLocation = mLocation;
188 | }
189 |
190 | public void setActive(Boolean active) {
191 | this.active = active;
192 | }
193 |
194 | public void setService(String service) {
195 | this.service = service;
196 | }
197 |
198 | public Boolean getActive() {
199 | return active;
200 | }
201 |
202 | public String getNotificationKey() {
203 | return notificationKey;
204 | }
205 |
206 | public float getPayoutAmount() {
207 | return payoutAmount;
208 | }
209 |
210 | public Boolean getConnect() {
211 | return connect;
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/android/app/src/main/res/layout/activity_driver_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
21 |
27 |
33 |
34 |
38 |
39 |
44 |
52 |
53 |
54 |
59 |
66 |
67 |
68 |
73 |
79 |
80 |
81 |
82 |
87 |
93 |
94 |
95 |
100 |
109 |
110 |
111 |
112 |
119 |
120 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------