/* * 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 { /*定义一个名为 NotesPreferenceActivity 的类,继承自 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; /*定义一个 PreferenceCategory 类型的成员变量,用于组织账户相关的偏好设置项*/ private GTaskReceiver mReceiver; /*定义一个 GTaskReceiver 类型的成员变量,用于接收广播*/ private Account[] mOriAccounts; /*定义一个 Account 数组类型的成员变量,用于存储原始账户列表*/ private boolean mHasAddedAccount; /*定义一个布尔类型的成员变量,用于标记是否已经添加过账户*/ @Override protected void onCreate(Bundle icicle) { /*重写 onCreate 方法,当 Activity 被创建时调用*/ super.onCreate(icicle); /*调用父类的 onCreate 方法*/ /* using the app icon for navigation */ getActionBar().setDisplayHomeAsUpEnabled(true); /*获取 ActionBar 并设置返回按钮显示应用图标*/ addPreferencesFromResource(R.xml.preferences); /*从指定的 XML 文件中加载偏好设置*/ mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);/*查找 PreferenceCategory 类型的偏好设置项,并赋值给 mAccountCategory 成员变量*/ mReceiver = new GTaskReceiver(); /*创建 GTaskReceiver 类型的对象*/ IntentFilter filter = new IntentFilter(); /*创建 IntentFilter 对象*/ filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME); /*向 IntentFilter 中添加动作,用于接收特定广播*/ registerReceiver(mReceiver, filter); /*注册 BroadcastReceiver,接收指定的动作广播*/ mOriAccounts = null; /*初始化 mOriAccounts 为空*/ View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null); /*使用 LayoutInflater 加载头部布局*/ getListView().addHeaderView(header, null, true); /*向 ListView 中添加头部视图*/ } @Override protected void onResume() { /*重写 onResume 方法,当 Activity 从不可见变为可见时调用*/ super.onResume(); /*调用父类的 onResume 方法*/ // need to set sync account automatically if user has added a new // account 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() { /*重写 onDestroy 方法,当 Activity 被销毁时调用*/ if (mReceiver != null) { /*检查 mReceiver 是否不为空*/ unregisterReceiver(mReceiver); /*注销广播接收者 mReceiver,防止内存泄漏*/ } super.onDestroy(); /*调用父类的 onDestroy 方法,完成销毁操作*/ } private void loadAccountPreference() { /*定义一个私有方法 loadAccountPreference,用于加载账户偏好设置*/ mAccountCategory.removeAll(); /*清空 mAccountCategory 中的所有子项*/ Preference accountPref = new Preference(this); /*创建一个新的 Preference 对象*/ final String defaultAccount = getSyncAccountName(this); /*获取当前设置的同步账户名字*/ accountPref.setTitle(getString(R.string.preferences_account_title)); /*设置 Preference 的标题*/ accountPref.setSummary(getString(R.string.preferences_account_summary)); /*设置 Preference 的摘要*/ accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { public boolean onPreferenceClick(Preference preference) { /*为 Preference 设置点击监听器*/ if (!GTaskSyncService.isSyncing()) { /*检查同步服务是否正在同步*/ if (TextUtils.isEmpty(defaultAccount)) { /*检查是否已经设置了同步账户*/ // the first time to set account showSelectAccountAlertDialog(); /*如果没有设置同步账户,显示选择账户的对话框*/ } else { // if the account has already been set, we need to promp // user about the risk showChangeAccountConfirmAlertDialog(); /*如果已经设置了同步账户,显示确认更改账户的对话框*/ } } else { Toast.makeText(NotesPreferenceActivity.this, R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT) .show(); /*如果同步服务正在同步,显示一个提示,告知用户不能更改账户*/ } return true; /*返回 true 表示点击事件已处理*/ } }); mAccountCategory.addPreference(accountPref); /*将 Preference 添加到 mAccountCategory 中*/ } private void loadSyncButton() { /*定义一个私有方法 loadSyncButton,用于加载同步按钮和最后同步时间的显示*/ Button syncButton = (Button) findViewById(R.id.preference_sync_button); /*通过 ID 获取同步按钮*/ TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview); /*通过 ID 获取显示最后同步时间的 TextView*/ // set button state 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))); /*设置按钮是否启用,取决于是否设置了同步账户*/ // set last sync time 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))); /*设置 TextView 显示最后同步时间*/ lastSyncTimeView.setVisibility(View.VISIBLE); /*显示 TextView*/ } else { lastSyncTimeView.setVisibility(View.GONE); /*如果没有同步时间,隐藏 TextView*/ } } } private void refreshUI() { /*定义一个私有方法 refreshUI,用于刷新界面*/ loadAccountPreference(); /*/*调用 loadAccountPreference 方法,加载账户偏好设置*/*/ loadSyncButton(); /*调用 loadSyncButton 方法,加载同步按钮和最后同步时间的显示*/ } private void showSelectAccountAlertDialog() { /*定义一个私有方法 showSelectAccountAlertDialog,用于显示选择账户的对话框*/ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); /*创建一个 AlertDialog.Builder 对象*/ View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); /*通过 LayoutInflater 加载自定义的对话框标题视图*/ TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); /*获取标题视图中的 TextView*/ titleTextView.setText(getString(R.string.preferences_dialog_select_account_title)); /*设置标题文本*/ TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); /*获取副标题视图中的 TextView*?*/ subtitleTextView.setText(getString(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]; /*创建一个 CharSequence 数组,用于存储账户名称*/ final CharSequence[] itemMapping = items; /*创建一个最终的 CharSequence 数组,用于映射选择的账户*/ int checkedItem = -1; /*初始化选中的项索引*/ int index = 0; /*初始化索引*/ for (Account account : accounts) { /*遍历账户列表*/ if (TextUtils.equals(account.name, defAccount)) { /*检查当前账户是否为默认账户*/ checkedItem = index; } items[index++] = account.name; /*将账户名称添加到 items 数组中*/ } 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"); /*创建一个意图,打开添加账户的设置页面*/ intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] { "gmail-ls" /*设置意图的额外参数,过滤账户类型*/ }); startActivityForResult(intent, -1); /*启动活动并等待结果*/ dialog.dismiss(); /*关闭对话框*/ } }); } private void showChangeAccountConfirmAlertDialog() { /*定义一个私有方法 showChangeAccountConfirmAlertDialog,用于显示确认更改账户的对话框*/ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); /*创建一个 AlertDialog.Builder 对象*/ View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); /*通过 LayoutInflater 加载自定义的对话框标题视图*/ TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); /*获取标题视图中的 TextView*/ titleTextView.setText(getString(R.string.preferences_dialog_change_account_title, getSyncAccountName(this))); /*设置标题文本,包含当前同步账户的名字*/ TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); /*获取副标题视图中的 TextView*/ subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg)); /*设置副标题文本,警告用户更改账户的风险*/ dialogBuilder.setCustomTitle(titleView); /*设置自定义的对话框标题*/ CharSequence[] menuItemArray = new CharSequence[] { /*创建一个 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(); /*显示对话框*/ } private Account[] getGoogleAccounts() { /*定义一个私有方法 getGoogleAccounts,用于获取设备上的所有 Google 账户*/ AccountManager accountManager = AccountManager.get(this); /*获取 AccountManager 对象*/ return accountManager.getAccountsByType("com.google"); /*返回所有 Google 类型的账户*/ } private void setSyncAccount(String account) { /*定义一个私有方法 setSyncAccount,用于设置同步账户*/ if (!getSyncAccountName(this).equals(account)) { /*检查当前设置的同步账户是否与新账户不同*/ SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); /*获取 SharedPreferences 对象*/ SharedPreferences.Editor editor = settings.edit(); /*获取 SharedPreferences 编辑器*/ if (account != null) { /*如果账户不为空,将其保存到偏好设置中*/ editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account); /*保存账户名字*/ } else { /*如果账户为空,保存空字符串*/ editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); /*保存空字符串*/ } editor.commit(); /*提交编辑*/ // clean up last sync time setLastSyncTime(this, 0); /*清除最后同步时间*/ // clean up local gtask related info 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(); /*创建并启动一个新线程,清除本地与 GTask 相关的信息*/ Toast.makeText(NotesPreferenceActivity.this, getString(R.string.preferences_toast_success_set_accout, account), Toast.LENGTH_SHORT).show(); /*显示一个提示,告知用户成功设置了账户*/ } } private void removeSyncAccount() { /*定义一个私有方法 removeSyncAccount,用于移除同步账户*/ SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); /*获取 SharedPreferences 对象*/ SharedPreferences.Editor editor = settings.edit(); /*获取 SharedPreferences 编辑器*/ 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(); /*提交编辑*/ // clean up local gtask related info new Thread(new Runnable() { /*创建并启动一个新线程,清除本地与 GTask 相关的信息*/ public void run() { ContentValues values = new ContentValues(); /*创建 ContentValues 对象*/ values.put(NoteColumns.GTASK_ID, ""); /*设置 GTASK_ID 为空*/ values.put(NoteColumns.SYNC_ID, 0); /*设置 SYNC_ID 为 0*/ getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); /*更新数据库中的相关记录*/ } }).start(); } public static String getSyncAccountName(Context context) { /*定义一个静态方法 getSyncAccountName,用于获取同步账户名字*/ SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); /*获取 SharedPreferences 对象*/ return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); /*返回同步账户名字,如果没有设置则返回空字符串*/ } public static void setLastSyncTime(Context context, long time) { /*定义一个静态方法 setLastSyncTime,用于设置最后同步时间*/ SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); /*获取 SharedPreferences 对象*/ SharedPreferences.Editor editor = settings.edit(); /*获取 SharedPreferences 编辑器*/ editor.putLong(PREFERENCE_LAST_SYNC_TIME, time); /*保存最后同步时间*/ editor.commit(); /*提交编辑*/ } public static long getLastSyncTime(Context context) { /*定义一个静态方法 getLastSyncTime,用于获取最后同步时间*/ SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); /*获取 SharedPreferences 对象*/ return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0); /*返回最后同步时间,如果没有设置则返回 0*/ } private class GTaskReceiver extends BroadcastReceiver { /*定义一个内部类 GTaskReceiver,继承自 BroadcastReceiver*/ @Override public void onReceive(Context context, Intent intent) { /*重写 onReceive 方法,当接收到广播时调用*/ refreshUI(); /*刷新界面*/ if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) { /*检查广播是否表示正在同步*/ TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview); /*获取显示同步状态的 TextView*/ syncStatus.setText(intent .getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG)); /*设置 TextView 显示同步进度*/ } } } public boolean onOptionsItemSelected(MenuItem item) { /*重写 onOptionsItemSelected 方法,处理选项菜单项的点击事件*/ switch (item.getItemId()) { /*根据菜单项的 ID 进行处理*/ case android.R.id.home: /*处理 Home 按钮的点击事件*/ Intent intent = new Intent(this, NotesListActivity.class); /*创建一个意图,跳转到 NotesListActivity*/ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); /*添加标志,确保活动栈中的其他活动被清除*/ startActivity(intent); /*启动活动*/ return true; /*返回 true 表示事件已处理*/ default: /*默认情况下返回 false*/ return false; } } }