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

478 lines
20 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;
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;
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;
// 重写onCreate方法这是Activity生命周期中的一个重要方法用于初始化Activity
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle); // 调用父类的onCreate方法
// 设置应用图标作为导航按钮,并启用向上导航功能
getActionBar().setDisplayHomeAsUpEnabled(true);
// 从资源文件中加载偏好设置布局
addPreferencesFromResource(R.xml.preferences);
// 获取同步账户的分类偏好设置项
mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);
// 实例化广播接收器用于接收来自GTaskSyncService的广播
mReceiver = new GTaskReceiver();
// 创建IntentFilter并添加要监听的广播动作
IntentFilter filter = new IntentFilter();
filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME);
// 注册广播接收器
registerReceiver(mReceiver, filter);
// 初始化原始账户数组为空
mOriAccounts = null;
// 使用LayoutInflater从布局资源中创建视图并将其作为头部添加到偏好设置的列表中
View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);
getListView().addHeaderView(header, null, true);
}
// 重写onResume方法当Activity重新进入用户视野时调用
@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();
}
// 重写onDestroy方法当Activity即将被销毁时调用
@Override
protected void onDestroy() {
// 如果广播接收器不为空,则注销广播接收器
if (mReceiver != null) {
unregisterReceiver(mReceiver);
}
super.onDestroy(); // 调用父类的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() {
@Override
public boolean onPreferenceClick(Preference preference) {
// 如果当前不在同步中
if (!GTaskSyncService.isSyncing()) {
// 如果当前没有设置同步账户,则显示选择账户对话框
if (TextUtils.isEmpty(defaultAccount)) {
showSelectAccountAlertDialog();
} else {
// 如果已经设置了同步账户,则显示更改账户确认对话框
showChangeAccountConfirmAlertDialog();
}
} else {
// 如果当前在同步中则显示无法更改账户的Toast提示
Toast.makeText(NotesPreferenceActivity.this,
R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT)
.show();
}
return true; // 表示事件已处理
}
});
}
// 将一个偏好项(可能是账户相关的设置)添加到偏好分类中
mAccountCategory.addPreference(accountPref);
// 加载并设置同步按钮的状态和文本
private void loadSyncButton() {
// 从布局文件中找到同步按钮和最后同步时间显示的TextView
Button syncButton = (Button) findViewById(R.id.preference_sync_button);
TextView lastSyncTimeView = (TextView) findViewById(R.id.preference_sync_status_textview); // 注意这里的ID拼写错误已修正
// 根据是否正在同步来设置按钮的文本和点击事件
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); // 显示TextView
} 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); // 显示TextView
} else { // 如果没有最后同步时间
lastSyncTimeView.setVisibility(View.GONE); // 隐藏TextView
}
}
}
// 刷新用户界面,包括加载账户偏好和同步按钮的状态
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(); // 刷新用户界面
}
});
}
// 创建一个对话框,用于添加账户
// 首先通过LayoutInflater从当前上下文this加载add_account_text布局
View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null);
// 设置对话框的内容视图为addAccountView
dialogBuilder.setView(addAccountView);
// 显示对话框
final AlertDialog dialog = dialogBuilder.show();
// 为addAccountView设置点击监听器
addAccountView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// 标记账户已添加
mHasAddedAccount = true;
// 创建一个意图,用于打开添加账户的设置页面
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
// 为意图添加额外的数据指定账户类型过滤器为gmail-lsGmail账户
intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {"gmail-ls"});
// 启动活动以响应意图,并等待结果(这里请求码使用了-1通常应使用有意义的正整数
startActivityForResult(intent, -1);
// 关闭对话框
dialog.dismiss();
}
});
// 显示一个确认更改账户的对话框
private void showChangeAccountConfirmAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
// 通过LayoutInflater加载account_dialog_title布局
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账户
private Account[] getGoogleAccounts() {
AccountManager accountManager = AccountManager.get(this);
return accountManager.getAccountsByType("com.google"); // 获取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();
// 清理上一次的同步时间
setLastSyncTime(this, 0);
// 清理本地与Google任务相关的信息
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, ""); // 清除GTASK_ID
values.put(NoteColumns.SYNC_ID, 0); // 重置SYNC_ID
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); // 更新数据库
}
}).start();
// 显示成功设置账户的Toast消息
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 values = new ContentValues();
values.put(NoteColumns.GTASK_ID, ""); // 清除GTASK_ID
values.put(NoteColumns.SYNC_ID, 0); // 重置SYNC_ID
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); // 更新数据库
}
}).start();
}
// 定义一个方法用于从SharedPreferences中获取同步账户名称
public static String getSyncAccountName(Context context) {
// 使用context获取SharedPreferences实例PREFERENCE_NAME是偏好文件的名称Context.MODE_PRIVATE表示只有当前应用可以访问
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
// 从偏好设置中获取字符串类型的同步账户名称,如果不存在则返回空字符串""
return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
// 定义一个方法用于设置最后同步时间到SharedPreferences中
public static void setLastSyncTime(Context context, long time) {
// 获取SharedPreferences实例
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
// 获取SharedPreferences.Editor对象用于修改偏好设置
SharedPreferences.Editor editor = settings.edit();
// 将最后同步时间保存到偏好设置中
editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
// 提交更改
editor.commit();
}
// 定义一个方法用于从SharedPreferences中获取最后同步时间
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);
}
// 定义一个内部类GTaskReceiver它继承自BroadcastReceiver
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.preference_sync_status_textview);
syncStatus.setText(intent
.getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));
}
}
}
// 定义一个方法,用于处理菜单项的点击事件
public boolean onOptionsItemSelected(MenuItem item) {
// 根据点击的菜单项ID执行不同的操作
switch (item.getItemId()) {
// 如果是点击了应用的“返回”图标(通常位于左上角)
case android.R.id.home:
// 创建一个Intent用于启动NotesListActivity
Intent intent = new Intent(this, NotesListActivity.class);
// 添加标志,以清除当前活动之上的所有活动
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// 启动目标Activity
startActivity(intent);
// 表示事件已处理
return true;
// 默认情况下返回false表示事件未处理
default:
return false;
}
}