<activity android:name="my" android:label="mine">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
android:name="my" 應為完整類名 com.example.manage.MainActivity,否則系統找不到入口,**安裝成功但圖標啟動即結束**(ActivityManager 無法解析組件)。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.manage"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
package com.example.manage;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.util.Map;
public class MainActivity extends Activity implements View.OnClickListener {
private EditText etNumber, etPassword;
private Button btnLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
loadSavedInfo();
}
private void initView() {
etNumber = findViewById(R.id.et_number);
etPassword = findViewById(R.id.et_password);
btnLogin = findViewById(R.id.btn_login);
btnLogin.setOnClickListener(this); // 直接 this,實現了 OnClickListener
}
private void loadSavedInfo() {
Map<String, String> userInfo = Utils.getUserInfo(this);
if (userInfo != null) {
etNumber.setText(userInfo.get("number"));
etPassword.setText(userInfo.get("password"));
}
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_login) {
String number = etNumber.getText().toString().trim();
String password = etPassword.getText().toString();
if (TextUtils.isEmpty(number)) { toast("請輸入賬號"); return; }
if (TextUtils.isEmpty(password)) { toast("請輸入密碼"); return; }
toast("登錄成功");
Log.i("MainActivity", "記住密碼: " + number + ", " + password);
Utils.saveUserInfo(this, number, password);
}
}
private void toast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}
package com.example.manage;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.HashMap;
import java.util.Map;
public class Utils {
private static final String PREFS_NAME = "data";
private static final String KEY_USER = "username";
private static final String KEY_PWD = "pwd";
public static boolean saveUserInfo(Context context, String number, String password) {
SharedPreferences sp = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
sp.edit().putString(KEY_USER, number).putString(KEY_PWD, password).apply();
return true;
}
public static Map<String, String> getUserInfo(Context context) {
SharedPreferences sp = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
String number = sp.getString(KEY_USER, "");
String password = sp.getString(KEY_PWD, "");
if (TextUtils.isEmpty(number) && TextUtils.isEmpty(password)) return null;
Map<String, String> map = new HashMap<>();
map.put("number", number);
map.put("password", password);
return map;
}
}
| 問題 | 修正 |
|---|---|
| Manifest Activity 名稱不全 | android:name=".MainActivity" |
| Utils 類放錯包 | 與 MainActivity 同包 com.example.manage |
| SharedPreferences key 不一致 | 存取統一用 username/pwd |
| OnClickListener 類型轉換錯誤 | Activity 直接 implements View.OnClickListener |
| Map 未泛型化 | Map<String,String> 避免強轉 |
「Manifest 入口類名寫全、SharedPreferences 鍵值對齊、上下文傳 this 不傳 Application」—— Android 登錄頁三大填坑指南。