diff --git a/app/build.gradle b/app/build.gradle
index 17e1498..36b1f69 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
+apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 28
@@ -6,7 +7,7 @@ android {
defaultConfig {
applicationId "com.example.mad_cw"
minSdkVersion 28
- targetSdkVersion 29
+ targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -23,6 +24,24 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+
+ // Firebase for Google Analytics:
+ implementation 'com.google.firebase:firebase-analytics:17.2.2'
+
+ // Firebase Authentication:
+ implementation 'com.google.firebase:firebase-auth:19.2.0'
+ implementation 'com.google.android.gms:play-services-auth:17.0.0'
+
+ // Firebase Dynamic Links:
+ implementation 'com.google.firebase:firebase-dynamic-links:19.1.0'
+
+ // Glide Dependency (Image Handling):
+ implementation 'com.github.bumptech.glide:glide:4.7.1'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
+
+ // Firebase Storage:
+ implementation 'com.google.firebase:firebase-storage:19.1.1'
+
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
diff --git a/app/google-services.json b/app/google-services.json
new file mode 100644
index 0000000..49181b7
--- /dev/null
+++ b/app/google-services.json
@@ -0,0 +1,77 @@
+{
+ "project_info": {
+ "project_number": "825859146304",
+ "firebase_url": "https://practical-android.firebaseio.com",
+ "project_id": "practical-android",
+ "storage_bucket": "practical-android.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:825859146304:android:7c67dac5123f089eb6d5a5",
+ "android_client_info": {
+ "package_name": "com.example.firebase_con"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "825859146304-v1qs3nlardt1i6o3kqf54i2k85sdv71g.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyAJSknN_NCrv8gZJUsxwOj9FiKIoz9-wXk"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "825859146304-v1qs3nlardt1i6o3kqf54i2k85sdv71g.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:825859146304:android:9be0832efb4e3c57b6d5a5",
+ "android_client_info": {
+ "package_name": "com.example.mad_cw"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "825859146304-85ruq4kj1vecoj38hb5fjgiga3ldak25.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.example.mad_cw",
+ "certificate_hash": "dd4b00285896b9ecfb467a2c48fe905a58eece5b"
+ }
+ },
+ {
+ "client_id": "825859146304-v1qs3nlardt1i6o3kqf54i2k85sdv71g.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyAJSknN_NCrv8gZJUsxwOj9FiKIoz9-wXk"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "825859146304-v1qs3nlardt1i6o3kqf54i2k85sdv71g.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b2f4730..a224146 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,11 @@
+
+
+
+
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mad_cw/BaseActivity.java b/app/src/main/java/com/example/mad_cw/BaseActivity.java
new file mode 100644
index 0000000..c901633
--- /dev/null
+++ b/app/src/main/java/com/example/mad_cw/BaseActivity.java
@@ -0,0 +1,47 @@
+package com.example.mad_cw;
+
+import android.content.Context;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.ProgressBar;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AppCompatActivity;
+
+public class BaseActivity extends AppCompatActivity {
+
+ @VisibleForTesting
+ public ProgressBar mProgressBar;
+
+ public void setProgressBar(int resId) {
+ mProgressBar = findViewById(resId);
+ }
+
+ public void showProgressBar() {
+ if (mProgressBar != null) {
+ mProgressBar.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public void hideProgressBar() {
+
+ if (mProgressBar != null) {
+ mProgressBar.setVisibility(View.INVISIBLE);
+ }
+
+ }
+
+ public void hideKeyboard(View view) {
+ final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ hideProgressBar();
+ }
+
+}
diff --git a/app/src/main/java/com/example/mad_cw/MainActivity.java b/app/src/main/java/com/example/mad_cw/MainActivity.java
index 90bd892..001018d 100644
--- a/app/src/main/java/com/example/mad_cw/MainActivity.java
+++ b/app/src/main/java/com/example/mad_cw/MainActivity.java
@@ -1,22 +1,125 @@
package com.example.mad_cw;
-import androidx.appcompat.app.AppCompatActivity;
+// Other Imports
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
import android.os.Bundle;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+// Firebase Imports
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+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.auth.UserProfileChangeRequest;
+import com.google.firebase.storage.FirebaseStorage;
+import com.google.firebase.storage.StorageReference;
+import com.google.firebase.storage.UploadTask;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
/**
* Main Activity Class
+ * _________
+ * Usage: Currently handles the user login onto the app and records them in Firebase App
+ * We will be using a password-less login here for the user authentication using the
+ * users email address.
+ *
+ * _________
+ * @author migbash
+ * @date 22/02/2020
+ *
*/
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends BaseActivity {
+
+ private static final String TAG = "MainActivity";
+
+ private FirebaseAuth mAuth;
+
+ public static final int PICK_IMAGE = 1;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ // Sign-Up Layout
setContentView(R.layout.activity_main);
- // On load show the Main App Welcome Screen / Loading Screen
+ // Views
+
+ // Buttons
+
+ // Initialize Firebase Auth
+ mAuth = FirebaseAuth.getInstance();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // Check if user is signed in (non-null) and update UI accordingly.
+ FirebaseUser currentUser = mAuth.getCurrentUser();
+ // updateUI(currentUser);
+ }
+
+// private void sendEmailVerification() {
+// // Disable button
+// findViewById(R.id.verifyEmailButton).setEnabled(false);
+//
+// // Send verification email
+// // [START send_email_verification]
+// final FirebaseUser user = mAuth.getCurrentUser();
+// user.sendEmailVerification()
+// .addOnCompleteListener(this, new OnCompleteListener() {
+// @Override
+// public void onComplete(@NonNull Task task) {
+// // [START_EXCLUDE]
+// // Re-enable button
+// findViewById(R.id.verifyEmailButton).setEnabled(true);
+//
+// if (task.isSuccessful()) {
+// Toast.makeText(MainActivity.this,
+// "Verification email sent to " + user.getEmail(),
+// Toast.LENGTH_SHORT).show();
+// } else {
+// Log.e(TAG, "sendEmailVerification", task.getException());
+// Toast.makeText(MainActivity.this,
+// "Failed to send verification email.",
+// Toast.LENGTH_SHORT).show();
+// }
+// // [END_EXCLUDE]
+// }
+// });
+// // [END send_email_verification]
+// }
+
+ public void pickManyImage() {
+ Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
+ getIntent.setType("image/*");
+
+ Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
+ pickIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ pickIntent.setType("image/*");
+
+ Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
+ chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
+ startActivityForResult(chooserIntent, PICK_IMAGE);
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mad_cw/User_Profile.java b/app/src/main/java/com/example/mad_cw/User_Profile.java
new file mode 100644
index 0000000..af639eb
--- /dev/null
+++ b/app/src/main/java/com/example/mad_cw/User_Profile.java
@@ -0,0 +1,243 @@
+package com.example.mad_cw;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.bumptech.glide.Glide;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.auth.UserProfileChangeRequest;
+import com.google.firebase.storage.FirebaseStorage;
+import com.google.firebase.storage.StorageReference;
+import com.google.firebase.storage.UploadTask;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public class User_Profile extends BaseActivity implements View.OnClickListener {
+
+ private static final String TAG = "User Profile";
+ private static final int PICK_IMAGE = 1;
+
+ private TextView UserUidNum;
+ private ImageView ProfilePicture;
+
+ private FirebaseAuth mAuth;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.user_profile);
+
+ // Views
+ ProfilePicture = findViewById(R.id.userProfilePic);
+ UserUidNum = findViewById(R.id.textView);
+
+ // Buttons
+ findViewById(R.id.updateProfilePic).setOnClickListener(this);
+ findViewById(R.id.signOutButton).setOnClickListener(this);
+
+ // Initialize Firebase Auth
+ mAuth = FirebaseAuth.getInstance();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // Check if user is signed in (non-null) and update UI accordingly.
+ FirebaseUser currentUser = mAuth.getCurrentUser();
+ updateUI(currentUser);
+ }
+
+ private void signOut() {
+ mAuth.signOut();
+ this.finish();
+ updateUI(null);
+ }
+
+ private void updateUI(FirebaseUser user) {
+ hideProgressBar();
+
+ // Check User Details
+ if (user != null) {
+
+// for (UserInfo profile : user.getProviderData()) {
+// // Id of the provider (ex: google.com)
+// String providerId = profile.getProviderId();
+//
+// // UID specific to the provider
+// String uid = profile.getUid();
+//
+// // Name, email address, and profile photo Url
+// String name = profile.getDisplayName();
+// String email = profile.getEmail();
+// Uri photoUrl = profile.getPhotoUrl();
+//
+// Log.w(TAG, providerId + " " + uid + " " + name + " " + email + " " + photoUrl.toString());
+// }
+
+ // Display user Profile Details:
+ // mStatusTextView.setText(getString(R.string.emailpassword_status_fmt, user.getEmail(), user.isEmailVerified()));
+ UserUidNum.setText(getString(R.string.firebase_status_fmt, user.getUid()));
+
+ Uri photoUrl = user.getPhotoUrl();
+ Glide.with(this).load(photoUrl).into(ProfilePicture);
+
+// Log.w(TAG, photoUrl.toString());
+// mProfilePic.setImageURI(Uri.parse(photoUrl.toString()));
+
+// findViewById(R.id.verifyEmailButton).setEnabled(!user.isEmailVerified());
+ } else {
+// mStatusTextView.setText(R.string.signed_out);
+// mDetailTextView.setText(null);
+//
+// findViewById(R.id.emailPasswordButtons).setVisibility(View.VISIBLE);
+// findViewById(R.id.emailPasswordFields).setVisibility(View.VISIBLE);
+// findViewById(R.id.signedInButtons).setVisibility(View.GONE);
+ }
+ }
+
+ /**
+ * Handling User Profile Image Update:
+ */
+
+ public void selectProfilePic() {
+ Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
+ getIntent.setType("image/*");
+
+ Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
+ pickIntent.setType("image/*");
+
+ Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
+ chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
+
+ startActivityForResult(chooserIntent, PICK_IMAGE);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+
+ if (requestCode == PICK_IMAGE && resultCode == RESULT_OK) {
+ if (data != null) {
+ // this is the image selected by the user
+ Uri imageUri = data.getData();
+ Log.w(TAG, imageUri.toString());
+
+ // Handle the user image in bitmap:
+ // Bitmap bitmap = (Bitmap) data.getExtras().get("data");
+ Bitmap bitmap = null;
+ try {
+ bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ ProfilePicture.setImageBitmap(bitmap);
+ handleUpload(bitmap);
+ }
+ }
+ }
+
+ private void handleUpload(Bitmap bitmap){
+
+ // Handle Image
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
+
+ // Get Current User UID String:
+ String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
+
+ // Store Data in Firebase Storage
+ final StorageReference reference = FirebaseStorage.getInstance().getReference()
+ .child("profileImages")
+ .child(uid + ".jpeg");
+
+ // Execute Storage
+ reference.putBytes(baos.toByteArray())
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
+ getDownloadUrl(reference);
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ Log.w(TAG, "onFailure: ", e.getCause());
+ }
+ });
+ }
+
+ private void getDownloadUrl(StorageReference reference) {
+ reference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Uri uri) {
+ Log.w(TAG, "onSuccess: " + uri);
+ updateProfile(uri);
+ }
+ });
+ }
+
+ public void updateProfile(Uri uri) {
+
+ // Get Current (Signed-In) User
+ FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
+
+ // Set Parameters that require Updating
+ UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
+ .setPhotoUri(uri)
+ .build();
+
+ // Update profile & add "complete" listener
+ user.updateProfile(profileUpdates).addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ Log.d(TAG, "User profile updated.");
+ }
+ }
+ });
+
+ // Refresh the UI Page:
+ onStart();
+
+ }
+
+ /**
+ * Class [Public Method]
+ * ______
+ * Params: View v
+ * ______
+ * Usage: User Clicks:
+ *
+ */
+
+ @Override
+ public void onClick(View v) {
+
+ switch (v.getId()) {
+
+ case R.id.updateProfilePic:
+ selectProfilePic();
+ break;
+
+ case R.id.signOutButton:
+ signOut();
+ break;
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/mad_cw/User_Sign_In.java b/app/src/main/java/com/example/mad_cw/User_Sign_In.java
new file mode 100644
index 0000000..e57f594
--- /dev/null
+++ b/app/src/main/java/com/example/mad_cw/User_Sign_In.java
@@ -0,0 +1,142 @@
+package com.example.mad_cw;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+
+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;
+
+public class User_Sign_In extends BaseActivity implements View.OnClickListener {
+
+ private static final String TAG = "UserSignIn";
+
+ private EditText emailField;
+ private EditText passwordField;
+
+ private FirebaseAuth mAuth;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Set Layout for User Sign In
+ setContentView(R.layout.user_sign_in);
+
+ // Views:
+ emailField = findViewById(R.id.userEmail);
+ passwordField = findViewById(R.id.userPassword);
+// setProgressBar(R.id.progressBar);
+
+ // Buttons & Click Events:
+ findViewById(R.id.signInButton).setOnClickListener(this);
+ findViewById(R.id.sign_Up_HyperLink).setOnClickListener(this);
+
+ // Initialize Firebase Auth
+ mAuth = FirebaseAuth.getInstance();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // Check if user is signed in (non-null) and update UI accordingly.
+ FirebaseUser currentUser = mAuth.getCurrentUser();
+ // updateUI(currentUser);
+ }
+
+ private void signIn(String email, String password) {
+ Log.d(TAG, "signIn:" + email);
+ if (!validateForm()) {
+ return;
+ }
+
+ showProgressBar();
+
+ mAuth.signInWithEmailAndPassword(email, password)
+ .addOnCompleteListener(this, new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ // Sign in success, update UI with the signed-in user's information
+ Log.d(TAG, "signInWithEmail:success");
+
+ // FirebaseUser user = mAuth.getCurrentUser();
+ // updateUI(user);
+
+ // Access the User Profile / Portal
+ Intent userProfile = new Intent(User_Sign_In.this, User_Profile.class);
+ startActivity(userProfile);
+
+ } else {
+ // If sign in fails, display a message to the user.
+ Log.w(TAG, "signInWithEmail:failure", task.getException());
+ Toast.makeText(User_Sign_In.this, "Authentication failed.",
+ Toast.LENGTH_SHORT).show();
+
+ // updateUI(null);
+ }
+
+ // [START_EXCLUDE]
+
+ if (!task.isSuccessful()) {
+ Toast.makeText(User_Sign_In.this, "Authentication failed.",
+ Toast.LENGTH_SHORT).show();
+ }
+ hideProgressBar();
+
+ // [END_EXCLUDE]
+ }
+ });
+ }
+
+ private boolean validateForm() {
+ boolean valid = true;
+
+ // Validate Email:
+ String email = emailField.getText().toString();
+ if (TextUtils.isEmpty(email)) {
+ emailField.setError("Required.");
+ valid = false;
+ } else {
+ emailField.setError(null);
+ }
+
+ // Validate Password Field
+ String password = passwordField.getText().toString();
+ if (TextUtils.isEmpty(password)) {
+ passwordField.setError("Required.");
+ valid = false;
+ } else {
+ passwordField.setError(null);
+ }
+
+ return valid;
+ }
+
+ // Handling Click Events:
+ @Override
+ public void onClick(View v) {
+
+ switch (v.getId()) {
+
+ case R.id.signInButton:
+ signIn(emailField.getText().toString(), passwordField.getText().toString());
+ break;
+
+ case R.id.sign_Up_HyperLink:
+ Intent sign_up = new Intent(this, User_Sign_Up.class);
+ startActivity(sign_up);
+ break;
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/example/mad_cw/User_Sign_Up.java b/app/src/main/java/com/example/mad_cw/User_Sign_Up.java
new file mode 100644
index 0000000..cbf9adb
--- /dev/null
+++ b/app/src/main/java/com/example/mad_cw/User_Sign_Up.java
@@ -0,0 +1,131 @@
+package com.example.mad_cw;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+
+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;
+
+public class User_Sign_Up extends BaseActivity implements View.OnClickListener {
+
+ private static final String TAG = "UserSignIn";
+
+ private EditText locationField;
+ private EditText usernameField;
+ private EditText emailField;
+ private EditText passwordField;
+
+ private FirebaseAuth mAuth;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Sign-Up Layout
+ setContentView(R.layout.user_sign_up);
+
+ // Views
+ usernameField = findViewById(R.id.username);
+ emailField = findViewById(R.id.userEmail);
+ passwordField = findViewById(R.id.userPassword);
+ locationField = findViewById(R.id.location_input);
+// setProgressBar(R.id.progressBar);
+
+ // Buttons
+ findViewById(R.id.signUpButton).setOnClickListener(this);
+ findViewById(R.id.sign_In_HyperLink).setOnClickListener(this);
+
+ // Initialize Firebase Auth
+ mAuth = FirebaseAuth.getInstance();
+ }
+
+ private void createAccount(String email, String password) {
+ Log.d(TAG, "createAccount:" + email);
+ if (!validateForm()) {
+ return;
+ }
+
+ showProgressBar();
+
+ // [START create_user_with_email]
+ mAuth.createUserWithEmailAndPassword(email, password)
+ .addOnCompleteListener(this, new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ // Sign in success, update UI with the signed-in user's information
+ Log.d(TAG, "createUserWithEmail:success");
+ FirebaseUser user = mAuth.getCurrentUser();
+ // updateUI(user);
+ } else {
+ // If sign in fails, display a message to the user.
+ Log.w(TAG, "createUserWithEmail:failure", task.getException());
+ Toast.makeText(User_Sign_Up.this, "Authentication failed.",
+ Toast.LENGTH_SHORT).show();
+ // updateUI(null);
+ }
+
+ // [START_EXCLUDE]
+ hideProgressBar();
+ // [END_EXCLUDE]
+ }
+ });
+ // [END create_user_with_email]
+ }
+
+ private boolean validateForm() {
+ boolean valid = true;
+
+ // validate User Name:
+ // Check that the user name does not exist in the database:
+
+ // Validate Email:
+ String email = emailField.getText().toString();
+ if (TextUtils.isEmpty(email)) {
+ emailField.setError("Required.");
+ valid = false;
+ } else {
+ emailField.setError(null);
+ }
+
+ // Validate Password Field
+ String password = passwordField.getText().toString();
+ if (TextUtils.isEmpty(password)) {
+ passwordField.setError("Required.");
+ valid = false;
+ } else {
+ passwordField.setError(null);
+ }
+
+ // Validate Location:
+ // check that the target location exists in the designated country.
+
+ return valid;
+ }
+
+ @Override
+ public void onClick(View v) {
+
+ switch(v.getId()) {
+
+ case R.id.signUpButton:
+ createAccount(emailField.getText().toString(), passwordField.getText().toString());
+ break;
+
+ case R.id.sign_In_HyperLink:
+ Intent sign_in = new Intent(this, User_Sign_In.class);
+ startActivity(sign_in);
+ break;
+ }
+ }
+}
diff --git a/app/src/main/res/drawable/border_input.xml b/app/src/main/res/drawable/border_input.xml
new file mode 100644
index 0000000..8ab7789
--- /dev/null
+++ b/app/src/main/res/drawable/border_input.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/button_primary.xml b/app/src/main/res/drawable/button_primary.xml
new file mode 100644
index 0000000..48f1645
--- /dev/null
+++ b/app/src/main/res/drawable/button_primary.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/font/raleway_semibold.ttf b/app/src/main/res/font/raleway_semibold.ttf
new file mode 100644
index 0000000..ed0a8b9
Binary files /dev/null and b/app/src/main/res/font/raleway_semibold.ttf differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 4fc2444..9a28ca2 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -7,12 +7,70 @@
tools:context=".MainActivity">
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="0.21" />
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/user_profile.xml b/app/src/main/res/layout/user_profile.xml
new file mode 100644
index 0000000..7ee6783
--- /dev/null
+++ b/app/src/main/res/layout/user_profile.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/user_sign_in.xml b/app/src/main/res/layout/user_sign_in.xml
new file mode 100644
index 0000000..c4d29f6
--- /dev/null
+++ b/app/src/main/res/layout/user_sign_in.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/user_sign_up.xml b/app/src/main/res/layout/user_sign_up.xml
new file mode 100644
index 0000000..bf53a54
--- /dev/null
+++ b/app/src/main/res/layout/user_sign_up.xml
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 69b2233..fd1dce3 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,6 +1,8 @@
- #008577
- #00574B
- #D81B60
+
+ #039BE5
+ #0288D1
+ #FFA000
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..5f1a79a
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ 16dp
+ 16dp
+
+ 24dp
+ 24dp
+ 16dp
+ 160dp
+
+ 8dp
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5c60ac1..21b6408 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,108 @@
- mad_cw
+
+
+ Pedal Tribe
+
+ Firebase + Google Sign In
+ Use a Google Sign In credential to authenticate with Firebase.
+
+ Firebase + Facebook Login
+ Use a Facebook Login credential to authenticate with Firebase.
+
+ Email/Password Authentication
+ Use an email and password to authenticate with Firebase.
+
+ Passwordless Authentication
+ Use only an email to authenticate with Firebase.
+
+ Phone Number Authentication
+ Use a phone number to authenticate with Firebase.
+
+ Anonymous Authentication
+ Sign in anonymously and then later upgrade to a full Firebase Auth user.
+
+ Custom Authentication
+ Use a custom token signed by your own server to authenticate with Firebase.
+
+ FirebaseUI Auth
+ Use the FirebaseUI-Android library to authenticate with Firebase.
+
+ Generic OAuth
+ Use a generic OAuth identity provider, like Apple, Microsoft, Yahoo, or Twitter to authenticate with Firebase.
+
+ User ID
+ Get Token
+ Sign In
+ Create Account
+ Send Link
+ Sign Out
+ Verify Email
+ Disconnect
+ Loading…
+ Custom Token
+ Signed In
+ Signed Out
+ Token: null
+ Firebase logo and name
+ Authentication failed
+ Start
+ Verify
+ Resend
+ Phone Number
+ Verification Code
+ Code Sent
+ Verification failed
+ Verification succeeded
+ Sign-in failed
+ (instant validation)
+
+ Firebase UID: %s
+ Firebase User Management
+
+ Google User: %s
+ Google Sign In
+
+ Facebook User: %s
+ Facebook Login
+
+ Email User: %1$s (verified: %2$b)
+ Email and Password
+
+ Email User: %1$s (verified: %2$b)
+ Passwordless Sign In
+ Send link to your email to get started.
+ Link sent, check your email to continue.
+ Link received, enter email to sign in.
+
+ OAuth Sign In
+ Sign In with %s
+ User: %s (%s)
+ Provider:
+
+
+ User ID: %s
+ Email: %s
+
+
+ Update Profile
+ Email
+ Password
+ Username
+ Location
+
+
+ Welcome to Pedal Tribe, \n the largest cycling community \n built for cyclists, by cyclists
+ Already have an account?
+ Sign Up
+ Uh-oh 😧 Sign In failed
+
+
+ Welcome back pedal freak,
+ Do not have an account?
+ Sign In
+ Uh-oh 😧 account could not be created
+
+
+
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 5885930..5c66108 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -8,4 +8,43 @@
- @color/colorAccent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build.gradle b/build.gradle
index a5bb815..e961888 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,12 +2,15 @@
buildscript {
repositories {
- google()
+ google() // Google's Maven repository
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
+
+ // Connecting to Google JSON Services
+ classpath 'com.google.gms:google-services:4.3.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -16,7 +19,7 @@ buildscript {
allprojects {
repositories {
- google()
+ google() // Google's Maven repository
jcenter()
}