Compare commits

...

29 Commits

Author SHA1 Message Date
LZ e1fe6a2ad7 这个XML文件定义了应用的多个方面,包括它需要的权限、它包含的组件(如活动和接收器)以及这些组件如何响应不同的动作和数据类型。
2 months ago
LZ 292ce745da 这个类是一个Android服务(Service),用于在后台执行同步任务。它提供了开始同步、取消同步、检查同步状态以及获取同步进度信息的功能。通过广播(Broadcast)机制,它可以与其他组件(如Activity)进行通信,以报告同步的进度和状态。
2 months ago
LZ 4a56e512df 这个类是一个自定义的异常类,用于表示网络操作失败的情况。通过提供不同的构造函数,它允许在抛出异常时传递详细的错误信息和原始异常(如果有的话)。
2 months ago
LZ 6973689e92 ActionFailureException类是一个功能齐全、易于使用的自定义异常类,它可以帮助开发者更好地处理和管理操作失败的情况。
2 months ago
LZ 72c7335b8b 这段代码定义了一个名为Node的抽象类,它用于表示一个可以同步的节点,如任务或笔记等。类中定义了一些同步操作类型的常量、一些用于表示节点状态的私有成员变量、一个构造方法、以及多个抽象方法和用于设置/获取节点状态的方法。这个类需要被其他类继承并实现其抽象方法,以完成具体的同步逻辑。
2 months ago
LZ cd33eef829 这段代码定义了一个MetaData类,它继承自Task类。MetaData类用于处理与Google Tasks相关的元数据,包括设置和获取与元数据相关的Gid(可能是Google Tasks中的任务ID),以及根据JSON对象设置和获取MetaData的内容。代码中还包括了一些不应该被调用的方法,这些方法通过抛出IllegalAccessError异常来表明它们不应该在MetaData类的上下文中被使用。
2 months ago
LZ 192b3e97b2 这段代码主要定义了一个名为GTaskStringUtils的类,其中包含了许多与Google Tasks(谷歌任务)和MIUI笔记相关的常量,这些常量主要用于处理JSON数据中的键名。通过定义这些常量,代码的可读性和可维护性得到了提高。
2 months ago
LZ 6f2ded25f6 ResourceParser类是一个资源管理器,它封装了与笔记应用相关的各种资源(如颜色、字体大小、背景图片等)的访问逻辑,使得在应用的其他部分可以更方便地获取和使用这些资源。此外,它还考虑了用户的偏好设置,能够根据用户的设置来调整资源的使用。
2 months ago
LZ 2dfbe8a5ba 这段代码定义了一个名为ResourceParser的类,用于管理和解析应用中的资源,如背景颜色、文本大小和背景图像等。
2 months ago
LZ 185ab7bd99 提交小米便签开源代码的质量分析报告。
2 months ago
LZ 44ab3e7551 这段代码定义了一个用于显示文件夹列表的适配器FoldersListAdapter,它继承自CursorAdapter,用于将数据库中的文件夹数据绑定到UI视图上。
2 months ago
LZ 9998ea2ad6 这段代码定义了一个名为DropdownMenu的类,用于在Android应用中创建一个具有下拉功能的菜单。它允许你通过指定的按钮触发一个包含多个菜单项的弹出菜单。你可以设置按钮的背景、标题,以及为菜单项设置点击事件监听器。
2 months ago
LZ 98a83530e1 这段代码定义了一个自定义的DateTimePickerDialog类,它继承自AlertDialog并实现了OnClickListener接口。这个对话框允许用户选择一个日期和时间,并提供了24小时制和12小时制的显示选项。用户选择完成后,可以通过设置的回调接口OnDateTimeSetListener获取选择的日期和时间。
2 months ago
LZ 95b20e5d05 DateTimePickerDialog是一个自定义的对话框,用于选择日期和时间。它继承自AlertDialog,并内部使用DateTimePicker来选择日期和时间。用户可以通过界面选择日期和时间,选择完成后,如果设置了回调监听器(OnDateTimeSetListener),则会回调其OnDateTimeSet方法,传递选择的日期和时间(长整型)。此外,对话框的标题会根据用户选择的日期和时间实时更新,同时支持24小时制和12小时制的切换。
2 months ago
LZ c01900846b 这个AlarmReceiver类是一个广播接收器,用于接收广播消息。当接收到广播时,它会启动一个新的Activity(AlarmAlertActivity),作为一个新的任务。这通常用于在特定事件(如闹钟响起)发生时通知用户。
2 months ago
LZ ed80fbc9a9 AlarmInitReceiver是一个BroadcastReceiver,用于初始化闹钟。当接收到广播时,它会查询数据库中所有未提醒且类型为笔记的记录。对于每条记录,它会创建一个PendingIntent,并设置一个闹钟,在记录的提醒日期时唤醒AlarmReceiver。这样,当到达提醒日期时,应用可以通过AlarmReceiver执行相应的提醒操作。
2 months ago
LZ 8335f7ce07 AlarmAlertActivity是一个Android Activity,用于在特定条件下(如笔记达到提醒时间)弹出一个对话框,显示笔记的摘要信息,并播放一个闹钟声音。它具备以下功能:
2 months ago
LZ f8c4333edd 这段代码定义了一个名为AlarmAlertActivity的Activity,用于在接收到闹钟提醒时显示一个对话框,并播放声音。它实现了从Intent中获取笔记ID和摘要,检查屏幕状态,播放声音,显示对话框,并处理对话框的按钮点击事件。
2 months ago
LZ 873438d8f3 AlarmInitReceiver是一个BroadcastReceiver,用于初始化闹钟。当接收到广播时,它会查询数据库中所有需要提醒(提醒日期大于当前时间)且类型为普通笔记的条目。对于每个符合条件的笔记,它会创建一个PendingIntent,并使用AlarmManager设置一个闹钟,该闹钟在笔记的提醒日期到达时触发。当闹钟触发时,会广播一个Intent,该Intent被AlarmReceiver(未在代码中定义,但假设存在)接收并处理,通常用于显示提醒通知。
2 months ago
LZ 0da440a0ac 是一个颜色选择器(selector),用于在Android应用程序中定义不同状态下的颜色变化。它包含三个<item>元素,分别对应以下状态:
3 months ago
LZ 80da33f388 LinearLayout:作为根布局,它填充整个父容器,布局方向为垂直。
3 months ago
LZ 18fbe1f9e1 Contact类提供了一个静态方法getContact,用于根据电话号码从Android设备的联系人数据库中查询并返回对应的联系人姓名。为了提高查询效率,该方法使用了一个静态的HashMap(sContactCache)来缓存已经查询过的电话号码和联系人姓名的映射关系。如果在缓存中找到了对应的电话号码,则直接返回缓存中的联系人姓名,避免重复查询数据库。如果缓存中没有找到,则通过ContentResolver查询联系人数据库,并将查询结果存入缓存中。该方法还包含了错误处理和日志记录的逻辑,以确保程序的健壮性和可调试性。
3 months ago
LZ 62927cf9df Note 类提供了一个完整的框架,用于创建、更新、管理和同步便签数据。它处理了便签的基本属性,以及与便签相关的文本和通话数据,并且能够将这些更改同步到后端数据库,确保数据的持久化和一致性。
3 months ago
LZ 54aaefd2f0 Note 类的主要功能是管理便签数据的创建、更新和同步。
3 months ago
LZ f02940aa15 NoteWidgetProvider_4x类是NoteWidgetProvider的子类,专门用于处理4x小部件的更新和配置。它重写了父类的onUpdate、getLayoutId、getBgResourceId和getWidgetType方法,以提供4x小部件特有的布局资源、背景资源和类型。这个类确保了当系统需要更新4x小部件时,能够正确地显示内容和样式。
3 months ago
LZ a38b175c87 NoteWidgetProvider_2x类是NoteWidgetProvider的子类,专门用于处理2x小部件的更新和配置。它重写了父类的onUpdate、getLayoutId、getBgResourceId和getWidgetType方法,以提供2x小部件特有的布局资源、背景资源和类型。这个类确保了当系统需要更新2x小部件时,能够正确地显示内容和样式。
3 months ago
LZ 4e8277c91a 注释代码NoteWidgetProvider (2)
3 months ago
LZ cedeb819da 注释代码NoteWidgetProvider
3 months ago
LZ 53ea90f52e 注释代码NoteWidgetProvider
3 months ago

@ -0,0 +1,75 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* 2010-2011MiCode
*/
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* Apache License, Version 2.0
*/
/*
* 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
* Apache License, Version 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.gtask.exception;
// 这行代码声明了当前类所在的包名即net.micode.notes.gtask.exception。
public class ActionFailureException extends RuntimeException {
// 这行代码声明了一个名为ActionFailureException的类它继承自RuntimeException类。
private static final long serialVersionUID = 4425249765923293627L;
// 这行代码声明了一个名为serialVersionUID的静态常量用于序列化版本控制。
public ActionFailureException() {
// 这是ActionFailureException的无参构造函数它调用了父类RuntimeException的无参构造函数。
super();
}
public ActionFailureException(String paramString) {
// 这是ActionFailureException的一个带有一个String类型参数的构造函数用于传递异常信息。
super(paramString);
}
public ActionFailureException(String paramString, Throwable paramThrowable) {
// 这是ActionFailureException的一个带有String类型和Throwable类型参数的构造函数
// 用于传递异常信息和导致异常的原始异常。
super(paramString, paramThrowable);
}
}

@ -0,0 +1,147 @@
// 引入必要的包和类
package net.micode.notes.ui;
import android.app.Activity; // 引入Activity类它是应用程序中用于与用户交互的单个屏幕
import android.app.AlertDialog; // 引入AlertDialog类用于显示对话框
import android.content.Context; // 引入Context类它表示应用环境的全局信息
import android.content.DialogInterface; // 引入DialogInterface类它是对话框的接口
import android.content.DialogInterface.OnClickListener; // 引入OnClickListener接口用于监听对话框按钮点击事件
import android.content.DialogInterface.OnDismissListener; // 引入OnDismissListener接口用于监听对话框消失事件
import android.content.Intent; // 引入Intent类它表示一个要执行的动作
import android.media.AudioManager; // 引入AudioManager类用于管理音频播放
import android.media.MediaPlayer; // 引入MediaPlayer类用于播放音频和视频
import android.media.RingtoneManager; // 引入RingtoneManager类用于访问设备上的铃声
import android.net.Uri; // 引入Uri类用于表示统一资源标识符
import android.os.Bundle; // 引入Bundle类用于传递数据
import android.os.PowerManager; // 引入PowerManager类用于控制电源状态
import android.provider.Settings; // 引入Settings类用于访问系统设置
import android.view.Window; // 引入Window类用于控制窗口的属性
import android.view.WindowManager; // 引入WindowManager类用于管理窗口
import net.micode.notes.R; // 引入R类它包含了应用程序的资源ID
import net.micode.notes.data.Notes; // 引入Notes类可能用于表示笔记数据
import net.micode.notes.tool.DataUtils; // 引入DataUtils类可能包含一些数据处理的工具方法
import java.io.IOException; // 引入IOException类表示输入输出异常
// 定义一个继承自Activity的类并实现OnClickListener和OnDismissListener接口
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
private long mNoteId; // 用于存储笔记的ID
private String mSnippet; // 用于存储笔记的摘要
private static final int SNIPPET_PREW_MAX_LEN = 60; // 定义摘要的最大长度
MediaPlayer mPlayer; // MediaPlayer实例用于播放声音
// 当Activity创建时调用此方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); // 请求窗口没有标题
final Window win = getWindow(); // 获取当前窗口
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); // 添加标志,允许在锁屏时显示窗口
if (!isScreenOn()) { // 如果屏幕当前未点亮
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); // 添加多个标志,保持屏幕常亮、点亮屏幕等
}
Intent intent = getIntent(); // 获取启动此Activity的Intent
try {
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); // 从Intent中获取笔记ID
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); // 通过ID获取笔记摘要
// 如果摘要长度超过最大长度,则截取并添加省略号
mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) : mSnippet;
} catch (IllegalArgumentException e) {
e.printStackTrace(); // 捕获异常并打印堆栈跟踪
return; // 退出方法
}
mPlayer = new MediaPlayer(); // 创建MediaPlayer实例
// 如果笔记在数据库中可见且类型为笔记,则显示操作对话框并播放声音
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
showActionDialog();
playAlarmSound();
} else {
finish(); // 退出Activity
}
}
// 检查屏幕是否点亮
private boolean isScreenOn() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); // 获取PowerManager实例
return pm.isScreenOn(); // 返回屏幕是否点亮的布尔值
}
// 播放声音
private void playAlarmSound() {
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); // 获取默认的闹钟铃声URI
// 获取静音模式下受影响的音频流类型
int silentModeStreams = Settings.System.getInt(getContentResolver(), Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
// 根据静音模式设置音频流类型
if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) {
mPlayer.setAudioStreamType(silentModeStreams);
} else {
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
}
try {
mPlayer.setDataSource(this, url); // 设置音频数据源
mPlayer.prepare(); // 准备播放
mPlayer.setLooping(true); // 设置循环播放
mPlayer.start(); // 开始播放
} catch (IllegalArgumentException e) {
e.printStackTrace(); // 捕获异常并打印堆栈跟踪
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 显示操作对话框
private void showActionDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this); // 创建对话框构建器
dialog.setTitle(R.string.app_name); // 设置对话框标题
dialog.setMessage(mSnippet); // 设置对话框消息
dialog.setPositiveButton(R.string.notealert_ok, this); // 设置确定按钮及其点击事件监听器
if (isScreenOn()) { // 如果屏幕点亮
dialog.setNegativeButton(R.string.notealert_enter, this); // 设置取消按钮及其点击事件监听器
}
dialog.show().setOnDismissListener(this); // 显示对话框并设置消失事件监听器
}
// 当对话框按钮被点击时调用此方法
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_NEGATIVE: // 如果点击的是取消按钮
Intent intent = new Intent(this, NoteEditActivity.class); // 创建Intent用于启动NoteEditActivity
intent.setAction(Intent.ACTION_VIEW); // 设置Intent动作为查看
intent.putExtra(Intent.EXTRA_UID, mNoteId); // 将笔记ID作为额外数据传递给NoteEditActivity
startActivity(intent); // 启动NoteEditActivity
break;
default:
break;
}
}
// 当对话框消失时调用此方法
public void onDismiss(DialogInterface dialog) {
stopAlarmSound(); // 停止播放声音
finish(); // 退出Activity
}
// 停止播放声音
private void stopAlarmSound() {
if (mPlayer != null) {
mPlayer.stop(); // 停止播放
mPlayer.release(); // 释放资源
mPlayer = null; // 将MediaPlayer实例置为null
}
}
}

@ -0,0 +1,187 @@
// 导入所需的包和类
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Settings;
import android.view.Window;
import android.view.WindowManager;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.tool.DataUtils;
import java.io.IOException;
// 定义一个继承自Activity的类并实现OnClickListener和OnDismissListener接口
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
// 成员变量用于存储笔记的ID和摘要
private long mNoteId;
private String mSnippet;
// 定义摘要预览的最大长度
private static final int SNIPPET_PREW_MAX_LEN = 60;
// 声明一个MediaPlayer对象用于播放声音
MediaPlayer mPlayer;
// 当Activity创建时调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 请求无标题窗口特性
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 获取当前窗口对象
final Window win = getWindow();
// 添加标志,使得当屏幕被锁定时,该窗口仍然可见
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
// 如果屏幕当前是关闭的
if (!isScreenOn()) {
// 添加多个标志,包括保持屏幕常亮、点亮屏幕等
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
}
// 获取启动该Activity的Intent
Intent intent = getIntent();
try {
// 从Intent中提取笔记ID
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
// 获取笔记的摘要
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);
// 如果摘要长度超过最大长度,则进行截断,并添加省略号信息
mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0,
SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info)
: mSnippet;
} catch (IllegalArgumentException e) {
// 捕获异常并打印堆栈跟踪信息
e.printStackTrace();
return;
}
// 初始化MediaPlayer对象
mPlayer = new MediaPlayer();
// 检查笔记是否在数据库中且类型为笔记
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
// 显示操作对话框
showActionDialog();
// 播放闹钟声音
playAlarmSound();
} else {
// 如果笔记不存在则结束Activity
finish();
}
}
// 检查屏幕是否处于点亮状态
private boolean isScreenOn() {
// 获取PowerManager服务
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
// 返回屏幕是否点亮的状态
return pm.isScreenOn();
}
// 播放闹钟声音的方法
private void playAlarmSound() {
// 获取默认的闹钟铃声Uri
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM);
// 获取静音模式下受影响的音频流类型
int silentModeStreams = Settings.System.getInt(getContentResolver(),
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
// 如果静音模式下闹钟声音受影响则设置MediaPlayer的音频流类型为受影响的音频流
if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) {
mPlayer.setAudioStreamType(silentModeStreams);
} else {
// 否则,设置音频流类型为闹钟
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
}
try {
// 设置MediaPlayer的数据源并准备播放
mPlayer.setDataSource(this, url);
mPlayer.prepare();
// 设置循环播放
mPlayer.setLooping(true);
// 开始播放
mPlayer.start();
} catch (IllegalArgumentException e) {
// 捕获异常并打印堆栈跟踪信息
e.printStackTrace();
} catch (SecurityException e) {
// 捕获异常并打印堆栈跟踪信息
e.printStackTrace();
} catch (IllegalStateException e) {
// 捕获异常并打印堆栈跟踪信息
e.printStackTrace();
} catch (IOException e) {
// 捕获异常并打印堆栈跟踪信息
e.printStackTrace();
}
}
// 显示操作对话框的方法
private void showActionDialog() {
// 创建AlertDialog.Builder对象
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
// 设置对话框标题
dialog.setTitle(R.string.app_name);
// 设置对话框消息
dialog.setMessage(mSnippet);
// 设置确定按钮的文本和点击事件监听器
dialog.setPositiveButton(R.string.notealert_ok, this);
// 如果屏幕处于点亮状态,则设置取消按钮的文本和点击事件监听器
if (isScreenOn()) {
dialog.setNegativeButton(R.string.notealert_enter, this);
}
// 显示对话框,并设置对话框关闭监听器
dialog.show().setOnDismissListener(this);
}
// 实现OnClickListener接口的onClick方法处理对话框按钮的点击事件
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_NEGATIVE:
// 如果点击的是取消按钮则跳转到编辑笔记Activity
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_UID, mNoteId);
startActivity(intent);
break;
default:
break;
}
}
// 实现OnDismissListener接口的onDismiss方法处理对话框关闭事件
public void onDismiss(DialogInterface dialog) {
// 停止播放闹钟声音
stopAlarmSound();
// 结束Activity
finish();
}
// 停止播放闹钟声音的方法
private void stopAlarmSound() {
if (mPlayer != null) {
// 停止播放并释放MediaPlayer资源
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
}
}

@ -0,0 +1,68 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Apache License, Version 2.0使
* 使
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
*
*/
package net.micode.notes.ui; // 指定当前类所在的包
import android.app.AlarmManager; // 导入AlarmManager类用于设置闹钟
import android.app.PendingIntent; // 导入PendingIntent类用于表示一个待执行的Intent
import android.content.BroadcastReceiver; // 导入BroadcastReceiver类用于接收广播
import android.content.ContentUris; // 导入ContentUris类用于处理URI
import android.content.Context; // 导入Context类表示应用程序环境的全局信息
import android.content.Intent; // 导入Intent类用于不同组件间的通信
import android.database.Cursor; // 导入Cursor类用于访问数据库查询结果
import net.micode.notes.data.Notes; // 导入Notes类用于访问笔记数据
import net.micode.notes.data.Notes.NoteColumns; // 导入NoteColumns类包含笔记表的列名
// 定义一个继承自BroadcastReceiver的类用于初始化闹钟
public class AlarmInitReceiver extends BroadcastReceiver {
// 定义一个字符串数组,用于指定查询数据库时要返回的列
private static final String [] PROJECTION = new String [] {
NoteColumns.ID, // 笔记的ID
NoteColumns.ALERTED_DATE // 笔记的提醒日期
};
// 定义常量,表示列索引
private static final int COLUMN_ID = 0; // 笔记ID的列索引
private static final int COLUMN_ALERTED_DATE = 1; // 提醒日期的列索引
// 重写onReceive方法当接收到广播时调用
@Override
public void onReceive(Context context, Intent intent) {
long currentDate = System.currentTimeMillis(); // 获取当前时间
// 查询数据库获取所有未提醒且类型为笔记的记录的ID和提醒日期
Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE,
new String[] { String.valueOf(currentDate) },
null);
if (c != null) { // 如果查询结果不为空
if (c.moveToFirst()) { // 移动到查询结果的第一条记录
do {
long alertDate = c.getLong(COLUMN_ALERTED_DATE); // 获取提醒日期
Intent sender = new Intent(context, AlarmReceiver.class); // 创建一个Intent用于唤醒AlarmReceiver
sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); // 设置Intent的URI包含笔记ID
// 获取PendingIntent用于AlarmManager唤醒时执行
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0);
AlarmManager alermManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE); // 获取AlarmManager服务
// 设置闹钟在提醒日期时唤醒AlarmReceiver
alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent);
} while (c.moveToNext()); // 移动到下一条记录,继续循环
}
c.close(); // 关闭Cursor
}
}
}

@ -0,0 +1,76 @@
/*
* 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;
// 导入所需的Android和自定义类
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
// 定义一个继承自BroadcastReceiver的类用于初始化闹钟
public class AlarmInitReceiver extends BroadcastReceiver {
// 定义查询数据库时需要的列
private static final String [] PROJECTION = new String [] {
NoteColumns.ID, // 笔记的ID
NoteColumns.ALERTED_DATE // 笔记的提醒日期
};
// 定义列索引用于从Cursor中获取数据
private static final int COLUMN_ID = 0; // ID列的索引
private static final int COLUMN_ALERTED_DATE = 1; // 提醒日期列的索引
// 当接收到广播时调用此方法
@Override
public void onReceive(Context context, Intent intent) {
long currentDate = System.currentTimeMillis(); // 获取当前时间
// 从内容提供者中查询需要提醒的笔记,条件是提醒日期大于当前时间且笔记类型为普通笔记
Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE,
new String[] { String.valueOf(currentDate) },
null);
if (c != null) {
if (c.moveToFirst()) { // 移动到查询结果的第一条记录
do {
long alertDate = c.getLong(COLUMN_ALERTED_DATE); // 获取提醒日期
// 创建一个Intent用于在提醒时间到达时广播
Intent sender = new Intent(context, AlarmReceiver.class);
// 设置Intent的URI包含笔记的ID
sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID)));
// 创建一个PendingIntent用于AlarmManager在提醒时间到达时启动
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0);
// 获取AlarmManager服务
AlarmManager alermManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
// 设置闹钟在提醒时间到达时广播Intent
alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent);
} while (c.moveToNext()); // 处理查询结果中的下一条记录
}
c.close(); // 关闭Cursor
}
}
}

@ -0,0 +1,74 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* MiCode2010-2011
*/
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* Apache License 2.0
*/
/*
* you may not use this file except in compliance with the License.
* License使
*/
/*
* You may obtain a copy of the License at
* License
*/
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,
* License
*/
/*
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
/*
* See the License for the specific language governing permissions and
* License
*/
/*
* limitations under the License.
* License
*/
package net.micode.notes.ui;
// 声明这个类所在的包名。
import android.content.BroadcastReceiver;
// 导入Android的BroadcastReceiver类用于接收广播消息。
import android.content.Context;
// 导入Android的Context类表示应用环境的信息。
import android.content.Intent;
// 导入Android的Intent类用于不同组件之间的通信。
public class AlarmReceiver extends BroadcastReceiver {
// 声明一个名为AlarmReceiver的类它继承自BroadcastReceiver。
@Override
public void onReceive(Context context, Intent intent) {
// 重写onReceive方法当接收到广播时调用接收两个参数Context和Intent。
intent.setClass(context, AlarmAlertActivity.class);
// 设置Intent的目标Activity为AlarmAlertActivity。
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 为Intent添加标志表示这个Activity将作为一个新的任务启动。
context.startActivity(intent);
// 使用Context启动Intent指定的Activity。
}
}

@ -0,0 +1,141 @@
<!-- 注释开始:版权信息 -->
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) -->
<!-- 该文件受Apache License, Version 2.0的许可 -->
<!-- 你可以在遵守许可的情况下使用此文件,否则不可以 -->
<!-- 你可以从http://www.apache.org/licenses/LICENSE-2.0获取许可的副本 -->
<!-- 除非适用法律要求或书面同意,否则按照“现状”分发软件 -->
<!-- 不提供任何明示或暗示的保证或条件 -->
<!-- 请参阅许可协议了解具体的权限和限制 -->
<!-- 注释结束 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.micode.notes"
android:versionCode="1"
android:versionName="0.1">
<!-- 定义应用的包名、版本号和版本名称 -->
<uses-sdk android:minSdkVersion="14"/>
<!-- 指定应用支持的最低SDK版本为14 -->
<!-- 应用的权限列表开始 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 允许应用写入外部存储 -->
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<!-- 允许应用安装快捷方式到桌面 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 允许应用访问网络 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!-- 允许应用读取联系人信息 -->
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<!-- 允许应用管理账户 -->
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<!-- 允许应用验证账户 -->
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!-- 允许应用获取账户列表 -->
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<!-- 允许应用使用账户凭据 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- 允许应用在设备启动完成后接收广播 -->
<!-- 应用的权限列表结束 -->
<application android:icon="@drawable/icon_app"
android:label="@string/app_name">
<!-- 定义应用的图标和标签 -->
<!-- 活动列表开始 -->
<activity android:name=".ui.NotesListActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="adjustPan">
<!-- 定义NotesListActivity活动 -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- 指定该活动为应用的主活动,并显示在启动器中 -->
</activity>
<activity android:name=".ui.NoteEditActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
android:theme="@style/NoteTheme">
<!-- 定义NoteEditActivity活动 -->
<!-- 以下是该活动的多个intent-filter用于处理不同的动作和数据类型 -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="vnd.android.cursor.item/text_note"/>
<data android:mimeType="vnd.android.cursor.item/call_note"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.INSERT_OR_EDIT"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="vnd.android.cursor.item/text_note"/>
<data android:mimeType="vnd.android.cursor.item/call_note"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/>
<!-- 指定该活动支持搜索并引用一个定义搜索行为的XML资源 -->
</activity>
<!-- 活动列表结束 -->
<provider android:name="net.micode.notes.data.NotesProvider"
android:authorities="micode_notes"
android:multiprocess="true"/>
<!-- 定义内容提供者,用于跨应用共享数据 -->
<!-- 小部件接收器列表开始 -->
<receiver android:name=".widget.NoteWidgetProvider_2x"
android:label="@string/app_widget2x2">
<!-- 定义2x2尺寸的小部件接收器 -->
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="android.appwidget.action.APPWIDGET_DELETED"/>
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_2x_info"/>
<!-- 指定小部件的元数据 -->
</receiver>
<receiver android:name=".widget.NoteWidgetProvider_4x"
android:label="@string/app_widget4x4">
<!-- 定义4x4尺寸的小部件接收器 -->
<!-- intent-filter和meta-data同上 -->
</receiver>
<!-- 小部件接收器列表结束 -->
<receiver android:name=".ui.AlarmInitReceiver">
<!-- 定义启动完成时的广播接收器 -->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<receiver android:name="net.micode.notes.ui.AlarmReceiver" android:process=":remote"> </receiver>
<!-- 定义远程进程中的广播接收器 -->
<activity android:name=".ui.AlarmAlertActivity"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> </activity>
<!-- 定义警报活动 -->
<activity android:name="net.micode.notes.ui.NotesPreferenceActivity"
android:label="@string/preferences_title"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Holo.Light"> </activity>
<!-- 定义设置活动 -->
<service android:name="net.micode.notes.gtask.remote.GTaskSyncService" android:exported="false"> </service>
<!-- 定义服务用于与Google任务同步 -->
<meta-data android:name="android.app.default_searchable" android:value=".ui.NoteEditActivity"/>
<!-- 指定应用默认的搜索活动 -->
</application>
</manifest>

@ -0,0 +1,90 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Apache License 2.0
* 使
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
*
*
*
*/
package net.micode.notes.data;
// 导入所需的Android类和Java类
import android.content.Context; // Android上下文类用于访问应用的环境信息
import android.database.Cursor; // 数据库查询结果的游标类
import android.provider.ContactsContract.CommonDataKinds.Phone; // 联系人数据库中的电话号码表
import android.provider.ContactsContract.Data; // 联系人数据库中的通用数据表
import android.telephony.PhoneNumberUtils; // 电话号码工具类
import android.util.Log; // 日志工具类
import java.util.HashMap; // 哈希映射表,用于存储键值对
// Contact类用于处理联系人数据
public class Contact {
// 静态HashMap用于缓存电话号码和联系人姓名的映射关系
private static HashMap<String, String> sContactCache;
// 日志标签,用于标识日志信息
private static final String TAG = "Contact";
// 用于查询联系人数据库时使用的SQL条件字符串
// 该条件用于匹配电话号码和联系人ID并确保查询的是电话号码类型的数据
private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"
+ " AND " + Data.RAW_CONTACT_ID + " IN "
+ "(SELECT raw_contact_id "
+ " FROM phone_lookup"
+ " WHERE min_match = '+')";
// 静态方法,根据电话号码获取联系人姓名
public static String getContact(Context context, String phoneNumber) {
// 如果缓存为空,则初始化缓存
if(sContactCache == null) {
sContactCache = new HashMap<String, String>();
}
// 如果缓存中已包含该电话号码对应的联系人姓名,则直接返回
if(sContactCache.containsKey(phoneNumber)) {
return sContactCache.get(phoneNumber);
}
// 将SQL条件字符串中的“+”替换为电话号码的最小匹配字符串
String selection = CALLER_ID_SELECTION.replace("+",
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));
// 使用ContentResolver查询联系人数据库
Cursor cursor = context.getContentResolver().query(
Data.CONTENT_URI, // 查询的目标URI
new String [] { Phone.DISPLAY_NAME }, // 需要查询的列,这里是联系人姓名
selection, // 查询条件
new String[] { phoneNumber }, // 查询条件的参数,这里是电话号码
null); // 查询结果的排序规则,这里为空表示不排序
// 如果查询结果不为空且游标指向第一条记录
if (cursor != null && cursor.moveToFirst()) {
try {
// 从游标中获取联系人姓名
String name = cursor.getString(0);
// 将电话号码和联系人姓名存入缓存
sContactCache.put(phoneNumber, name);
// 返回联系人姓名
return name;
} catch (IndexOutOfBoundsException e) {
// 如果获取联系人姓名时发生索引越界异常则记录错误日志并返回null
Log.e(TAG, " Cursor get string error " + e.toString());
return null;
} finally {
// 关闭游标
cursor.close();
}
} else {
// 如果没有找到匹配的联系人则记录日志并返回null
Log.d(TAG, "No contact matched with number:" + phoneNumber);
return null;
}
}
}

@ -0,0 +1,83 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* 2010-2011MiCode
*/
/* 省略了其余版权和许可信息 */
package net.micode.notes.ui;
// 声明这个类所在的包名。
import java.util.Calendar;
// 导入Java的Calendar类用于处理日期和时间。
// 省略了其他import语句
public class DateTimePickerDialog extends AlertDialog implements OnClickListener {
// 声明一个名为DateTimePickerDialog的类它继承自AlertDialog并实现OnClickListener接口。
private Calendar mDate = Calendar.getInstance();
// 声明一个Calendar对象mDate用于存储日期和时间初始化为当前时间。
private boolean mIs24HourView;
// 声明一个布尔变量mIs24HourView用于表示是否使用24小时制。
private OnDateTimeSetListener mOnDateTimeSetListener;
// 声明一个OnDateTimeSetListener接口类型的变量mOnDateTimeSetListener用于回调日期和时间设置。
private DateTimePicker mDateTimePicker;
// 声明一个DateTimePicker对象mDateTimePicker用于日期和时间的选择。
// 声明一个内部接口OnDateTimeSetListener包含一个方法OnDateTimeSet。
public interface OnDateTimeSetListener {
void OnDateTimeSet(AlertDialog dialog, long date);
}
// DateTimePickerDialog的构造方法接收Context和初始日期长整型
public DateTimePickerDialog(Context context, long date) {
super(context);
// 初始化DateTimePicker对象并设置到对话框中。
mDateTimePicker = new DateTimePicker(context);
setView(mDateTimePicker);
// 设置日期和时间变化监听器当日期或时间变化时更新mDate对象并更新标题。
mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() { ... });
// 使用传入的日期初始化mDate对象并设置秒为0。
mDate.setTimeInMillis(date);
mDate.set(Calendar.SECOND, 0);
// 设置DateTimePicker的当前日期。
mDateTimePicker.setCurrentDate(mDate.getTimeInMillis());
// 设置对话框的确定按钮和取消按钮确定按钮使用当前对象作为监听器取消按钮为null。
setButton(...);
setButton2(...);
// 根据系统的设置初始化24小时制视图。
set24HourView(DateFormat.is24HourFormat(this.getContext()));
// 更新对话框的标题为当前日期和时间。
updateTitle(mDate.getTimeInMillis());
}
// 设置24小时制视图的方法。
public void set24HourView(boolean is24HourView) {
mIs24HourView = is24HourView;
}
// 设置日期和时间设置监听器的方法。
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
mOnDateTimeSetListener = callBack;
}
// 更新标题的方法,根据当前日期和时间设置对话框的标题。
private void updateTitle(long date) {
int flag = ...; // 设置日期时间格式化标志包括是否显示年、日期、时间以及是否使用24小时制。
setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));
}
// 实现OnClickListener接口的onClick方法当点击确定按钮时调用。
public void onClick(DialogInterface arg0, int arg1) {
if (mOnDateTimeSetListener != null) {
// 如果设置了日期和时间设置监听器则回调其OnDateTimeSet方法。
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
}
}
}

@ -0,0 +1,158 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* MiCode2010-2011
*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* Apache License 2.0
*
* 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 java.util.Calendar;
// 导入Java的Calendar类用于处理日期和时间。
import net.micode.notes.R;
// 导入项目资源文件。
import net.micode.notes.ui.DateTimePicker;
// 导入自定义的DateTimePicker类。
import net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener;
// 导入DateTimePicker类的内部接口OnDateTimeChangedListener。
import android.app.AlertDialog;
// 导入Android的AlertDialog类用于显示对话框。
import android.content.Context;
// 导入Android的Context类表示应用环境的全局信息。
import android.content.DialogInterface;
// 导入Android的DialogInterface接口表示对话框的接口。
import android.content.DialogInterface.OnClickListener;
// 导入DialogInterface接口中的OnClickListener内部接口用于处理对话框按钮的点击事件。
import android.text.format.DateFormat;
// 导入Android的DateFormat类用于格式化日期。
import android.text.format.DateUtils;
// 导入Android的DateUtils类提供日期和时间的格式化方法。
public class DateTimePickerDialog extends AlertDialog implements OnClickListener {
// 声明DateTimePickerDialog类它继承自AlertDialog并实现OnClickListener接口。
private Calendar mDate = Calendar.getInstance();
// 声明一个Calendar对象用于存储日期和时间。
private boolean mIs24HourView;
// 声明一个布尔变量用于指示是否使用24小时制显示时间。
private OnDateTimeSetListener mOnDateTimeSetListener;
// 声明一个OnDateTimeSetListener接口类型的变量用于回调日期时间设置完成的操作。
private DateTimePicker mDateTimePicker;
// 声明一个DateTimePicker对象用于显示日期和时间选择器。
// 声明一个内部接口OnDateTimeSetListener用于回调日期时间设置完成的操作。
public interface OnDateTimeSetListener {
void OnDateTimeSet(AlertDialog dialog, long date);
}
// DateTimePickerDialog的构造函数初始化对话框。
public DateTimePickerDialog(Context context, long date) {
super(context);
mDateTimePicker = new DateTimePicker(context);
// 创建DateTimePicker对象。
setView(mDateTimePicker);
// 设置对话框的内容视图为DateTimePicker。
mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() {
// 设置日期时间变化监听器。
public void onDateTimeChanged(DateTimePicker view, int year, int month,
int dayOfMonth, int hourOfDay, int minute) {
// 当日期时间变化时更新Calendar对象。
mDate.set(Calendar.YEAR, year);
mDate.set(Calendar.MONTH, month);
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
mDate.set(Calendar.MINUTE, minute);
updateTitle(mDate.getTimeInMillis());
// 更新对话框标题。
}
});
mDate.setTimeInMillis(date);
// 设置Calendar对象的初始时间为传入的日期。
mDate.set(Calendar.SECOND, 0);
// 将秒数设置为0。
mDateTimePicker.setCurrentDate(mDate.getTimeInMillis());
// 设置DateTimePicker的当前日期时间。
setButton(context.getString(R.string.datetime_dialog_ok), this);
// 设置对话框的确定按钮文本和点击事件监听器。
setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener)null);
// 设置对话框的取消按钮文本,不设置点击事件监听器。
set24HourView(DateFormat.is24HourFormat(this.getContext()));
// 根据系统设置初始化24小时制显示。
updateTitle(mDate.getTimeInMillis());
// 更新对话框标题。
}
// 设置是否使用24小时制显示时间。
public void set24HourView(boolean is24HourView) {
mIs24HourView = is24HourView;
}
// 设置日期时间设置完成的回调监听器。
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
mOnDateTimeSetListener = callBack;
}
// 更新对话框标题。
private void updateTitle(long date) {
int flag =
DateUtils.FORMAT_SHOW_YEAR |
DateUtils.FORMAT_SHOW_DATE |
DateUtils.FORMAT_SHOW_TIME;
// 设置日期时间格式标志。
flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_12HOUR;
// 根据是否使用24小时制设置格式标志。
setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));
// 使用DateUtils格式化日期时间并设置为对话框标题。
}
// 处理对话框按钮的点击事件。
public void onClick(DialogInterface arg0, int arg1) {
if (mOnDateTimeSetListener != null) {
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
// 如果设置了日期时间设置完成的回调监听器则调用其OnDateTimeSet方法。
}
}
}

@ -0,0 +1,56 @@
/*
* 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.
*/
// 定义一个名为DropdownMenu的公开类
public class DropdownMenu {
// 声明一个Button类型的私有成员变量mButton用于存储下拉按钮
private Button mButton;
// 声明一个PopupMenu类型的私有成员变量mPopupMenu用于存储弹出的菜单
private PopupMenu mPopupMenu;
// 声明一个Menu类型的私有成员变量mMenu用于存储菜单项
private Menu mMenu;
// 构造方法初始化DropdownMenu对象
public DropdownMenu(Context context, Button button, int menuId) {
mButton = button; // 将传入的Button对象赋值给mButton
mButton.setBackgroundResource(R.drawable.dropdown_icon); // 设置按钮的背景资源为dropdown_icon
mPopupMenu = new PopupMenu(context, mButton); // 创建一个新的PopupMenu对象并将其与mButton绑定
mMenu = mPopupMenu.getMenu(); // 获取PopupMenu中的Menu对象
mPopupMenu.getMenuInflater().inflate(menuId, mMenu); // 使用menuId指定的XML布局文件来填充Menu对象
mButton.setOnClickListener(new OnClickListener() { // 为mButton设置点击监听器
public void onClick(View v) {
mPopupMenu.show(); // 当按钮被点击时显示PopupMenu
}
});
}
// 设置PopupMenu的菜单项点击监听器
public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) {
if (mPopupMenu != null) {
mPopupMenu.setOnMenuItemClickListener(listener); // 为PopupMenu设置菜单项点击监听器
}
}
// 根据ID查找菜单项
public MenuItem findItem(int id) {
return mMenu.findItem(id); // 在Menu对象中查找具有指定ID的菜单项并返回它
}
// 设置按钮的标题
public void setTitle(CharSequence title) {
mButton.setText(title); // 将传入的CharSequence对象设置为按钮的标题
}
}

@ -0,0 +1,93 @@
/*
* 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.
*/
// 定义一个名为FoldersListAdapter的类该类继承自CursorAdapter
package net.micode.notes.ui;
import android.content.Context; // 导入Context类用于访问应用环境信息
import android.database.Cursor; // 导入Cursor类用于数据库查询结果集的遍历
import android.view.View; // 导入View类用于UI界面上的元素
import android.view.ViewGroup; // 导入ViewGroup类用于容纳其他视图元素
import android.widget.CursorAdapter; // 导入CursorAdapter类用于将Cursor数据绑定到视图上
import android.widget.LinearLayout; // 导入LinearLayout类用于创建线性布局的视图
import android.widget.TextView; // 导入TextView类用于显示文本
import net.micode.notes.R; // 导入R类用于访问应用资源
import net.micode.notes.data.Notes; // 导入Notes类用于访问笔记数据
import net.micode.notes.data.Notes.NoteColumns; // 导入NoteColumns内部类用于访问笔记表的列名
// FoldersListAdapter类的定义开始
public class FoldersListAdapter extends CursorAdapter {
// 定义用于查询的列名数组
public static final String [] PROJECTION = {
NoteColumns.ID, // 笔记的ID
NoteColumns.SNIPPET // 笔记的摘要(这里用作文件夹名)
};
// 定义列索引常量
public static final int ID_COLUMN = 0; // ID列的索引
public static final int NAME_COLUMN = 1; // 名称(摘要)列的索引
// FoldersListAdapter的构造函数
public FoldersListAdapter(Context context, Cursor c) {
super(context, c); // 调用父类的构造函数
// TODO Auto-generated constructor stub
}
// 当需要新的视图来显示数据时,调用此方法
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new FolderListItem(context); // 创建一个新的FolderListItem视图
}
// 当需要将数据绑定到视图上时,调用此方法
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof FolderListItem) { // 如果视图是FolderListItem的实例
// 根据ID判断是否是根文件夹并获取文件夹名
String folderName = (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
// 调用FolderListItem的bind方法将文件夹名设置到视图上
((FolderListItem) view).bind(folderName);
}
}
// 根据位置获取文件夹名的方法
public String getFolderName(Context context, int position) {
Cursor cursor = (Cursor) getItem(position); // 获取指定位置的Cursor
// 根据ID判断是否是根文件夹并返回文件夹名
return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
}
// 定义一个内部类FolderListItem继承自LinearLayout
private class FolderListItem extends LinearLayout {
private TextView mName; // 用于显示文件夹名的TextView
// FolderListItem的构造函数
public FolderListItem(Context context) {
super(context); // 调用父类的构造函数
inflate(context, R.layout.folder_list_item, this); // 使用指定的布局文件初始化视图
mName = (TextView) findViewById(R.id.tv_folder_name); // 获取TextView的实例
}
// 定义一个方法,用于设置文件夹名
public void bind(String name) {
mName.setText(name); // 将文件夹名设置到TextView上
}
}
}

@ -1 +1,113 @@
mi
/*
* 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.tool;
public class GTaskStringUtils {
public final static String GTASK_JSON_ACTION_ID = "action_id";
public final static String GTASK_JSON_ACTION_LIST = "action_list";
public final static String GTASK_JSON_ACTION_TYPE = "action_type";
public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create";
public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all";
public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move";
public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update";
public final static String GTASK_JSON_CREATOR_ID = "creator_id";
public final static String GTASK_JSON_CHILD_ENTITY = "child_entity";
public final static String GTASK_JSON_CLIENT_VERSION = "client_version";
public final static String GTASK_JSON_COMPLETED = "completed";
public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id";
public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id";
public final static String GTASK_JSON_DELETED = "deleted";
public final static String GTASK_JSON_DEST_LIST = "dest_list";
public final static String GTASK_JSON_DEST_PARENT = "dest_parent";
public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type";
public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta";
public final static String GTASK_JSON_ENTITY_TYPE = "entity_type";
public final static String GTASK_JSON_GET_DELETED = "get_deleted";
public final static String GTASK_JSON_ID = "id";
public final static String GTASK_JSON_INDEX = "index";
public final static String GTASK_JSON_LAST_MODIFIED = "last_modified";
public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point";
public final static String GTASK_JSON_LIST_ID = "list_id";
public final static String GTASK_JSON_LISTS = "lists";
public final static String GTASK_JSON_NAME = "name";
public final static String GTASK_JSON_NEW_ID = "new_id";
public final static String GTASK_JSON_NOTES = "notes";
public final static String GTASK_JSON_PARENT_ID = "parent_id";
public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id";
public final static String GTASK_JSON_RESULTS = "results";
public final static String GTASK_JSON_SOURCE_LIST = "source_list";
public final static String GTASK_JSON_TASKS = "tasks";
public final static String GTASK_JSON_TYPE = "type";
public final static String GTASK_JSON_TYPE_GROUP = "GROUP";
public final static String GTASK_JSON_TYPE_TASK = "TASK";
public final static String GTASK_JSON_USER = "user";
public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]";
public final static String FOLDER_DEFAULT = "Default";
public final static String FOLDER_CALL_NOTE = "Call_Note";
public final static String FOLDER_META = "METADATA";
public final static String META_HEAD_GTASK_ID = "meta_gid";
public final static String META_HEAD_NOTE = "meta_note";
public final static String META_HEAD_DATA = "meta_data";
public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE";
}

@ -0,0 +1,82 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* 2010-2011MiCode
*/
/* 以下注释是关于Apache License 2.0的声明 */
/* ...与前文相同省略了详细的Apache License注释内容 */
package net.micode.notes.gtask.remote;
// 这行代码声明了当前类所在的包名为net.micode.notes.gtask.remote。
import android.app.Activity;
// 导入Android框架中的Activity类用于表示应用中的一个单一屏幕包含用户界面的一个窗口。
import android.app.Service;
// 导入Android框架中的Service类用于执行后台操作而不提供用户界面。
import android.content.Context;
// 导入Android框架中的Context类它允许访问特定资源和类以及调用应用级操作如启动活动、广播和接收意图等。
import android.content.Intent;
// 导入Android框架中的Intent类它用于在不同组件之间进行消息传递。
import android.os.Bundle;
// 导入Android框架中的Bundle类它用于传递数据集例如从活动到另一个活动。
import android.os.IBinder;
// 导入Android框架中的IBinder接口它是远程服务的基石用于进程间通信IPC
public class GTaskSyncService extends Service {
// 声明了一个名为GTaskSyncService的类它继承自Android框架中的Service类。
// 声明了一些静态常量,用于同步操作的类型和广播名称等。
// ...(省略了静态常量的详细声明)
// 声明了一个静态的GTaskASyncTask类型的变量mSyncTask用于表示当前的同步任务。
// ...(省略了其他静态变量的声明)
// 私有方法startSync用于开始同步操作。
// ...省略了startSync方法的详细实现
// 私有方法cancelSync用于取消当前的同步操作。
// ...省略了cancelSync方法的详细实现
@Override
public void onCreate() {
// 重写了Service类中的onCreate方法当服务被创建时调用。这里将mSyncTask重置为null。
mSyncTask = null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 重写了Service类中的onStartCommand方法当服务被启动时调用。
// 这里根据传入的Intent中的动作来决定是开始同步还是取消同步并返回START_STICKY表示如果服务被杀死后会重新创建。
// ...省略了onStartCommand方法的详细实现
}
@Override
public void onLowMemory() {
// 重写了Service类中的onLowMemory方法当设备内存低时调用。这里取消当前的同步任务以释放资源。
if (mSyncTask != null) {
mSyncTask.cancelSync();
}
}
@Override
public IBinder onBind(Intent intent) {
// 重写了Service类中的onBind方法用于返回一个IBinder对象以允许其他应用绑定到这个服务。
// 这里返回null表示这个服务不支持绑定。
return null;
}
// 公有方法sendBroadcast用于发送一个包含同步进度信息的广播。
// ...省略了sendBroadcast方法的详细实现
// 公有静态方法startSync用于从Activity中启动同步服务。
// ...省略了startSync方法的详细实现
// 公有静态方法cancelSync用于从任何Context中取消同步服务。
// ...省略了cancelSync方法的详细实现
// 公有静态方法isSyncing用于检查当前是否有同步任务正在进行。
// ...省略了isSyncing方法的详细实现
// 公有静态方法getProgressString用于获取当前的同步进度信息。
// ...省略了getProgressString方法的详细实现
}

@ -0,0 +1,100 @@
/*
* 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.
*/
// 声明MetaData类它继承自Task类
package net.micode.notes.gtask.data;
import android.database.Cursor; // 导入Cursor类用于数据库操作
import android.util.Log; // 导入Log类用于日志输出
import net.micode.notes.tool.GTaskStringUtils; // 导入工具类,用于处理字符串
import org.json.JSONException; // 导入JSONException类用于处理JSON异常
import org.json.JSONObject; // 导入JSONObject类用于处理JSON对象
// MetaData类的定义开始
public class MetaData extends Task {
// 定义日志标签
private final static String TAG = MetaData.class.getSimpleName();
// 定义与MetaData相关的Gid可能是Google Tasks中的任务ID
private String mRelatedGid = null;
// 设置MetaData的gid和metaInfo
public void setMeta(String gid, JSONObject metaInfo) {
try {
// 在metaInfo中添加gid信息
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
} catch (JSONException e) {
// 如果添加失败,则记录错误日志
Log.e(TAG, "failed to put related gid");
}
// 将metaInfo转换为字符串并设置为任务的备注
setNotes(metaInfo.toString());
// 设置任务名称为特定的Meta任务名称
setName(GTaskStringUtils.META_NOTE_NAME);
}
// 获取与MetaData相关的Gid
public String getRelatedGid() {
return mRelatedGid;
}
// 判断MetaData是否值得保存基于备注是否非空
@Override
public boolean isWorthSaving() {
return getNotes() != null;
}
// 根据远程JSON对象设置MetaData的内容
@Override
public void setContentByRemoteJSON(JSONObject js) {
// 调用父类的方法设置内容
super.setContentByRemoteJSON(js);
// 如果备注不为空则尝试解析并获取相关的Gid
if (getNotes() != null) {
try {
JSONObject metaInfo = new JSONObject(getNotes().trim());
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
} catch (JSONException e) {
// 如果解析失败则记录警告日志并将Gid设置为null
Log.w(TAG, "failed to get related gid");
mRelatedGid = null;
}
}
}
// 根据本地JSON对象设置MetaData的内容不应被调用
@Override
public void setContentByLocalJSON(JSONObject js) {
// 抛出异常,表示这个方法不应该被调用
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");
}
// 从MetaData的内容获取本地JSON对象不应被调用
@Override
public JSONObject getLocalJSONFromContent() {
// 抛出异常,表示这个方法不应该被调用
throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called");
}
// 根据Cursor获取同步操作不应被调用
@Override
public int getSyncAction(Cursor c) {
// 抛出异常,表示这个方法不应该被调用
throw new IllegalAccessError("MetaData:getSyncAction should not be called");
}
}

@ -0,0 +1,76 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* 2010-2011MiCode
*/
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* Apache License, Version 2.0
*/
/*
* 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
* Apache License, Version 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.gtask.exception;
// 这行代码声明了当前类所在的包名即net.micode.notes.gtask.exception。
public class NetworkFailureException extends Exception {
// 这行代码声明了一个名为NetworkFailureException的类它继承自Java标准库中的Exception类。
// 这意味着NetworkFailureException是一个检查型异常checked exception需要在方法签名中声明或在代码中捕获。
private static final long serialVersionUID = 2107610287180234136L;
// 这行代码声明了一个名为serialVersionUID的静态常量用于序列化版本控制。
// 当对象被序列化时serialVersionUID用于确保发送方和接收方对序列化的对象版本保持一致。
public NetworkFailureException() {
// 这是NetworkFailureException的无参构造函数它调用了父类Exception的无参构造函数。
super();
}
public NetworkFailureException(String paramString) {
// 这是NetworkFailureException的一个带有一个String类型参数的构造函数用于传递异常信息。
// 它调用了父类Exception的带有String类型参数的构造函数。
super(paramString);
}
public NetworkFailureException(String paramString, Throwable paramThrowable) {
// 这是NetworkFailureException的一个带有String类型和Throwable类型参数的构造函数
// 用于传递异常信息和导致异常的原始异常。它调用了父类Exception的带有String类型和Throwable类型参数的构造函数。
super(paramString, paramThrowable);
}
}

@ -0,0 +1,121 @@
/*
* 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.
*/
// 声明一个名为Node的抽象类位于net.micode.notes.gtask.data包中
package net.micode.notes.gtask.data;
// 导入必要的类
import android.database.Cursor;
import org.json.JSONObject;
// 定义一个名为Node的抽象类
public abstract class Node {
// 定义同步操作类型的常量
public static final int SYNC_ACTION_NONE = 0; // 无操作
public static final int SYNC_ACTION_ADD_REMOTE = 1; // 远程添加
public static final int SYNC_ACTION_ADD_LOCAL = 2; // 本地添加
public static final int SYNC_ACTION_DEL_REMOTE = 3; // 远程删除
public static final int SYNC_ACTION_DEL_LOCAL = 4; // 本地删除
public static final int SYNC_ACTION_UPDATE_REMOTE = 5; // 远程更新
public static final int SYNC_ACTION_UPDATE_LOCAL = 6; // 本地更新
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; // 更新冲突
public static final int SYNC_ACTION_ERROR = 8; // 错误
// 私有成员变量
private String mGid; // 全局唯一标识符
private String mName; // 名称
private long mLastModified; // 最后修改时间
private boolean mDeleted; // 是否已删除
// Node类的构造方法
public Node() {
mGid = null; // 初始化mGid为null
mName = ""; // 初始化mName为空字符串
mLastModified = 0; // 初始化mLastModified为0
mDeleted = false; // 初始化mDeleted为false
}
// 抽象方法用于获取创建操作的JSON对象
public abstract JSONObject getCreateAction(int actionId);
// 抽象方法用于获取更新操作的JSON对象
public abstract JSONObject getUpdateAction(int actionId);
// 抽象方法用于通过远程JSON对象设置内容
public abstract void setContentByRemoteJSON(JSONObject js);
// 抽象方法用于通过本地JSON对象设置内容
public abstract void setContentByLocalJSON(JSONObject js);
// 抽象方法用于从内容中获取本地JSON对象
public abstract JSONObject getLocalJSONFromContent();
// 抽象方法用于根据Cursor对象获取同步操作类型
public abstract int getSyncAction(Cursor c);
// 设置全局唯一标识符的方法
public void setGid(String gid) {
this.mGid = gid;
}
// 设置名称的方法
public void setName(String name) {
this.mName = name;
}
// 设置最后修改时间的方法
public void setLastModified(long lastModified) {
this.mLastModified = lastModified;
}
// 设置是否已删除状态的方法
public void setDeleted(boolean deleted) {
this.mDeleted = deleted;
}
// 获取全局唯一标识符的方法
public String getGid() {
return this.mGid;
}
// 获取名称的方法
public String getName() {
return this.mName;
}
// 获取最后修改时间的方法
public long getLastModified() {
return this.mLastModified;
}
// 获取是否已删除状态的方法
public boolean getDeleted() {
return this.mDeleted;
}
}

@ -0,0 +1,231 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* MiCodeMiCode
*
* 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
* Apache 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.model;
// 声明该文件属于net.micode.notes.model包。
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.net.Uri;
import android.os.RemoteException;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote;
import java.util.ArrayList;
// 定义Note类用于管理便签的数据和操作。
public class Note {
private ContentValues mNoteDiffValues; // 用于存储便签的差异值,用于更新操作。
private NoteData mNoteData; // 存储便签的额外数据,如文本和通话数据。
private static final String TAG = "Note"; // 用于日志输出的标签。
/**
* 便ID便
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
// 创建一个新的便签在数据库中。
ContentValues values = new ContentValues();
long createdTime = System.currentTimeMillis();
values.put(NoteColumns.CREATED_DATE, createdTime); // 设置创建时间。
values.put(NoteColumns.MODIFIED_DATE, createdTime); // 设置修改时间。
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); // 设置便签类型。
values.put(NoteColumns.LOCAL_MODIFIED, 1); // 设置本地修改标志。
values.put(NoteColumns.PARENT_ID, folderId); // 设置父ID即文件夹ID。
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); // 插入便签到数据库。
long noteId = 0;
try {
noteId = Long.valueOf(uri.getPathSegments().get(1)); // 从URI中获取新创建的便签ID。
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString()); // 记录日志如果ID获取失败。
noteId = 0;
}
if (noteId == -1) {
throw new IllegalStateException("Wrong note id:" + noteId); // 如果ID错误抛出异常。
}
return noteId; // 返回新创建的便签ID。
}
public Note() {
mNoteDiffValues = new ContentValues(); // 初始化差异值ContentValues。
mNoteData = new NoteData(); // 初始化便签数据。
}
// 设置便签的值,并标记为本地修改。
public void setNoteValue(String key, String value) {
mNoteDiffValues.put(key, value);
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 设置文本数据。
public void setTextData(String key, String value) {
mNoteData.setTextData(key, value);
}
// 设置文本数据ID。
public void setTextDataId(long id) {
mNoteData.setTextDataId(id);
}
// 获取文本数据ID。
public long getTextDataId() {
return mNoteData.mTextDataId;
}
// 设置通话数据ID。
public void setCallDataId(long id) {
mNoteData.setCallDataId(id);
}
// 设置通话数据。
public void setCallData(String key, String value) {
mNoteData.setCallData(key, value);
}
// 检查是否有本地修改。
public boolean isLocalModified() {
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified();
}
// 同步便签到数据库。
public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
if (!isLocalModified()) {
return true;
}
/**
* 便{@link NoteColumns#LOCAL_MODIFIED}
* {@link NoteColumns#MODIFIED_DATE}使便便
*/
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
Log.e(TAG, "Update note error, should not happen");
// Do not return, fall through
}
mNoteDiffValues.clear();
if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false;
}
return true;
}
// 定义NoteData内部类用于管理便签的文本和通话数据。
private class NoteData {
private long mTextDataId;
private ContentValues mTextDataValues;
private long mCallDataId;
private ContentValues mCallDataValues;
private static final String TAG = "NoteData";
public NoteData() {
mTextDataValues = new ContentValues();
mCallDataValues = new ContentValues();
mTextDataId = 0;
mCallDataId = 0;
}
// 检查是否有本地修改。
boolean isLocalModified() {
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
// 设置文本数据ID。
void setTextDataId(long id) {
if(id <= 0) {
throw new IllegalArgumentException("Text data id should larger than 0");
}
mTextDataId = id;
}
// 设置通话数据ID。
void setCallDataId(long id) {
if (id <= 0) {
throw new IllegalArgumentException("Call data id should larger than 0");
}
mCallDataId = id;
}
// 设置通话数据。
void setCallData(String key, String value) {
mCallDataValues.put(key, value);
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 设置文本数据。
void setTextData(String key, String value) {
mTextDataValues.put(key, value);
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 将数据推送到内容解析器。
Uri pushIntoContentResolver(Context context, long noteId) {
/**
*
*/
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;
if(mTextDataValues.size() > 0) {
mTextDataValues.put(DataColumns.NOTE_ID, noteId);
if (mTextDataId == 0) {
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mTextDataValues);
try {
setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
Log.e(TAG, "Insert new text data fail with noteId" + noteId);
mTextDataValues.clear();
return null;
}
} else {
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId));
builder.withValues(mTextDataValues);
operationList.add(builder.build());
}
mTextDataValues.clear();
}
if(mCallDataValues.size() > 0) {
mCallDataValues.put(DataColumns.NOTE

@ -1 +1,231 @@
mi
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* MiCodeMiCode
*
* 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
* Apache 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.model;
// 声明该文件属于net.micode.notes.model包。
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.net.Uri;
import android.os.RemoteException;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote;
import java.util.ArrayList;
// 定义Note类用于管理便签的数据和操作。
public class Note {
private ContentValues mNoteDiffValues; // 用于存储便签的差异值,用于更新操作。
private NoteData mNoteData; // 存储便签的额外数据,如文本和通话数据。
private static final String TAG = "Note"; // 用于日志输出的标签。
/**
* 便ID便
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
// 创建一个新的便签在数据库中。
ContentValues values = new ContentValues();
long createdTime = System.currentTimeMillis();
values.put(NoteColumns.CREATED_DATE, createdTime); // 设置创建时间。
values.put(NoteColumns.MODIFIED_DATE, createdTime); // 设置修改时间。
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); // 设置便签类型。
values.put(NoteColumns.LOCAL_MODIFIED, 1); // 设置本地修改标志。
values.put(NoteColumns.PARENT_ID, folderId); // 设置父ID即文件夹ID。
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); // 插入便签到数据库。
long noteId = 0;
try {
noteId = Long.valueOf(uri.getPathSegments().get(1)); // 从URI中获取新创建的便签ID。
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString()); // 记录日志如果ID获取失败。
noteId = 0;
}
if (noteId == -1) {
throw new IllegalStateException("Wrong note id:" + noteId); // 如果ID错误抛出异常。
}
return noteId; // 返回新创建的便签ID。
}
public Note() {
mNoteDiffValues = new ContentValues(); // 初始化差异值ContentValues。
mNoteData = new NoteData(); // 初始化便签数据。
}
// 设置便签的值,并标记为本地修改。
public void setNoteValue(String key, String value) {
mNoteDiffValues.put(key, value);
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 设置文本数据。
public void setTextData(String key, String value) {
mNoteData.setTextData(key, value);
}
// 设置文本数据ID。
public void setTextDataId(long id) {
mNoteData.setTextDataId(id);
}
// 获取文本数据ID。
public long getTextDataId() {
return mNoteData.mTextDataId;
}
// 设置通话数据ID。
public void setCallDataId(long id) {
mNoteData.setCallDataId(id);
}
// 设置通话数据。
public void setCallData(String key, String value) {
mNoteData.setCallData(key, value);
}
// 检查是否有本地修改。
public boolean isLocalModified() {
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified();
}
// 同步便签到数据库。
public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
if (!isLocalModified()) {
return true;
}
/**
* 便{@link NoteColumns#LOCAL_MODIFIED}
* {@link NoteColumns#MODIFIED_DATE}使便便
*/
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
Log.e(TAG, "Update note error, should not happen");
// Do not return, fall through
}
mNoteDiffValues.clear();
if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false;
}
return true;
}
// 定义NoteData内部类用于管理便签的文本和通话数据。
private class NoteData {
private long mTextDataId;
private ContentValues mTextDataValues;
private long mCallDataId;
private ContentValues mCallDataValues;
private static final String TAG = "NoteData";
public NoteData() {
mTextDataValues = new ContentValues();
mCallDataValues = new ContentValues();
mTextDataId = 0;
mCallDataId = 0;
}
// 检查是否有本地修改。
boolean isLocalModified() {
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
// 设置文本数据ID。
void setTextDataId(long id) {
if(id <= 0) {
throw new IllegalArgumentException("Text data id should larger than 0");
}
mTextDataId = id;
}
// 设置通话数据ID。
void setCallDataId(long id) {
if (id <= 0) {
throw new IllegalArgumentException("Call data id should larger than 0");
}
mCallDataId = id;
}
// 设置通话数据。
void setCallData(String key, String value) {
mCallDataValues.put(key, value);
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 设置文本数据。
void setTextData(String key, String value) {
mTextDataValues.put(key, value);
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 将数据推送到内容解析器。
Uri pushIntoContentResolver(Context context, long noteId) {
/**
*
*/
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;
if(mTextDataValues.size() > 0) {
mTextDataValues.put(DataColumns.NOTE_ID, noteId);
if (mTextDataId == 0) {
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mTextDataValues);
try {
setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
Log.e(TAG, "Insert new text data fail with noteId" + noteId);
mTextDataValues.clear();
return null;
}
} else {
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId));
builder.withValues(mTextDataValues);
operationList.add(builder.build());
}
mTextDataValues.clear();
}
if(mCallDataValues.size() > 0) {
mCallData

@ -0,0 +1,164 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* MiCodeMiCode
*
* 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
* Apache 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.widget;
// 声明该文件属于net.micode.notes.widget包。
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.util.Log;
import android.widget.RemoteViews;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.ui.NoteEditActivity;
import net.micode.notes.ui.NotesListActivity;
// 定义一个抽象类NoteWidgetProvider继承自AppWidgetProvider用于提供便签应用的小部件功能。
public abstract class NoteWidgetProvider extends AppWidgetProvider {
// 定义一个字符串数组,用于数据库查询时指定需要返回的列。
public static final String [] PROJECTION = new String [] {
NoteColumns.ID,
NoteColumns.BG_COLOR_ID,
NoteColumns.SNIPPET
};
// 定义列索引常量,用于在查询结果中快速定位到特定的列。
public static final int COLUMN_ID = 0;
public static final int COLUMN_BG_COLOR_ID = 1;
public static final int COLUMN_SNIPPET = 2;
// 定义一个标签,用于日志输出时标识日志来源。
private static final String TAG = "NoteWidgetProvider";
// 当小部件被删除时,系统会调用此方法,用于更新数据库中与该小部件相关的记录。
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
ContentValues values = new ContentValues();
values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
for (int i = 0; i < appWidgetIds.length; i++) {
// 更新数据库将被删除小部件的WIDGET_ID设置为INVALID_APPWIDGET_ID。
context.getContentResolver().update(Notes.CONTENT_NOTE_URI,
values,
NoteColumns.WIDGET_ID + "=?",
new String[] { String.valueOf(appWidgetIds[i])});
}
}
// 获取与小部件相关的便签信息的查询结果。
private Cursor getNoteWidgetInfo(Context context, int widgetId) {
return context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?",
new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) },
null);
}
// 更新小部件显示,不包含隐私模式。
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, false);
}
// 更新小部件显示的私有方法,包含隐私模式参数。
private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
boolean privacyMode) {
for (int i = 0; i < appWidgetIds.length; i++) {
if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {
// 获取默认背景ID。
int bgId = ResourceParser.getDefaultBgId(context);
// 初始化便签摘要字符串。
String snippet = "";
// 创建一个Intent用于启动NoteEditActivity。
Intent intent = new Intent(context, NoteEditActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());
// 查询数据库,获取与小部件相关的便签信息。
Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]);
if (c != null && c.moveToFirst()) {
if (c.getCount() > 1) {
// 如果查询结果有多条记录,打印错误日志并返回。
Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]);
c.close();
return;
}
// 从查询结果中获取便签摘要和背景ID。
snippet = c.getString(COLUMN_SNIPPET);
bgId = c.getInt(COLUMN_BG_COLOR_ID);
intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID));
intent.setAction(Intent.ACTION_VIEW);
} else {
// 如果没有查询到记录设置默认摘要文本并设置Intent动作为插入或编辑。
snippet = context.getResources().getString(R.string.widget_havenot_content);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
}
// 关闭查询结果的Cursor。
if (c != null) {
c.close();
}
// 创建RemoteViews对象用于更新小部件视图。
RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId());
// 设置小部件背景资源ID。
rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId));
// 将背景ID作为额外信息传递给Intent。
intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId);
/**
* Generate the pending intent to start host for the widget.
* 宿PendingIntent
*/
PendingIntent pendingIntent = null;
if (privacyMode) {
// 如果启用隐私模式设置小部件文本为隐私模式提示并创建PendingIntent以启动NotesListActivity。
rv.setTextViewText(R.id.widget_text,
context.getString(R.string.widget_under_visit_mode));
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent(
context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
} else {
// 如果不启用隐私模式设置小部件文本为便签摘要并创建PendingIntent以启动NoteEditActivity。
rv.setTextViewText(R.id.widget_text, snippet);
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
// 设置小部件文本视图的点击事件关联到PendingIntent。
rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
// 更新小部件视图。
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
}
}
// 抽象方法子类需要实现用于获取背景资源ID。
protected abstract int getBgResourceId(int bgId);
// 抽象方法子类需要实现用于获取布局资源ID。
protected abstract int getLayoutId();
// 抽象方法,子类需要实现,用于获取小部件类型。
protected abstract int getWidgetType();
}

@ -0,0 +1,144 @@
/*
* 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.widget;
// 导入必要的Android类和界面
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.util.Log;
import android.widget.RemoteViews;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.ui.NoteEditActivity;
import net.micode.notes.ui.NotesListActivity;
// 定义一个抽象类NoteWidgetProvider继承自AppWidgetProvider用于管理Note应用的小部件
public abstract class NoteWidgetProvider extends AppWidgetProvider {
// 定义查询数据库时需要的列
public static final String [] PROJECTION = new String [] {
NoteColumns.ID,
NoteColumns.BG_COLOR_ID,
NoteColumns.SNIPPET
};
// 定义列索引常量
public static final int COLUMN_ID = 0;
public static final int COLUMN_BG_COLOR_ID = 1;
public static final int COLUMN_SNIPPET = 2;
// 定义日志标签
private static final String TAG = "NoteWidgetProvider";
// 当小部件被删除时调用的方法用于更新数据库中的widget_id字段
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
ContentValues values = new ContentValues();
values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
for (int i = 0; i < appWidgetIds.length; i++) {
context.getContentResolver().update(Notes.CONTENT_NOTE_URI,
values,
NoteColumns.WIDGET_ID + "=?",
new String[] { String.valueOf(appWidgetIds[i])});
}
}
// 获取小部件相关的笔记信息
private Cursor getNoteWidgetInfo(Context context, int widgetId) {
return context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?",
new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) },
null);
}
// 更新小部件显示,可以带隐私模式参数
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, false);
}
// 更新小部件显示的私有方法,包含隐私模式参数
private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
boolean privacyMode) {
for (int i = 0; i < appWidgetIds.length; i++) {
if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {
int bgId = ResourceParser.getDefaultBgId(context); // 默认背景ID
String snippet = ""; // 笔记摘要
Intent intent = new Intent(context, NoteEditActivity.class); // 编辑笔记的Intent
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // 设置Intent标志
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); // 附加小部件ID
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); // 附加小部件类型
// 查询数据库获取笔记信息
Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]);
if (c != null && c.moveToFirst()) {
if (c.getCount() > 1) {
Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]);
c.close();
return;
}
snippet = c.getString(COLUMN_SNIPPET); // 获取摘要
bgId = c.getInt(COLUMN_BG_COLOR_ID); // 获取背景ID
intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); // 附加笔记ID
intent.setAction(Intent.ACTION_VIEW); // 设置Intent动作为查看
} else {
snippet = context.getResources().getString(R.string.widget_havenot_content); // 默认提示文本
intent.setAction(Intent.ACTION_INSERT_OR_EDIT); // 设置Intent动作为插入或编辑
}
if (c != null) {
c.close(); // 关闭Cursor
}
// 创建RemoteViews对象用于更新小部件视图
RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId());
rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); // 设置背景资源ID
intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); // 附加背景ID
// 生成PendingIntent用于小部件点击事件
PendingIntent pendingIntent = null;
if (privacyMode) {
rv.setTextViewText(R.id.widget_text, context.getString(R.string.widget_under_visit_mode)); // 隐私模式文本
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent(
context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); // 笔记列表的PendingIntent
} else {
rv.setTextViewText(R.id.widget_text, snippet); // 设置文本内容
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, // 编辑笔记的PendingIntent
PendingIntent.FLAG_UPDATE_CURRENT);
}
rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); // 设置点击事件
appWidgetManager.updateAppWidget(appWidgetIds[i], rv); // 更新小部件
}
}
}
// 抽象方法用于获取背景资源ID
protected abstract int getBgResourceId(int bgId);
// 抽象方法用于获取布局资源ID
protected abstract int getLayoutId();
// 抽象方法,用于获取小部件类型
protected abstract int getWidgetType();
}

@ -0,0 +1,144 @@
/*
* 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.widget;
// 导入必要的Android类和界面
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.util.Log;
import android.widget.RemoteViews;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.ui.NoteEditActivity;
import net.micode.notes.ui.NotesListActivity;
// 定义一个抽象类NoteWidgetProvider继承自AppWidgetProvider用于管理Note应用的小部件
public abstract class NoteWidgetProvider extends AppWidgetProvider {
// 定义查询数据库时需要的列
public static final String [] PROJECTION = new String [] {
NoteColumns.ID,
NoteColumns.BG_COLOR_ID,
NoteColumns.SNIPPET
};
// 定义列索引常量
public static final int COLUMN_ID = 0;
public static final int COLUMN_BG_COLOR_ID = 1;
public static final int COLUMN_SNIPPET = 2;
// 定义日志标签
private static final String TAG = "NoteWidgetProvider";
// 当小部件被删除时调用的方法用于更新数据库中的widget_id字段
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
ContentValues values = new ContentValues();
values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
for (int i = 0; i < appWidgetIds.length; i++) {
context.getContentResolver().update(Notes.CONTENT_NOTE_URI,
values,
NoteColumns.WIDGET_ID + "=?",
new String[] { String.valueOf(appWidgetIds[i])});
}
}
// 获取小部件相关的笔记信息
private Cursor getNoteWidgetInfo(Context context, int widgetId) {
return context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?",
new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) },
null);
}
// 更新小部件显示,可以带隐私模式参数
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, false);
}
// 更新小部件显示的私有方法,包含隐私模式参数
private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
boolean privacyMode) {
for (int i = 0; i < appWidgetIds.length; i++) {
if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {
int bgId = ResourceParser.getDefaultBgId(context); // 默认背景ID
String snippet = ""; // 笔记摘要
Intent intent = new Intent(context, NoteEditActivity.class); // 编辑笔记的Intent
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // 设置Intent标志
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); // 附加小部件ID
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); // 附加小部件类型
// 查询数据库获取笔记信息
Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]);
if (c != null && c.moveToFirst()) {
if (c.getCount() > 1) {
Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]);
c.close();
return;
}
snippet = c.getString(COLUMN_SNIPPET); // 获取摘要
bgId = c.getInt(COLUMN_BG_COLOR_ID); // 获取背景ID
intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); // 附加笔记ID
intent.setAction(Intent.ACTION_VIEW); // 设置Intent动作为查看
} else {
snippet = context.getResources().getString(R.string.widget_havenot_content); // 默认提示文本
intent.setAction(Intent.ACTION_INSERT_OR_EDIT); // 设置Intent动作为插入或编辑
}
if (c != null) {
c.close(); // 关闭Cursor
}
// 创建RemoteViews对象用于更新小部件视图
RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId());
rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); // 设置背景资源ID
intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); // 附加背景ID
// 生成PendingIntent用于小部件点击事件
PendingIntent pendingIntent = null;
if (privacyMode) {
rv.setTextViewText(R.id.widget_text, context.getString(R.string.widget_under_visit_mode)); // 隐私模式文本
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent(
context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); // 笔记列表的PendingIntent
} else {
rv.setTextViewText(R.id.widget_text, snippet); // 设置文本内容
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, // 编辑笔记的PendingIntent
PendingIntent.FLAG_UPDATE_CURRENT);
}
rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); // 设置点击事件
appWidgetManager.updateAppWidget(appWidgetIds[i], rv); // 更新小部件
}
}
}
// 抽象方法用于获取背景资源ID
protected abstract int getBgResourceId(int bgId);
// 抽象方法用于获取布局资源ID
protected abstract int getLayoutId();
// 抽象方法,用于获取小部件类型
protected abstract int getWidgetType();
}

@ -0,0 +1,64 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* MiCode2010-2011
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Apache License 2.0使
* 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.widget;
// 声明该类属于net.micode.notes.widget包。
import android.appwidget.AppWidgetManager;
import android.content.Context;
// 导入Android小部件管理器和上下文相关的类。
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.tool.ResourceParser;
// 导入项目的资源、数据和工具类。
public class NoteWidgetProvider_2x extends NoteWidgetProvider {
// 定义NoteWidgetProvider_2x类继承自NoteWidgetProvider用于提供2x小部件的具体实现。
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// 当小部件需要更新时,系统会调用此方法。
super.update(context, appWidgetManager, appWidgetIds);
// 调用父类的update方法执行更新逻辑。
}
@Override
protected int getLayoutId() {
// 获取小部件的布局资源ID。
return R.layout.widget_2x;
// 返回2x小部件的布局资源ID。
}
@Override
protected int getBgResourceId(int bgId) {
// 根据背景ID获取对应的资源ID。
return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId);
// 使用ResourceParser工具类来获取2x小部件的背景资源ID。
}
@Override
protected int getWidgetType() {
// 获取小部件的类型。
return Notes.TYPE_WIDGET_2X;
// 返回小部件的类型常量,用于区分不同的小部件。
}
}

@ -0,0 +1,64 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
* MiCode2010-2011
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Apache License 2.0使
* 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.widget;
// 声明该类属于net.micode.notes.widget包。
import android.appwidget.AppWidgetManager;
import android.content.Context;
// 导入Android小部件管理器和上下文相关的类。
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.tool.ResourceParser;
// 导入项目的资源、数据和工具类。
public class NoteWidgetProvider_4x extends NoteWidgetProvider {
// 定义NoteWidgetProvider_4x类继承自NoteWidgetProvider用于提供4x小部件的具体实现。
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// 当小部件需要更新时,系统会调用此方法。
super.update(context, appWidgetManager, appWidgetIds);
// 调用父类的update方法执行更新逻辑。
}
@Override
protected int getLayoutId() {
// 获取小部件的布局资源ID。
return R.layout.widget_4x;
// 返回4x小部件的布局资源ID。
}
@Override
protected int getBgResourceId(int bgId) {
// 根据背景ID获取对应的资源ID。
return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId);
// 使用ResourceParser工具类来获取4x小部件的背景资源ID。
}
@Override
protected int getWidgetType() {
// 获取小部件的类型。
return Notes.TYPE_WIDGET_4X;
// 返回小部件的类型常量,用于区分不同的小部件。
}
}

@ -0,0 +1,209 @@
/*
* 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.tool; // 声明该Java文件所在的包名
import android.content.Context; // 导入Android的Context类用于访问应用的特定资源和类以及调用应用级操作
import android.preference.PreferenceManager; // 导入Android的PreferenceManager类用于访问应用的默认SharedPreferences
import net.micode.notes.R; // 导入应用自己的资源类
import net.micode.notes.ui.NotesPreferenceActivity; // 导入应用的NotesPreferenceActivity类
public class ResourceParser { // 声明一个公共类ResourceParser
// 定义几种颜色常量
public static final int YELLOW = 0; // 黄色
public static final int BLUE = 1; // 蓝色
public static final int WHITE = 2; // 白色
public static final int GREEN = 3; // 绿色
public static final int RED = 4; // 红色
// 默认背景颜色
public static final int BG_DEFAULT_COLOR = YELLOW;
// 定义几种字体大小常量
public static final int TEXT_SMALL = 0; // 小号字体
public static final int TEXT_MEDIUM = 1; // 中号字体
public static final int TEXT_LARGE = 2; // 大号字体
public static final int TEXT_SUPER = 3; // 特大号字体
// 默认字体大小
public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM;
// 内部类,用于管理笔记背景资源
public static class NoteBgResources {
// 笔记编辑背景资源数组
private final static int [] BG_EDIT_RESOURCES = new int [] {
R.drawable.edit_yellow,
R.drawable.edit_blue,
R.drawable.edit_white,
R.drawable.edit_green,
R.drawable.edit_red
};
// 笔记编辑标题背景资源数组
private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] {
R.drawable.edit_title_yellow,
R.drawable.edit_title_blue,
R.drawable.edit_title_white,
R.drawable.edit_title_green,
R.drawable.edit_title_red
};
// 根据ID获取笔记背景资源
public static int getNoteBgResource(int id) {
return BG_EDIT_RESOURCES[id];
}
// 根据ID获取笔记标题背景资源
public static int getNoteTitleBgResource(int id) {
return BG_EDIT_TITLE_RESOURCES[id];
}
}
// 根据用户的偏好设置获取默认背景颜色ID
public static int getDefaultBgId(Context context) {
// 检查用户是否设置了背景颜色偏好
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) {
// 如果设置了则随机选择一个背景颜色ID
return (int) (Math.random() * NoteBgResources.BG_EDIT_RESOURCES.length);
} else {
// 否则返回默认的背景颜色ID
return BG_DEFAULT_COLOR;
}
}
// 内部类,用于管理笔记条目背景资源
public static class NoteItemBgResources {
// 笔记条目第一个背景资源数组
private final static int [] BG_FIRST_RESOURCES = new int [] {
R.drawable.list_yellow_up,
R.drawable.list_blue_up,
R.drawable.list_white_up,
R.drawable.list_green_up,
R.drawable.list_red_up
};
// 笔记条目普通背景资源数组
private final static int [] BG_NORMAL_RESOURCES = new int [] {
R.drawable.list_yellow_middle,
R.drawable.list_blue_middle,
R.drawable.list_white_middle,
R.drawable.list_green_middle,
R.drawable.list_red_middle
};
// 笔记条目最后一个背景资源数组
private final static int [] BG_LAST_RESOURCES = new int [] {
R.drawable.list_yellow_down,
R.drawable.list_blue_down,
R.drawable.list_white_down,
R.drawable.list_green_down,
R.drawable.list_red_down,
};
// 笔记条目单个背景资源数组
private final static int [] BG_SINGLE_RESOURCES = new int [] {
R.drawable.list_yellow_single,
R.drawable.list_blue_single,
R.drawable.list_white_single,
R.drawable.list_green_single,
R.drawable.list_red_single
};
// 根据ID获取笔记条目第一个背景资源
public static int getNoteBgFirstRes(int id) {
return BG_FIRST_RESOURCES[id];
}
// 根据ID获取笔记条目最后一个背景资源
public static int getNoteBgLastRes(int id) {
return BG_LAST_RESOURCES[id];
}
// 根据ID获取笔记条目单个背景资源
public static int getNoteBgSingleRes(int id) {
return BG_SINGLE_RESOURCES[id];
}
// 根据ID获取笔记条目普通背景资源
public static int getNoteBgNormalRes(int id) {
return BG_NORMAL_RESOURCES[id];
}
// 获取文件夹背景资源
public static int getFolderBgRes() {
return R.drawable.list_folder;
}
}
// 内部类,用于管理小部件背景资源
public static class WidgetBgResources {
// 小部件2x背景资源数组
private final static int [] BG_2X_RESOURCES = new int [] {
R.drawable.widget_2x_yellow,
R.drawable.widget_2x_blue,
R.drawable.widget_2x_white,
R.drawable.widget_2x_green,
R.drawable.widget_2x_red,
};
// 根据ID获取小部件2x背景资源
public static int getWidget2xBgResource(int id) {
return BG_2X_RESOURCES[id];
}
// 小部件4x背景资源数组
private final static int [] BG_4X_RESOURCES = new int [] {
R.drawable.widget_4x_yellow,
R.drawable.widget_4x_blue,
R.drawable.widget_4x_white,
R.drawable.widget_4x_green,
R.drawable.widget_4x_red
};
// 根据ID获取小部件4x背景资源
public static int getWidget4xBgResource(int id) {
return BG_4X_RESOURCES[id];
}
}
// 内部类,用于管理文本外观资源
public static class TextAppearanceResources {
// 文本外观资源数组
private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] {
R.style.TextAppearanceNormal,
R.style.TextAppearanceMedium,
R.style.TextAppearanceLarge,
R.style.TextAppearanceSuper
};
// 根据ID获取文本外观资源
public static int getTexAppearanceResource(int id) {
// 如果ID超出资源数组长度则返回默认字体大小
if (id >= TEXTAPPEARANCE_RESOURCES.length) {
return BG_DEFAULT_FONT_SIZE;
}
return TEXTAPPEARANCE_RESOURCES[id];
}
// 获取文本外观资源数组的大小
public static int getResourcesSize() {
return TEXTAPPEARANCE_RESOURCES.length;
}
}
}

@ -0,0 +1,204 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Apache License 2.0使
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
*
*/
package net.micode.notes.tool; // 声明包名
import android.content.Context; // 导入Context类用于访问应用的环境信息
import android.preference.PreferenceManager; // 导入PreferenceManager类用于访问应用的偏好设置
import net.micode.notes.R; // 导入R类访问应用的资源
import net.micode.notes.ui.NotesPreferenceActivity; // 导入NotesPreferenceActivity类用于设置应用的偏好
public class ResourceParser { // 声明ResourceParser类
// 定义笔记背景颜色的常量
public static final int YELLOW = 0; // 黄色
public static final int BLUE = 1; // 蓝色
public static final int WHITE = 2; // 白色
public static final int GREEN = 3; // 绿色
public static final int RED = 4; // 红色
// 默认背景颜色为黄色
public static final int BG_DEFAULT_COLOR = YELLOW;
// 定义文本大小的常量
public static final int TEXT_SMALL = 0; // 小号文本
public static final int TEXT_MEDIUM = 1; // 中号文本
public static final int TEXT_LARGE = 2; // 大号文本
public static final int TEXT_SUPER = 3; // 超大号文本
// 默认文本大小为中号
public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM;
// 声明内部类NoteBgResources用于管理笔记背景资源
public static class NoteBgResources {
// 定义编辑状态下的背景资源数组
private final static int [] BG_EDIT_RESOURCES = new int [] {
R.drawable.edit_yellow,
R.drawable.edit_blue,
R.drawable.edit_white,
R.drawable.edit_green,
R.drawable.edit_red
};
// 定义编辑状态下的标题背景资源数组
private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] {
R.drawable.edit_title_yellow,
R.drawable.edit_title_blue,
R.drawable.edit_title_white,
R.drawable.edit_title_green,
R.drawable.edit_title_red
};
// 根据id获取编辑状态下的背景资源
public static int getNoteBgResource(int id) {
return BG_EDIT_RESOURCES[id];
}
// 根据id获取编辑状态下的标题背景资源
public static int getNoteTitleBgResource(int id) {
return BG_EDIT_TITLE_RESOURCES[id];
}
}
// 根据用户偏好或默认设置获取默认背景颜色的id
public static int getDefaultBgId(Context context) {
// 如果用户设置了背景颜色则随机选择一个颜色id
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) {
return (int) (Math.random() * NoteBgResources.BG_EDIT_RESOURCES.length);
} else {
// 否则返回默认颜色id
return BG_DEFAULT_COLOR;
}
}
// 声明内部类NoteItemBgResources用于管理笔记条目背景资源
public static class NoteItemBgResources {
// 定义列表项第一个位置的背景资源数组
private final static int [] BG_FIRST_RESOURCES = new int [] {
R.drawable.list_yellow_up,
R.drawable.list_blue_up,
R.drawable.list_white_up,
R.drawable.list_green_up,
R.drawable.list_red_up
};
// 定义列表项中间位置的背景资源数组
private final static int [] BG_NORMAL_RESOURCES = new int [] {
R.drawable.list_yellow_middle,
R.drawable.list_blue_middle,
R.drawable.list_white_middle,
R.drawable.list_green_middle,
R.drawable.list_red_middle
};
// 定义列表项最后一个位置的背景资源数组
private final static int [] BG_LAST_RESOURCES = new int [] {
R.drawable.list_yellow_down,
R.drawable.list_blue_down,
R.drawable.list_white_down,
R.drawable.list_green_down,
R.drawable.list_red_down,
};
// 定义列表项为单个条目时的背景资源数组
private final static int [] BG_SINGLE_RESOURCES = new int [] {
R.drawable.list_yellow_single,
R.drawable.list_blue_single,
R.drawable.list_white_single,
R.drawable.list_green_single,
R.drawable.list_red_single
};
// 根据id获取列表项第一个位置的背景资源
public static int getNoteBgFirstRes(int id) {
return BG_FIRST_RESOURCES[id];
}
// 根据id获取列表项最后一个位置的背景资源
public static int getNoteBgLastRes(int id) {
return BG_LAST_RESOURCES[id];
}
// 根据id获取列表项为单个条目时的背景资源
public static int getNoteBgSingleRes(int id) {
return BG_SINGLE_RESOURCES[id];
}
// 根据id获取列表项中间位置的背景资源
public static int getNoteBgNormalRes(int id) {
return BG_NORMAL_RESOURCES[id];
}
// 获取文件夹的背景资源
public static int getFolderBgRes() {
return R.drawable.list_folder;
}
}
// 声明内部类WidgetBgResources用于管理小部件背景资源
public static class WidgetBgResources {
// 定义2x大小的小部件背景资源数组
private final static int [] BG_2X_RESOURCES = new int [] {
R.drawable.widget_2x_yellow,
R.drawable.widget_2x_blue,
R.drawable.widget_2x_white,
R.drawable.widget_2x_green,
R.drawable.widget_2x_red,
};
// 根据id获取2x大小的小部件背景资源
public static int getWidget2xBgResource(int id) {
return BG_2X_RESOURCES[id];
}
// 定义4x大小的小部件背景资源数组
private final static int [] BG_4X_RESOURCES = new int [] {
R.drawable.widget_4x_yellow,
R.drawable.widget_4x_blue,
R.drawable.widget_4x_white,
R.drawable.widget_4x_green,
R.drawable.widget_4x_red
};
// 根据id获取4x大小的小部件背景资源
public static int getWidget4xBgResource(int id) {
return BG_4X_RESOURCES[id];
}
}
// 声明内部类TextAppearanceResources用于管理文本外观资源
public static class TextAppearanceResources {
// 定义文本外观资源数组
private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] {
R.style.TextAppearanceNormal,
R.style.TextAppearanceMedium,
R.style.TextAppearanceLarge,
R.style.TextAppearanceSuper
};
// 根据id获取文本外观资源
// 如果id超出资源数组长度则返回默认文本大小
public static int getTexAppearanceResource(int id) {
if (id >= TEXTAPPEARANCE_RESOURCES.length) {
return BG_DEFAULT_FONT_SIZE;
}
return TEXTAPPEARANCE_RESOURCES[id];
}
// 获取文本外观资源数组的大小
public static int getResourcesSize() {
return TEXTAPPEARANCE_RESOURCES.length;
}
}
}

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- XML声明指定文档版本为1.0编码格式为UTF-8 -->
<!--
Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
版权信息版权归2010-2011年MiCode开源社区所有网址www.micode.net
Licensed under the Apache License, Version 2.0 (the "License");
许可信息此文件受Apache License 2.0版(“许可证”)许可
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.
请参阅许可证以了解有关权限和许可证下限制的特定条款
-->
<LinearLayout
android:layout_width="fill_parent"
<!-- 布局宽度设为填充父容器 -->
android:layout_height="fill_parent"
<!-- 布局高度设为填充父容器 -->
android:orientation="vertical"
<!-- 布局方向为垂直 -->
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义Android命名空间 -->
<TextView
android:id="@+id/account_dialog_title"
<!-- 设置TextView的ID为account_dialog_title -->
style="?android:attr/textAppearanceMedium"
<!-- 应用中等外观的文本样式 -->
android:singleLine="true"
<!-- 文本设置为单行显示 -->
android:ellipsize="end"
<!-- 如果文本过长,则在末尾省略显示 -->
android:gravity="center"
<!-- 文本在TextView中居中显示 -->
android:layout_marginTop="-2.7dip"
<!-- 上边距设为-2.7密度无关像素 -->
android:layout_marginBottom="-2.7dip"
<!-- 下边距设为-2.7密度无关像素 -->
android:layout_width="fill_parent"
<!-- 宽度设为填充父容器 -->
android:layout_height="wrap_content"/>
<!-- 高度设为包裹内容 -->
<TextView
android:id="@+id/account_dialog_subtitle"
<!-- 设置TextView的ID为account_dialog_subtitle -->
android:layout_width="fill_parent"
<!-- 宽度设为填充父容器 -->
android:layout_height="wrap_content"
<!-- 高度设为包裹内容 -->
android:layout_marginTop="5dip"
<!-- 上边距设为5密度无关像素 -->
android:layout_marginBottom="1dip"
<!-- 下边距设为1密度无关像素 -->
android:gravity="center"/>
<!-- 文本在TextView中居中显示 -->
</LinearLayout>

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- XML声明指定文档版本为1.0编码格式为UTF-8 -->
<!--
Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
版权信息版权归2010-2011年MiCode开源社区所有网址www.micode.net
Licensed under the Apache License, Version 2.0 (the "License");
许可信息此文件受Apache License 2.0版(“许可证”)许可
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.
请参阅许可证以了解有关权限和许可证下限制的特定条款
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义颜色选择器,用于在不同状态下改变颜色 -->
<!-- 当按钮或视图被按下时,应用半透明的深灰色(#88555555 -->
<item android:state_pressed="true" android:color="#88555555" />
<!-- 当按钮或视图被选中时,应用半透明的浅灰色(#ff999999 -->
<item android:state_selected="true" android:color="#ff999999" />
<!-- 默认情况下,应用不透明的黑色(#ff000000 -->
<item android:color="#ff000000" />
</selector>
Loading…
Cancel
Save