сделай так чтобы использовался firebase напиши все что мне нужно сделать для этого и напиши весь код который будет нужен для этого то есть чтобы допустим игрок авторизовывался при помощи google и его данные и рекорды которые храниться в локальной базе данных для каждого пользователя дело в том что я использую кажется локальную базу данных и например там храниться данные о игроке только в локальной базе данных пока что и эти данные удаляются допустим при удалении самого приложения а я хочу подключить firebase чтобы даже после удаления приложения данные сохранялись на авторизованном при входе аккаунте google 

у меня совершенно нет опыта в этом поэтому ты должен полностью объяснить мне точно как это сделать


package com.example.memorygameone;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DB extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "games.db";
    public static final int DATABASE_VERSION = 1;

    // Table for the original memory game
    public static final String MEMORY_GAME_TABLE = "memory_game_statistics";
    public static final String COL_ID = "ID";
    public static final String COL_NICKNAME = "NICKNAME";
    public static final String COL_DIFFICULTY = "DIFFICULTY";
    public static final String COL_BEST_TIME_MEMORY = "BEST_TIME_MEMORY";
    public static final String COL_BEST_TIME_SCORE_MEMORY = "BEST_TIME_SCORE_MEMORY";
    public static final String COL_BEST_SCORE_MEMORY = "BEST_SCORE_MEMORY";
    public static final String COL_BEST_SCORE_TIME_MEMORY = "BEST_SCORE_TIME_MEMORY";

    // Table for the reaction game
    public static final String REACTION_GAME_TABLE = "reaction_game_statistics";
    public static final String COL_BEST_REACTION_TIME = "BEST_REACTION_TIME";

    // Table for the pair matching game
    public static final String PAIR_MATCHING_TABLE = "pair_matching_statistics";
    public static final String COL_BEST_MOVES = "BEST_MOVES";
    public static final String COL_BEST_TIME = "BEST_TIME";
    public static final String COL_FASTEST_MOVES = "FASTEST_MOVES";
    public static final String COL_FASTEST_TIME = "FASTEST_TIME";

    public DB(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        // Create table for memory game
        db.execSQL("CREATE TABLE " + MEMORY_GAME_TABLE + " (" +
                COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_NICKNAME + " TEXT, " +
                COL_DIFFICULTY + " TEXT, " +
                COL_BEST_TIME_MEMORY + " INTEGER, " +
                COL_BEST_TIME_SCORE_MEMORY + " INTEGER, " +
                COL_BEST_SCORE_MEMORY + " INTEGER, " +
                COL_BEST_SCORE_TIME_MEMORY + " INTEGER)");


        // Create table for reaction game
        db.execSQL("CREATE TABLE " + REACTION_GAME_TABLE + " (" +
                COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_NICKNAME + " TEXT, " +
                COL_BEST_REACTION_TIME + " INTEGER)");

        // Create table for pair matching game
        db.execSQL("CREATE TABLE " + PAIR_MATCHING_TABLE + " (" +
                COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_NICKNAME + " TEXT, " +
                COL_BEST_MOVES + " INTEGER, " +
                COL_BEST_TIME + " INTEGER, " +
                COL_FASTEST_MOVES + " INTEGER, " +
                COL_FASTEST_TIME + " INTEGER)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older tables if existed
        db.execSQL("DROP TABLE IF EXISTS " + MEMORY_GAME_TABLE);
        db.execSQL("DROP TABLE IF EXISTS " + REACTION_GAME_TABLE);
        db.execSQL("DROP TABLE IF EXISTS " + PAIR_MATCHING_TABLE);
        // Create tables again
        onCreate(db);
    }

    // Метод обновления статистики игры Memory
    public boolean updateMemoryGameStats(String nickname, String difficulty, int newScore, long newTime) {
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM " + MEMORY_GAME_TABLE +
                " WHERE " + COL_NICKNAME + "=? AND " + COL_DIFFICULTY + "=?", new String[]{nickname, difficulty});

        boolean newRecord = false;
        ContentValues values = new ContentValues();

        if (cursor.moveToFirst()) {
            long bestTime = cursor.getLong(cursor.getColumnIndexOrThrow(COL_BEST_TIME_MEMORY));
            int bestScore = cursor.getInt(cursor.getColumnIndexOrThrow(COL_BEST_SCORE_MEMORY));

            if (newTime < bestTime) {
                values.put(COL_BEST_TIME_MEMORY, newTime);
                values.put(COL_BEST_TIME_SCORE_MEMORY, newScore);
                newRecord = true;
            }

            if (newScore > bestScore) {
                values.put(COL_BEST_SCORE_MEMORY, newScore);
                values.put(COL_BEST_SCORE_TIME_MEMORY, newTime);
                newRecord = true;
            }

            if (newRecord) {
                db.update(MEMORY_GAME_TABLE, values, COL_NICKNAME + "=? AND " + COL_DIFFICULTY + "=?", new String[]{nickname, difficulty});
            }
        } else {
            values.put(COL_NICKNAME, nickname);
            values.put(COL_DIFFICULTY, difficulty);
            values.put(COL_BEST_TIME_MEMORY, newTime);
            values.put(COL_BEST_TIME_SCORE_MEMORY, newScore);
            values.put(COL_BEST_SCORE_MEMORY, newScore);
            values.put(COL_BEST_SCORE_TIME_MEMORY, newTime);
            db.insert(MEMORY_GAME_TABLE, null, values);
            newRecord = true;
        }

        cursor.close();


        return newRecord;
    }


    public Cursor getMemoryGameStats(String nickname, String difficulty) {
        SQLiteDatabase db = this.getReadableDatabase();
        return db.rawQuery("SELECT * FROM " + MEMORY_GAME_TABLE +
                " WHERE " + COL_NICKNAME + "=? AND " + COL_DIFFICULTY + "=?", new String[]{nickname, difficulty});
    }

    // Methods for Reaction Game
    public boolean updateReactionGameStats(String nickname, int reactionTime) {
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT " + COL_BEST_REACTION_TIME + " FROM " + REACTION_GAME_TABLE +
                " WHERE " + COL_NICKNAME + "=?", new String[]{nickname});
        boolean newRecord = false;

        if (cursor.moveToFirst()) {
            int bestTime = cursor.getInt(0);
            if (reactionTime < bestTime) {
                ContentValues contentValues = new ContentValues();
                contentValues.put(COL_BEST_REACTION_TIME, reactionTime);
                db.update(REACTION_GAME_TABLE, contentValues, COL_NICKNAME + "=?", new String[]{nickname});
                newRecord = true;
            }
        } else {
            ContentValues contentValues = new ContentValues();
            contentValues.put(COL_NICKNAME, nickname);
            contentValues.put(COL_BEST_REACTION_TIME, reactionTime);
            db.insert(REACTION_GAME_TABLE, null, contentValues);
            newRecord = true;
        }
        cursor.close();
        return newRecord;
    }

    public Cursor getReactionGameStats(String nickname) {
        SQLiteDatabase db = this.getReadableDatabase();
        return db.rawQuery("SELECT " + COL_BEST_REACTION_TIME + " FROM " + REACTION_GAME_TABLE +
                " WHERE " + COL_NICKNAME + "=?", new String[]{nickname});
    }

    // Methods for Pair Matching Game
    public boolean updatePairMatchingStats(String nickname, int moves, long time) {
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM " + PAIR_MATCHING_TABLE + " WHERE " + COL_NICKNAME + "=?", new String[]{nickname});

        boolean newRecord = false;
        ContentValues values = new ContentValues();

        if (cursor.moveToFirst()) {
            int bestMovesIndex = cursor.getColumnIndex(COL_BEST_MOVES);
            int bestTimeIndex = cursor.getColumnIndex(COL_BEST_TIME);
            int fastestMovesIndex = cursor.getColumnIndex(COL_FASTEST_MOVES);
            int fastestTimeIndex = cursor.getColumnIndex(COL_FASTEST_TIME);

            int bestMoves = (bestMovesIndex != -1) ? cursor.getInt(bestMovesIndex) : Integer.MAX_VALUE;
            long bestTime = (bestTimeIndex != -1) ? cursor.getLong(bestTimeIndex) : Long.MAX_VALUE;
            int fastestMoves = (fastestMovesIndex != -1) ? cursor.getInt(fastestMovesIndex) : Integer.MAX_VALUE;
            long fastestTime = (fastestTimeIndex != -1) ? cursor.getLong(fastestTimeIndex) : Long.MAX_VALUE;

            if (moves < bestMoves) {
                values.put(COL_BEST_MOVES, moves);
                values.put(COL_BEST_TIME, time);
                newRecord = true;
            }

            if (time < fastestTime) {
                values.put(COL_FASTEST_MOVES, moves);
                values.put(COL_FASTEST_TIME, time);
                newRecord = true;
            }

            if (newRecord) {
                db.update(PAIR_MATCHING_TABLE, values, COL_NICKNAME + "=?", new String[]{nickname});
            }
        } else {
            values.put(COL_NICKNAME, nickname);
            values.put(COL_BEST_MOVES, moves);
            values.put(COL_BEST_TIME, time);
            values.put(COL_FASTEST_MOVES, moves);
            values.put(COL_FASTEST_TIME, time);
            db.insert(PAIR_MATCHING_TABLE, null, values);
            newRecord = true;
        }

        cursor.close();
        return newRecord;
    }

    public Cursor getPairMatchingStats(String nickname) {
        SQLiteDatabase db = this.getReadableDatabase();
        return db.rawQuery("SELECT * FROM " + PAIR_MATCHING_TABLE + " WHERE " + COL_NICKNAME + "=?", new String[]{nickname});
    }
}




package com.example.memorygameone;

import android.content.Intent;
import android.os.Bundle;
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.tasks.Task;
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 int RC_SIGN_IN = 9001;
    private GoogleSignInClient googleSignInClient;
    private FirebaseAuth auth;

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

        // Настройка Google Sign-In
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))  // Добавь client_id из google-services.json
                .requestEmail()
                .build();

        googleSignInClient = GoogleSignIn.getClient(this, gso);
        auth = FirebaseAuth.getInstance();

        findViewById(R.id.login_button).setOnClickListener(v -> signInWithGoogle());
    }

    private void signInWithGoogle() {
        Intent signInIntent = googleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    @Override
    public 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);
            handleSignInResult(task);
        }
    }

    private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
        try {
            GoogleSignInAccount account = completedTask.getResult(Exception.class);
            if (account != null) {
                firebaseAuthWithGoogle(account);
            }
        } catch (Exception e) {
            // Обработка ошибки
        }
    }

    private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
        AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
        auth.signInWithCredential(credential).addOnCompleteListener(this, task -> {
            if (task.isSuccessful()) {
                FirebaseUser user = auth.getCurrentUser();
                updateUI(user);
            } else {
                updateUI(null);
            }
        });
    }

    private void updateUI(FirebaseUser user) {
        if (user != null) {
            startActivity(new Intent(LoginActivity.this, MainActivity.class));
            finish();
        }
    }
}





package com.example.memorygameone;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private SoundManager soundManager;
    private FirebaseAuth auth;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        auth = FirebaseAuth.getInstance();

        // Проверяем, вошел ли пользователь
        if (auth.getCurrentUser() == null) {
            startActivity(new Intent(MainActivity.this, LoginActivity.class));
            finish();
        }
        FirebaseApp.initializeApp(this);
        soundManager = SoundManager.getInstance(this);

        SharedPreferences preferences = getSharedPreferences("game_prefs", MODE_PRIVATE);
        boolean isFirstRun = preferences.getBoolean("isFirstRun", true);

        if (isFirstRun) {
            // Go to LoginActivity on the first run
            startActivity(new Intent(MainActivity.this, LoginActivity.class));
            finish();
            preferences.edit().putBoolean("isFirstRun", false).apply();
            return;
        }


        Button btnStartMemoryGame = findViewById(R.id.btn_memory);
        Button btnStartReactionGame = findViewById(R.id.btn_reaction);
        Button btnProfile = findViewById(R.id.btn_profile);
        Button btnStartPairMatchingGame = findViewById(R.id.btn_pair_matching);

        btnStartMemoryGame.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            Intent intent = new Intent(MainActivity.this, DifficultySelectionActivity.class);
            startActivity(intent);
        });

        btnStartReactionGame.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            Intent intent = new Intent(MainActivity.this, ReactionGameModeSelection.class);
            startActivity(intent);
        });

        btnProfile.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            Intent intent = new Intent(MainActivity.this, ProfileActivity.class);
            startActivity(intent);
        });

        btnStartPairMatchingGame.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            Intent intent = new Intent(MainActivity.this, PairMatchingGame.class);
            startActivity(intent);
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        auth = FirebaseAuth.getInstance();
        FirebaseUser currentUser = auth.getCurrentUser();

        // If user is not logged in, navigate to LoginActivity
        if (currentUser == null) {
            Intent intent = new Intent(MainActivity.this, LoginActivity.class);
            startActivity(intent);
            finish();  // Close MainActivity to prevent going back to it
        }
    }



    @Override
    protected void onPause() {
        super.onPause();
        if (soundManager != null) {
            soundManager.pauseBackgroundMusic();
        }
    }

}




package com.example.memorygameone;

import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class ProfileActivity extends AppCompatActivity {

    private DB dbHelper;
    private TextView profileView;
    private SharedPreferences preferences;

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

        dbHelper = new DB(this);
        preferences = getSharedPreferences("game_prefs", MODE_PRIVATE);
        profileView = findViewById(R.id.profile_view);

        loadProfileData();
    }

    private void loadProfileData() {
        String nickname = preferences.getString("nickname", "Player");

        StringBuilder profileInfo = new StringBuilder();
        profileInfo.append("Никнейм: ").append(nickname).append("\n\n");

        profileInfo.append("Легкая сложность: \n").append(getBestScoreForDifficulty(nickname, "easy")).append("\n");
        profileInfo.append("Средняя сложность: \n").append(getBestScoreForDifficulty(nickname, "medium")).append("\n");
        profileInfo.append("Тяжелая сложность: \n").append(getBestScoreForDifficulty(nickname, "hard")).append("\n");

        profileInfo.append("\nИгра на реакцию: \n").append(getBestReactionTime(nickname)).append("\n");

        profileInfo.append("\nИгра 'Найди пары': \n").append(getPairMatchingStats(nickname)).append("\n");

        profileView.setText(profileInfo.toString());
    }

    // Получаем рекорд для указанной сложности
    private String getBestScoreForDifficulty(String nickname, String difficulty) {
        Cursor cursor = dbHelper.getMemoryGameStats(nickname, difficulty);
        if (cursor != null && cursor.moveToFirst()) {
            int bestTimeIndex = cursor.getColumnIndex(DB.COL_BEST_TIME_MEMORY);
            int bestTimeScoreIndex = cursor.getColumnIndex(DB.COL_BEST_TIME_SCORE_MEMORY);
            int bestScoreIndex = cursor.getColumnIndex(DB.COL_BEST_SCORE_MEMORY);
            int bestScoreTimeIndex = cursor.getColumnIndex(DB.COL_BEST_SCORE_TIME_MEMORY);

            long bestTime = bestTimeIndex != -1 ? cursor.getLong(bestTimeIndex) : -1;
            int bestTimeScore = bestTimeScoreIndex != -1 ? cursor.getInt(bestTimeScoreIndex) : -1;
            int bestScore = bestScoreIndex != -1 ? cursor.getInt(bestScoreIndex) : -1;
            long bestScoreTime = bestScoreTimeIndex != -1 ? cursor.getLong(bestScoreTimeIndex) : -1;

            cursor.close();

            StringBuilder result = new StringBuilder();
            if (bestTime != -1 && bestTimeScore != -1) {
                result.append("Лучшее время: ").append(bestTime).append(" секунд, Очки: ").append(bestTimeScore).append("\n");
            }
            if (bestScore != -1 && bestScoreTime != -1) {
                result.append("Лучшие очки: ").append(bestScore).append(", Время: ").append(bestScoreTime).append(" секунд");
            }

            return result.length() > 0 ? result.toString() : "Неполные данные";
        } else {
            if (cursor != null) {
                cursor.close();
            }
            return "Нет записей";
        }
    }


    // Получаем рекорд для игры на реакцию
    private String getBestReactionTime(String nickname) {
        Cursor cursor = dbHelper.getReactionGameStats(nickname);
        if (cursor.moveToFirst()) {
            int bestTime = cursor.getInt(0);
            cursor.close();
            return "Лучшее время реакции: " + bestTime + " мс";
        } else {
            cursor.close();
            return "Нет записей";
        }
    }

    // Получаем рекорд из игры на нахождение одинаковых плиток
    private String getPairMatchingStats(String nickname) {
        Cursor cursor = dbHelper.getPairMatchingStats(nickname);
        if (cursor != null && cursor.moveToFirst()) {
            int bestMovesIndex = cursor.getColumnIndex(DB.COL_BEST_MOVES);
            int bestTimeIndex = cursor.getColumnIndex(DB.COL_BEST_TIME);
            int fastestMovesIndex = cursor.getColumnIndex(DB.COL_FASTEST_MOVES);
            int fastestTimeIndex = cursor.getColumnIndex(DB.COL_FASTEST_TIME);

            int bestMoves = (bestMovesIndex != -1) ? cursor.getInt(bestMovesIndex) : -1;
            long bestTime = (bestTimeIndex != -1) ? cursor.getLong(bestTimeIndex) : -1;
            int fastestMoves = (fastestMovesIndex != -1) ? cursor.getInt(fastestMovesIndex) : -1;
            long fastestTime = (fastestTimeIndex != -1) ? cursor.getLong(fastestTimeIndex) : -1;

            cursor.close();

            StringBuilder stats = new StringBuilder();
            if (bestMoves != -1 && bestTime != -1) {
                stats.append("Лучшие ходы: ").append(bestMoves).append(", Время: ").append(formatTime(bestTime)).append("\n");
            }
            if (fastestTime != -1 && fastestMoves != -1) {
                stats.append("Быстрейшее время: ").append(formatTime(fastestTime)).append(", Ходы: ").append(fastestMoves);
            }

            return stats.length() > 0 ? stats.toString() : "Неполные данные";
        } else {
            if (cursor != null) {
                cursor.close();
            }
            return "Нет записей";
        }
    }

    private String formatTime(long totalSeconds) {
        if (totalSeconds < 0) {
            return "Недоступно";
        }
        long minutes = totalSeconds / 60;
        long seconds = totalSeconds % 60;
        return String.format("%d:%02d", minutes, seconds);
    }
}