You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MiNote/ui/NotesPreferenceActivity.java

442 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 版权所有 (c) 2010-2011The MiCode 开源社区 (www.micode.net)
*
* 本软件根据 Apache 许可证 2.0 版("许可证")发布;
* 除非符合许可证,否则不得使用此文件。
* 您可以在以下网址获取许可证副本:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 除非法律要求或书面同意,软件
* 根据许可证分发的内容按"原样"提供,
* 不附带任何明示或暗示的保证或条件。
* 请参阅许可证,了解有关权限和限制的具体语言。
*/
package net.micode.notes.ui;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.ActionBar;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.remote.GTaskSyncService;
/**
* 笔记应用的设置界面Activity
* 主要功能:
* 1. 管理同步账户Google账户
* 2. 触发数据同步操作
* 3. 显示同步状态和最后同步时间
* 4. 处理账户切换/删除逻辑
*/
public class NotesPreferenceActivity extends PreferenceActivity {
// 偏好设置文件名
public static final String PREFERENCE_NAME = "notes_preferences";
// 存储同步账户名的偏好键
public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name";
// 存储最后同步时间的偏好键
public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time";
// 存储背景颜色随机显示的偏好键(未在代码中使用,可能为遗留字段)
public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear";
// 账户管理类别在XML中的键内部使用
private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key";
// 账户过滤参数键(用于添加账户时的意图)
private static final String AUTHORITIES_FILTER_KEY = "authorities";
// 账户管理类别视图
private PreferenceCategory mAccountCategory;
// 同步服务广播接收器
private GTaskReceiver mReceiver;
// 原始账户列表(用于检测新增账户)
private Account[] mOriAccounts;
// 标记是否新增了账户
private boolean mHasAddedAccount;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
// 设置ActionBar导航图标返回按钮
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true); // 启用返回按钮
// 加载设置界面布局来自XML资源
addPreferencesFromResource(R.xml.preferences);
// 获取账户管理类别
mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);
// 初始化广播接收器,监听同步服务状态
mReceiver = new GTaskReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME); // 监听同步服务广播
registerReceiver(mReceiver, filter);
mOriAccounts = null; // 初始化原始账户列表
// 添加设置界面头部视图
View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);
getListView().addHeaderView(header, null, true); // 将头部添加到列表视图
}
@Override
protected void onResume() {
super.onResume();
// 自动设置同步账户(如果有新账户添加)
if (mHasAddedAccount) {
Account[] accounts = getGoogleAccounts(); // 获取所有Google账户
// 检测是否有新账户添加(账户数量增加)
if (mOriAccounts != null && accounts.length > mOriAccounts.length) {
for (Account accountNew : accounts) {
boolean found = false;
// 检查是否为已存在的账户
for (Account accountOld : mOriAccounts) {
if (TextUtils.equals(accountOld.name, accountNew.name)) {
found = true;
break;
}
}
if (!found) { // 发现新账户,自动设置为同步账户
setSyncAccount(accountNew.name);
break;
}
}
}
}
refreshUI(); // 刷新界面显示
}
@Override
protected void onDestroy() {
if (mReceiver != null) {
unregisterReceiver(mReceiver); // 注销广播接收器
}
super.onDestroy();
}
/**
* 加载账户管理偏好项
*/
private void loadAccountPreference() {
mAccountCategory.removeAll(); // 清空现有偏好项
// 创建账户选择偏好项
Preference accountPref = new Preference(this);
String defaultAccount = getSyncAccountName(this); // 获取当前同步账户
accountPref.setTitle(R.string.preferences_account_title); // 设置标题
accountPref.setSummary(R.string.preferences_account_summary); // 设置摘要
// 点击事件处理:选择/更改同步账户
accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
if (!GTaskSyncService.isSyncing()) { // 非同步状态才能修改账户
if (TextUtils.isEmpty(defaultAccount)) { // 首次设置账户
showSelectAccountAlertDialog(); // 显示账户选择对话框
} else { // 已设置账户,提示更改风险
showChangeAccountConfirmAlertDialog(); // 显示更改确认对话框
}
} else { // 同步中,提示无法更改
Toast.makeText(NotesPreferenceActivity.this,
R.string.preferences_toast_cannot_change_account,
Toast.LENGTH_SHORT).show();
}
return true;
}
});
mAccountCategory.addPreference(accountPref); // 添加到账户类别
}
/**
* 加载同步按钮和状态
*/
private void loadSyncButton() {
Button syncButton = (Button) findViewById(R.id.preference_sync_button);
TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
// 设置按钮状态
if (GTaskSyncService.isSyncing()) { // 同步中
syncButton.setText(R.string.preferences_button_sync_cancel); // 显示取消按钮
syncButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
GTaskSyncService.cancelSync(NotesPreferenceActivity.this); // 取消同步
}
});
} else { // 非同步状态
syncButton.setText(R.string.preferences_button_sync_immediately); // 显示立即同步按钮
syncButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
GTaskSyncService.startSync(NotesPreferenceActivity.this); // 启动同步
}
});
}
// 按钮可用性:必须有同步账户才能操作
syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this)));
// 设置最后同步时间
if (GTaskSyncService.isSyncing()) { // 同步中显示进度
lastSyncTimeView.setText(GTaskSyncService.getProgressString());
lastSyncTimeView.setVisibility(View.VISIBLE);
} else { // 显示最后同步时间或隐藏
long lastSyncTime = getLastSyncTime(this);
if (lastSyncTime != 0) {
// 格式化时间显示
lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time,
DateFormat.format(getString(R.string.preferences_last_sync_time_format),
lastSyncTime)));
lastSyncTimeView.setVisibility(View.VISIBLE);
} else {
lastSyncTimeView.setVisibility(View.GONE);
}
}
}
/**
* 刷新界面显示(账户和同步状态)
*/
private void refreshUI() {
loadAccountPreference(); // 刷新账户偏好项
loadSyncButton(); // 刷新同步按钮状态
}
/**
* 显示选择账户对话框(首次设置或更改时)
*/
private void showSelectAccountAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
// 自定义对话框标题
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(R.string.preferences_dialog_select_account_title); // 设置标题
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(R.string.preferences_dialog_select_account_tips); // 设置提示语
dialogBuilder.setCustomTitle(titleView); // 设置自定义标题
dialogBuilder.setPositiveButton(null, null); // 移除默认按钮
Account[] accounts = getGoogleAccounts(); // 获取所有Google账户
String defAccount = getSyncAccountName(this); // 当前账户
mOriAccounts = accounts; // 保存原始账户列表
mHasAddedAccount = false; // 初始化新增标记
if (accounts.length > 0) {
// 构建账户列表选项
CharSequence[] items = new CharSequence[accounts.length];
int checkedItem = -1; // 选中项索引
int index = 0;
for (Account account : accounts) {
items[index] = account.name; // 填充账户名
if (TextUtils.equals(account.name, defAccount)) {
checkedItem = index; // 标记当前账户为选中
}
index++;
}
// 设置单选列表
dialogBuilder.setSingleChoiceItems(items, checkedItem,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
setSyncAccount(items[which].toString()); // 设置选中账户
dialog.dismiss(); // 关闭对话框
refreshUI(); // 刷新界面
}
});
}
// 添加"添加账户"自定义视图
View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null);
dialogBuilder.setView(addAccountView); // 将视图添加到对话框
final AlertDialog dialog = dialogBuilder.show();
// 点击"添加账户"视图时的处理
addAccountView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mHasAddedAccount = true; // 标记新增账户操作
// 跳转到系统添加账户界面过滤Google账户类型
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {"gmail-ls"});
startActivityForResult(intent, -1); // 启动添加账户页面
dialog.dismiss(); // 关闭当前对话框
}
});
}
/**
* 显示更改账户确认对话框(提示数据同步风险)
*/
private void showChangeAccountConfirmAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
// 自定义对话框标题(显示当前账户名)
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(getString(R.string.preferences_dialog_change_account_title,
getSyncAccountName(this))); // 标题包含当前账户名
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(R.string.preferences_dialog_change_account_warn_msg); // 警告信息
dialogBuilder.setCustomTitle(titleView); // 设置自定义标题
// 对话框选项:更改账户、移除账户、取消
CharSequence[] menuItemArray = new CharSequence[] {
getString(R.string.preferences_menu_change_account),
getString(R.string.preferences_menu_remove_account),
getString(R.string.preferences_menu_cancel)
};
dialogBuilder.setItems(menuItemArray, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == 0) { // 选择更改账户
showSelectAccountAlertDialog(); // 显示账户选择对话框
} else if (which == 1) { // 选择移除账户
removeSyncAccount(); // 移除当前账户
refreshUI(); // 刷新界面
}
}
});
dialogBuilder.show(); // 显示对话框
}
/**
* 获取所有Google账户账户类型为com.google
* @return Google账户数组
*/
private Account[] getGoogleAccounts() {
AccountManager accountManager = AccountManager.get(this);
return accountManager.getAccountsByType("com.google"); // 获取指定类型账户
}
/**
* 设置同步账户
* @param account 账户名(可为空)
*/
private void setSyncAccount(String account) {
if (!getSyncAccountName(this).equals(account)) { // 仅在账户变更时处理
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account); // 存储账户名
editor.commit(); // 提交更改
// 重置最后同步时间
setLastSyncTime(this, 0);
// 异步清理本地GTask相关数据在新线程中执行
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, ""); // 清空GTask ID
values.put(NoteColumns.SYNC_ID, 0); // 重置同步ID
// 更新所有笔记的同步状态
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
// 提示设置成功
Toast.makeText(NotesPreferenceActivity.this,
getString(R.string.preferences_toast_success_set_accout, account),
Toast.LENGTH_SHORT).show();
}
}
/**
* 移除当前同步账户
*/
private void removeSyncAccount() {
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
// 移除账户名和最后同步时间
if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) {
editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);
}
if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) {
editor.remove(PREFERENCE_LAST_SYNC_TIME);
}
editor.commit(); // 提交更改
// 异步清理本地GTask相关数据同设置账户逻辑
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, "");
values.put(NoteColumns.SYNC_ID, 0);
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
}
// ====================== 静态工具方法 ======================
/**
* 获取当前同步账户名
* @param context 上下文
* @return 账户名(空字符串表示未设置)
*/
public static String getSyncAccountName(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE);
return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
/**
* 设置最后同步时间
* @param context 上下文
* @param time 时间戳(毫秒)
*/
public static void setLastSyncTime(Context context, long time) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE);
settings.edit().putLong(PREFERENCE_LAST_SYNC_TIME, time).commit();
}
/**
* 获取最后同步时间
* @param context 上下文
* @return 时间戳0表示未同步过
*/
public static long getLastSyncTime(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE);
return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
}
// ====================== 广播接收器 ======================
/**
* 监听同步服务状态变化的广播接收器
*/
private class GTaskReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
refreshUI(); // 刷新界面显示
// 处理同步进度更新
if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) {