Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
alias(libs.plugins.android.application)
id("com.google.gms.google-services")
}

android {
Expand Down Expand Up @@ -62,6 +63,11 @@ dependencies {
implementation("com.github.bumptech.glide:glide:4.16.0")
annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")

// Firebase
implementation(platform("com.google.firebase:firebase-bom:32.7.2"))
implementation("com.google.firebase:firebase-auth")
implementation("com.google.android.gms:play-services-auth:20.7.0")

testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
Expand Down
121 changes: 112 additions & 9 deletions app/google-services.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,144 @@
{
"project_info": {
"project_number": "396348569226",
"project_id": "to-do-app-49217",
"storage_bucket": "to-do-app-49217.firebasestorage.app"
"project_number": "767282860838",
"project_id": "to-do-1d14f",
"storage_bucket": "to-do-1d14f.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:396348569226:android:1a57f94b687fdf83a21f73",
"mobilesdk_app_id": "1:767282860838:android:7414e6a2a5491489d6e7e7",
"android_client_info": {
"package_name": "com.example.login"
}
},
"oauth_client": [
{
"client_id": "767282860838-8kn6msc75sl7fc2qk6tbb79mnlacck98.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyC2uu3l_afXE62nLGJBlWZcJjMJqvSnKNw"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "767282860838-8kn6msc75sl7fc2qk6tbb79mnlacck98.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:767282860838:android:fc85b1d75558ae89d6e7e7",
"android_client_info": {
"package_name": "com.example.todoapp"
}
},
"oauth_client": [
{
"client_id": "767282860838-8n21vh7f2plpsjogn518lpam46usdcid.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.example.todoapp",
"certificate_hash": "4bff53fcb2a58c2562df2312aab097de9f6715ae"
}
},
{
"client_id": "767282860838-8kn6msc75sl7fc2qk6tbb79mnlacck98.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyC2uu3l_afXE62nLGJBlWZcJjMJqvSnKNw"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "767282860838-8kn6msc75sl7fc2qk6tbb79mnlacck98.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:767282860838:android:ba1adf879e8432cfd6e7e7",
"android_client_info": {
"package_name": "com.example.todoappv2"
}
},
"oauth_client": [
{
"client_id": "396348569226-d3fd7d7s6tm4vl6ijfbpjt8gvbslrj9v.apps.googleusercontent.com",
"client_id": "767282860838-m9hb1tq84usudk3po63f34s5smo9jvgb.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.example.todoappv2",
"certificate_hash": "9c04ba4ed1a9957a60183031dde2beb7c8e39e75"
"certificate_hash": "4bff53fcb2a58c2562df2312aab097de9f6715ae"
}
},
{
"client_id": "767282860838-8kn6msc75sl7fc2qk6tbb79mnlacck98.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyC2uu3l_afXE62nLGJBlWZcJjMJqvSnKNw"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "767282860838-8kn6msc75sl7fc2qk6tbb79mnlacck98.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:767282860838:android:816f9590c5136c3bd6e7e7",
"android_client_info": {
"package_name": "com.example.ver1"
}
},
"oauth_client": [
{
"client_id": "767282860838-bc3drpltfpb14d7g7ec5fg94e8pa0jle.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.example.ver1",
"certificate_hash": "4bff53fcb2a58c2562df2312aab097de9f6715ae"
}
},
{
"client_id": "396348569226-sfsf7pftqp1p4bcpb57h9ilt50mbkdqb.apps.googleusercontent.com",
"client_id": "767282860838-8kn6msc75sl7fc2qk6tbb79mnlacck98.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDtCC8nXM8q4RtDXRi7VbEzTc2I6UFSmrI"
"current_key": "AIzaSyC2uu3l_afXE62nLGJBlWZcJjMJqvSnKNw"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "396348569226-sfsf7pftqp1p4bcpb57h9ilt50mbkdqb.apps.googleusercontent.com",
"client_id": "767282860838-8kn6msc75sl7fc2qk6tbb79mnlacck98.apps.googleusercontent.com",
"client_type": 3
}
]
Expand Down
11 changes: 9 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,22 @@
android:theme="@style/Theme.TodoAppV2"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:name=".LoginActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name=".RegisterActivity"
android:exported="false" />

<activity
android:name=".MainActivity"
android:exported="false" />

<activity
android:name=".AddTodoActivity"
android:exported="false"
Expand Down
151 changes: 151 additions & 0 deletions app/src/main/java/com/example/todoappv2/LoginActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package com.example.todoappv2;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.Task;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GoogleAuthProvider;

public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LoginActivity";
private static final int RC_SIGN_IN = 9001;

private TextInputEditText emailEditText, passwordEditText;
private MaterialButton loginButton, googleLoginButton;
private FirebaseAuth mAuth;
private GoogleSignInClient mGoogleSignInClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);

mAuth = FirebaseAuth.getInstance();

// Initialize views
emailEditText = findViewById(R.id.emailEditText);
passwordEditText = findViewById(R.id.passwordEditText);
loginButton = findViewById(R.id.loginButton);
googleLoginButton = findViewById(R.id.googleLoginButton);

// Get data from RegisterActivity if any
Intent intent = getIntent();
String passedEmail = intent.getStringExtra("username");
String passedPassword = intent.getStringExtra("password");

if (passedEmail != null) {
emailEditText.setText(passedEmail);
}
if (passedPassword != null) {
passwordEditText.setText(passedPassword);
}

// Email/Password login
loginButton.setOnClickListener(v -> {
String email = emailEditText.getText().toString().trim();
String password = passwordEditText.getText().toString().trim();

if (email.isEmpty() || password.isEmpty()) {
Toast.makeText(this, "Email và mật khẩu không được để trống", Toast.LENGTH_SHORT).show();
return;
}

mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Toast.makeText(this, "Đăng nhập thành công!", Toast.LENGTH_SHORT).show();
startActivity(new Intent(this, MainActivity.class));
finish();
} else {
Toast.makeText(this, "Đăng nhập thất bại: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
});
});

// Register navigation
findViewById(R.id.goToRegister).setOnClickListener(v -> {
startActivity(new Intent(this, RegisterActivity.class));
});

// Configure Google Sign-In
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();

mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

// Google Sign-In button
googleLoginButton.setOnClickListener(v -> signInWithGoogle());
}

private void signInWithGoogle() {
mGoogleSignInClient.signOut().addOnCompleteListener(this, task -> {
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RC_SIGN_IN);
});
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (requestCode == RC_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
try {
GoogleSignInAccount account = task.getResult(ApiException.class);
String idToken = account.getIdToken();
if (idToken != null) {
firebaseAuthWithGoogle(idToken);
} else {
Toast.makeText(this, "Không lấy được ID token", Toast.LENGTH_SHORT).show();
}
} catch (ApiException e) {
Log.e(TAG, "Đăng nhập Google thất bại", e);
Toast.makeText(this, "Đăng nhập Google thất bại: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}

private void firebaseAuthWithGoogle(String idToken) {
AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
FirebaseUser user = mAuth.getCurrentUser();
Toast.makeText(this, "Đăng nhập thành công: " + user.getDisplayName(), Toast.LENGTH_SHORT).show();
startActivity(new Intent(this, MainActivity.class));
finish();
} else {
Log.e(TAG, "Firebase Auth thất bại", task.getException());
Toast.makeText(this, "Xác thực Firebase thất bại", Toast.LENGTH_SHORT).show();
}
});
}

@Override
protected void onStart() {
super.onStart();
// Check if user is signed in
FirebaseUser currentUser = mAuth.getCurrentUser();
if (currentUser != null) {
startActivity(new Intent(this, MainActivity.class));
finish();
}
}
}
Loading