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.
git/java/net/micode/notes/ui/NotesPreferenceActivity.java

584 lines
23 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.

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// NotesPreferenceActivity.java - 便签设置Activity
// 主要功能管理应用的偏好设置特别是Google Tasks同步账户管理
package net.micode.notes.ui;
// ======================= 导入区域 =======================
// Android账户管理
import android.accounts.Account; // 账户对象
import android.accounts.AccountManager; // 账户管理器
// Android界面
import android.app.ActionBar; // 操作栏
import android.app.AlertDialog; // 警告对话框
// Android广播
import android.content.BroadcastReceiver; // 广播接收器
// Android数据
import android.content.ContentValues; // 内容值
// Android基础
import android.content.Context; // 上下文
import android.content.DialogInterface; // 对话框接口
import android.content.Intent; // 意图
import android.content.IntentFilter; // 意图过滤器
import android.content.SharedPreferences; // 偏好设置
import android.os.Bundle; // 状态保存
// Android偏好设置
import android.preference.Preference; // 偏好设置项
import android.preference.Preference.OnPreferenceClickListener; // 偏好设置点击监听
import android.preference.PreferenceActivity; // 偏好设置Activity基类
import android.preference.PreferenceCategory; // 偏好设置分类
import android.preference.PreferenceManager; // 偏好设置管理器
// Android工具
import android.text.TextUtils; // 文本工具
import android.text.format.DateFormat; // 日期格式化
// Android视图
import android.view.LayoutInflater; // 布局加载器
import android.view.Menu; // 菜单
import android.view.MenuItem; // 菜单项
import android.view.View; // 视图基类
import android.widget.ListView; // 列表视图
// Android控件
import android.widget.Button; // 按钮
import android.widget.TextView; // 文本视图
import android.widget.Toast; // 提示信息
// 应用内部资源
import net.micode.notes.R; // 资源文件R类
// 应用数据模型
import net.micode.notes.data.Notes; // Notes主类
import net.micode.notes.data.Notes.NoteColumns; // 便签表列定义
// 应用同步服务
import net.micode.notes.gtask.remote.GTaskSyncService; // Google任务同步服务
// 应用工具
import net.micode.notes.tool.SearchHistoryManager; // 搜索历史管理器
// ======================= 便签设置Activity =======================
/**
* NotesPreferenceActivity - 便签设置Activity
* 继承自PreferenceActivity管理应用的所有偏好设置
* 核心功能Google Tasks同步账户管理、同步控制、设置管理
*/
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;
/** Google Tasks同步广播接收器 - 监听同步状态变化 */
private GTaskReceiver mReceiver;
/** 原始账户列表 - 用于检测新添加的账户 */
private Account[] mOriAccounts;
/** 是否添加了新账户标志 - 标记用户是否添加了新账户 */
private boolean mHasAddedAccount;
// ======================= 生命周期方法 =======================
/**
* onCreate - Activity创建
* 初始化设置界面
* @param icicle 保存的状态
*/
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
// 从XML加载偏好设置
addPreferencesFromResource(R.xml.preferences);
// 获取账户设置分类
mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);
// 设置清除搜索历史按钮的点击事件
Preference clearSearchHistoryPref = findPreference("pref_key_clear_search_history");
if (clearSearchHistoryPref != null) {
clearSearchHistoryPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
// 清除搜索历史
SearchHistoryManager.getInstance(NotesPreferenceActivity.this).clearSearchHistory();
Toast.makeText(NotesPreferenceActivity.this,
"Search history cleared", Toast.LENGTH_SHORT).show();
return true;
}
});
}
// 创建并注册同步广播接收器
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);
ListView listView = getListView();
if (listView != null) {
listView.addHeaderView(header, null, true);
}
/* 使用应用图标作为导航按钮 */
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
/**
* onResume - Activity恢复可见
* 检测新添加的账户并自动设置
*/
@Override
protected void onResume() {
super.onResume();
// 如果用户添加了新账户,需要自动设置为同步账户
if (mHasAddedAccount) {
Account[] accounts = getGoogleAccounts();
// 比较新旧账户数量,检测新账户
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(); // 刷新界面
}
/**
* onDestroy - Activity销毁
* 注销广播接收器
*/
@Override
protected void onDestroy() {
if (mReceiver != null) {
unregisterReceiver(mReceiver);
}
super.onDestroy();
}
// ======================= 账户偏好设置加载 =======================
/**
* 加载账户偏好设置
* 动态创建账户设置项
*/
private void loadAccountPreference() {
mAccountCategory.removeAll(); // 清空现有设置项
// 创建账户设置项
Preference accountPref = new Preference(this);
final String defaultAccount = getSyncAccountName(this);
accountPref.setTitle(getString(R.string.preferences_account_title));
accountPref.setSummary(getString(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(getString(R.string.preferences_button_sync_cancel));
syncButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
GTaskSyncService.cancelSync(NotesPreferenceActivity.this);
}
});
} else {
// 未同步:显示立即同步按钮
syncButton.setText(getString(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(getString(R.string.preferences_dialog_select_account_title));
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));
dialogBuilder.setCustomTitle(titleView);
dialogBuilder.setPositiveButton(null, null); // 不显示确定按钮
// 获取Google账户列表
Account[] accounts = getGoogleAccounts();
String defAccount = getSyncAccountName(this);
// 保存原始账户列表,用于检测新账户
mOriAccounts = accounts;
mHasAddedAccount = false;
if (accounts.length > 0) {
// 创建账户列表项
CharSequence[] items = new CharSequence[accounts.length];
final CharSequence[] itemMapping = items; // 用于内部类访问
int checkedItem = -1; // 默认未选中
// 填充账户列表
int index = 0;
for (Account account : accounts) {
if (TextUtils.equals(account.name, defAccount)) {
checkedItem = index; // 选中已设置的账户
}
items[index++] = account.name;
}
// 设置单选列表
dialogBuilder.setSingleChoiceItems(items, checkedItem,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 选择账户
setSyncAccount(itemMapping[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; // 标记为添加账户
// 启动系统添加账户界面
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
// 只显示Gmail账户类型
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(getString(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账户 =======================
/**
* 获取设备上的Google账户
* @return Google账户数组
*/
private Account[] getGoogleAccounts() {
AccountManager accountManager = AccountManager.get(this);
// 获取类型为"com.google"的账户Google账户
return accountManager.getAccountsByType("com.google");
}
// ======================= 设置同步账户 =======================
/**
* 设置同步账户
* 保存账户名到偏好设置,并清理同步相关数据
* @param account 账户名
*/
private void setSyncAccount(String account) {
if (!getSyncAccountName(this).equals(account)) {
// 保存到偏好设置
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
if (account != null) {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account);
} else {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
editor.commit();
// 清理最后同步时间
setLastSyncTime(this, 0);
// 清理本地同步相关数据(在后台线程执行)
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, Context.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();
// 清理本地同步相关数据(在后台线程执行)
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();
}
// ======================= 静态工具方法 =======================
/**
* 获取同步账户名
* 静态方法,供其他类调用
* @param context 上下文
* @return 同步账户名,无账户时返回空字符串
*/
public static String getSyncAccountName(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.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,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
editor.commit();
}
/**
* 获取最后同步时间
* 静态方法,供其他类调用
* @param context 上下文
* @return 最后同步时间戳从未同步返回0
*/
public static long getLastSyncTime(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
}
// ======================= 同步广播接收器 =======================
/**
* GTaskReceiver - Google Tasks同步广播接收器
* 监听同步状态变化
*/
private class GTaskReceiver extends BroadcastReceiver {
/**
* 接收广播
* 处理同步状态变化
*/
@Override
public void onReceive(Context context, Intent intent) {
refreshUI(); // 刷新界面
// 如果正在同步,更新进度信息
if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) {
TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
syncStatus.setText(intent
.getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));
}
}
}
// ======================= 菜单项处理 =======================
/**
* 选项菜单项选择处理
* 处理返回按钮点击
*/
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// 返回按钮:回到主界面
Intent intent = new Intent(this, NotesListActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return false;
}
}
}