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.
xiaomi-Notes/NotesPreferenceActivity.java

568 lines
22 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.
*/
package net.micode.notes.ui;
// 导入与账户相关的类,用于账户管理和认证
import android.accounts.Account;
import android.accounts.AccountManager;
// 导入用于操作 Android 应用中的 ActionBar顶部导航栏功能
import android.app.ActionBar;
// 导入用于显示和管理弹出对话框的类
import android.app.AlertDialog;
// 导入用于接收广播消息的类
import android.content.BroadcastReceiver;
// 导入用于在 ContentProvider 中存储和插入数据的类
import android.content.ContentValues;
// 导入 Android 应用的上下文类,用于访问全局应用信息和资源
import android.content.Context;
// 导入用于显示和管理对话框按钮点击事件的接口
import android.content.DialogInterface;
// 导入用于启动新活动或广播的 Intent 类
import android.content.Intent;
// 导入用于过滤广播消息的 IntentFilter 类
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;
// 导入常用的 UI 控件类,如按钮、文本视图和弹出提示框
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;
// 导入与 Google 任务同步服务相关的类,用于同步任务数据
import net.micode.notes.gtask.remote.GTaskSyncService;
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";
// 私有常量,存储同步账户的键
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);
// 使用应用图标作为导航栏的“向上”按钮
getActionBar().setDisplayHomeAsUpEnabled(true);
// 加载偏好设置界面资源
addPreferencesFromResource(R.xml.preferences);
// 获取账户设置类别对象
mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);
// 初始化 GTaskReceiver 接收器,用于接收同步相关广播
mReceiver = new GTaskReceiver();
// 创建 IntentFilter注册 GTaskSyncService 广播
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) {
// 获取当前所有的 Google 账户
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();
}
@Override
protected void onDestroy() {
// 如果 mReceiver 已初始化,则注销广播接收器,防止内存泄漏
if (mReceiver != null) {
unregisterReceiver(mReceiver);
}
// 调用父类的 onDestroy确保正确销毁 Activity
super.onDestroy();
}
private void loadAccountPreference() {
// 清空当前账户类别中的所有项
mAccountCategory.removeAll();
// 创建一个新的 Preference 用于账户设置
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) {
// 选择账户后,设置同步账户,并刷新 UI
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");
intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] { "gmail-ls" });
startActivityForResult(intent, -1); // 启动账户添加页面
dialog.dismiss(); // 关闭当前对话框
}
});
}
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");
intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {
"gmail-ls"
});
startActivityForResult(intent, -1);
dialog.dismiss();
}
});
private void showChangeAccountConfirmAlertDialog() {
// 创建一个 AlertDialog.Builder 实例,用于构建弹出的确认对话框
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(); // 刷新 UI更新界面
}
}
});
// 显示对话框
dialogBuilder.show();
}
// 获取所有Google账户
private Account[] getGoogleAccounts() {
// 获取 AccountManager 实例,这个对象用来管理设备上的账户
AccountManager accountManager = AccountManager.get(this);
// 返回所有Google账户"com.google" 表示Google账户类型
return accountManager.getAccountsByType("com.google");
}
// 设置同步账户
private void setSyncAccount(String account) {
// 如果新设置的账户与当前同步账户不同
if (!getSyncAccountName(this).equals(account)) {
// 获取 SharedPreferences用于保存同步账户的配置信息
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();
// 清除上次同步时间将其设置为0
setLastSyncTime(this, 0);
// 清除与Google任务相关的本地信息
new Thread(new Runnable() {
public void run() {
// 创建一个 ContentValues 对象来更新 Google 任务相关的字段
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, ""); // 清除任务ID
values.put(NoteColumns.SYNC_ID, 0); // 清除同步ID
// 更新 Notes 内容提供者中的数据,清除与同步相关的信息
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删除同步账户设置
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();
// 清除与Google任务相关的本地信息
new Thread(new Runnable() {
public void run() {
// 创建一个 ContentValues 对象来更新 Google 任务相关的字段
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, ""); // 清除任务ID
values.put(NoteColumns.SYNC_ID, 0); // 清除同步ID
// 更新 Notes 内容提供者中的数据,清除与同步相关的信息
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
}
// 获取同步账户名称
public static String getSyncAccountName(Context context) {
// 获取 SharedPreferences 实例,存储同步账户名称
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
// 返回同步账户名称,如果没有保存该名称,返回空字符串
return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
// 设置上次同步时间
public static void setLastSyncTime(Context context, long time) {
// 获取 SharedPreferences 实例,存储同步信息
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
// 获取 SharedPreferences 的编辑器,用于修改存储的数据
SharedPreferences.Editor editor = settings.edit();
// 将时间值存储到 PREFERENCE_LAST_SYNC_TIME 键中
editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
// 提交更改
editor.commit();
}
// 获取上次同步时间
public static long getLastSyncTime(Context context) {
// 获取 SharedPreferences 实例,读取同步信息
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
// 获取上次同步时间,如果没有保存则返回 0表示没有同步
return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
}
// 广播接收器,用于接收来自 GTaskSyncService 的广播消息
private class GTaskReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 刷新UI显示
refreshUI();
// 检查是否正在同步
if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) {
// 获取同步状态显示的 TextView
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()) {
// 点击返回按钮,返回到 NotesListActivity
case android.R.id.home:
// 创建返回 Intent设置标志位清除栈顶活动
Intent intent = new Intent(this, NotesListActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// 启动 NotesListActivity
startActivity(intent);
return true;
default:
// 如果没有匹配的菜单项,返回 false
return false;
}
}
}