Android Firebase登录和存储用户数据方案

281 阅读2分钟

以下是使用 Firebase 在 Android 中实现用户认证和待办事项数据操作的详细代码示例(Java 和 Kotlin 双版本):


一、Firebase 配置步骤

  1. Firebase 控制台 创建项目
  2. 添加 Android 应用(填写包名)
  3. 下载 google-services.json 文件并放入 app/ 目录
  4. 添加依赖:

build.gradle (Module)

// Java 版本
implementation 'com.google.firebase:firebase-auth:22.3.1'
implementation 'com.google.firebase:firebase-database:20.3.1'

// Kotlin 额外需要
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3'

build.gradle (Project)

classpath 'com.google.gms:google-services:4.4.1'

二、用户认证实现

1. 注册功能

Java 版本 (RegisterActivity.java)

public class RegisterActivity extends AppCompatActivity {
    private EditText etEmail, etPassword;
    private FirebaseAuth mAuth;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);
        
        mAuth = FirebaseAuth.getInstance();
        etEmail = findViewById(R.id.etEmail);
        etPassword = findViewById(R.id.etPassword);
        
        findViewById(R.id.btnRegister).setOnClickListener(v -> {
            String email = etEmail.getText().toString();
            String password = etPassword.getText().toString();
            
            mAuth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        // 注册成功
                        startActivity(new Intent(this, MainActivity.class));
                    } else {
                        // 处理错误
                        Toast.makeText(this, "注册失败: " + task.getException(), 
                            Toast.LENGTH_SHORT).show();
                    }
                });
        });
    }
}

Kotlin 版本 (RegisterActivity.kt)

class RegisterActivity : AppCompatActivity() {
    private lateinit var auth: FirebaseAuth

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_register)
        
        auth = FirebaseAuth.getInstance()
        
        btnRegister.setOnClickListener {
            val email = etEmail.text.toString()
            val password = etPassword.text.toString()
            
            auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener { task ->
                    if (task.isSuccessful()) {
                        startActivity(Intent(this, MainActivity::class.java))
                    } else {
                        Toast.makeText(this, "注册失败: ${task.exception?.message}", 
                            Toast.LENGTH_SHORT).show()
                    }
                }
        }
    }
}

2. 登录功能

Java 版本 (LoginActivity.java)

public class LoginActivity extends AppCompatActivity {
    // ... 类似注册的初始化代码
    
    private void performLogin() {
        String email = etEmail.getText().toString();
        String password = etPassword.getText().toString();
        
        mAuth.signInWithEmailAndPassword(email, password)
            .addOnCompleteListener(task -> {
                if (task.isSuccessful()) {
                    // 登录成功
                    startActivity(new Intent(this, MainActivity.class));
                } else {
                    Toast.makeText(this, "登录失败: " + task.getException(), 
                        Toast.LENGTH_SHORT).show();
                }
            });
    }
}

Kotlin 版本 (LoginActivity.kt)

// ... 类似注册的初始化代码
auth.signInWithEmailAndPassword(email, password)
    .addOnCompleteListener { task ->
        if (task.isSuccessful()) {
            startActivity(Intent(this, MainActivity::class.java))
        } else {
            Toast.makeText(this, "登录失败: ${task.exception?.message}", 
                Toast.LENGTH_SHORT).show()
        }
    }

三、待办事项数据操作

1. 数据结构设计

{
  "todos" : {
    "userId1" : {
      "todoId1" : {
        "title" : "购物",
        "content" : "买牛奶",
        "timestamp" : 1717029200,
        "completed" : false
      },
      "todoId2" : { ... }
    }
  }
}

2. 数据模型类

Java 版本 (TodoItem.java)

public class TodoItem {
    private String id;
    private String title;
    private String content;
    private long timestamp;
    private boolean completed;

    // 空构造方法(Firebase 必需)
    public TodoItem() {}

    // Getter 和 Setter
    // ... 自动生成或手动编写
}

Kotlin 版本 (TodoItem.kt)

data class TodoItem(
    var id: String = "",
    var title: String = "",
    var content: String = "",
    var timestamp: Long = 0,
    var completed: Boolean = false
)

3. 数据存储操作

Java 版本 (TodoRepository.java)

public class TodoRepository {
    private DatabaseReference databaseRef;
    private String userId;

    public TodoRepository() {
        userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
        databaseRef = FirebaseDatabase.getInstance()
                        .getReference("todos").child(userId);
    }

    public void addTodo(TodoItem todo, DatabaseReference.CompletionListener listener) {
        String key = databaseRef.push().getKey();
        todo.setId(key);
        databaseRef.child(key).setValue(todo).addOnCompleteListener(task -> {
            if (listener != null) listener.onComplete(null, task.getException());
        });
    }
}

Kotlin 版本 (TodoRepository.kt)

class TodoRepository {
    private val userId = FirebaseAuth.getInstance().currentUser?.uid ?: ""
    private val databaseRef = FirebaseDatabase.getInstance()
                          .getReference("todos/$userId")

    fun addTodo(todo: TodoItem, onComplete: (Exception?) -> Unit) {
        val key = databaseRef.push().key
        key?.let {
            todo.id = it
            databaseRef.child(it).setValue(todo)
                .addOnCompleteListener { onComplete(it.exception) }
        }
    }
}

4. 数据查询与监听

Java 版本

public void observeTodos(ValueEventListener listener) {
    databaseRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            List<TodoItem> todos = new ArrayList<>();
            for (DataSnapshot child : snapshot.getChildren()) {
                TodoItem item = child.getValue(TodoItem.class);
                todos.add(item);
            }
            // 更新UI(使用LiveData或直接回调)
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            // 处理错误
        }
    });
}

Kotlin 版本

fun observeTodos(onUpdate: (List<TodoItem>) -> Unit) {
    databaseRef.addValueEventListener(object : ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            val todos = snapshot.children.mapNotNull { it.getValue(TodoItem::class.java) }
            onUpdate(todos)
        }

        override fun onCancelled(error: DatabaseError) {
            // 处理错误
        }
    })
}

5. 修改数据操作

Java 版本

public void updateTodo(String todoId, Map<String, Object> updates) {
    databaseRef.child(todoId).updateChildren(updates)
        .addOnCompleteListener(task -> {
            // 处理完成状态
        });
}

// 使用示例:
Map<String, Object> updates = new HashMap<>();
updates.put("completed", true);
repository.updateTodo(todoId, updates);

Kotlin 版本

fun updateTodo(todoId: String, updates: Map<String, Any>) {
    databaseRef.child(todoId).updateChildren(updates)
        .addOnCompleteListener { /* 处理结果 */ }
}

// 使用示例:
val updates = mapOf("completed" to true)
repository.updateTodo(todoId, updates)

四、数据库安全规则

在 Firebase 控制台设置 Realtime Database 规则:

{
  "rules": {
    "todos": {
      "$userId": {
        ".read": "auth != null && auth.uid == $userId",
        ".write": "auth != null && auth.uid == $userId"
      }
    }
  }
}

五、附加说明

  1. 需要在 AndroidManifest.xml 添加网络权限:
    <uses-permission android:name="android.permission.INTERNET" />
    
  2. 使用 ProGuard 时需要添加 Firebase 的混淆规则
  3. 完整实现需要处理用户状态持久化(使用 FirebaseAuth.AuthStateListener

以上代码示例展示了完整的 Firebase 集成流程,实际开发中建议结合 ViewModel 和 LiveData 实现更健壮的架构。