final代码

main
LQS 10 months ago
parent 2d8057d35a
commit dd1fa99e75

@ -1,26 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.micode.notes"
android:versionCode="1"
android:versionName="0.1" >
android:versionName="0.1">
<uses-sdk android:minSdkVersion="14" />
<uses-sdk android:minSdkVersion="21" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
@ -33,8 +17,49 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:icon="@drawable/icon_app"
android:label="@string/app_name" >
android:icon="@drawable/icon_app_new"
android:label="@string/app_name">
<activity
android:name=".ui.SplashActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/Theme.Note.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.LoginActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/app_name" android:launchMode="singleTop" android:theme="@style/NoteTheme" android:windowSoftInputMode="adjustPan">
<!-- android:uiOptions="splitActionBarWhenNarrow" -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".ui.ChangePassword"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan">
</activity>
<activity
android:name=".ui.CreatePassword"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan">
</activity>
<activity
android:name=".ui.DeletePassword"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan">
</activity>
<activity
android:name=".ui.NotesListActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
@ -44,34 +69,32 @@
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="adjustPan" >
<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" >
android:theme="@style/NoteTheme">
<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>
@ -81,13 +104,13 @@
</activity>
<provider
android:name="net.micode.notes.data.NotesProvider"
android:name=".data.NotesProvider"
android:authorities="micode_notes"
android:multiprocess="true" />
<receiver
android:name=".widget.NoteWidgetProvider_2x"
android:label="@string/app_widget2x2" >
android:label="@string/app_widget2x2">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
@ -100,8 +123,7 @@
</receiver>
<receiver
android:name=".widget.NoteWidgetProvider_4x"
android:label="@string/app_widget4x4" >
android:label="@string/app_widget4x4">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
@ -112,39 +134,32 @@
android:name="android.appwidget.provider"
android:resource="@xml/widget_4x_info" />
</receiver>
<receiver android:name=".ui.AlarmInitReceiver" >
<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>
android:name=".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>
android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"></activity>
<activity
android:name="net.micode.notes.ui.NotesPreferenceActivity"
android:name=".ui.NotesPreferenceActivity"
android:label="@string/preferences_title"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Holo.Light" >
</activity>
android:theme="@android:style/Theme.Holo.Light"></activity>
<service
android:name="net.micode.notes.gtask.remote.GTaskSyncService"
android:exported="false" >
</service>
android:name=".gtask.remote.GTaskSyncService"
android:exported="false"></service>
<meta-data
android:name="android.app.default_searchable"
android:value=".ui.NoteEditActivity" />
</application>
</manifest>
</manifest>

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="输入原有密码:"/>
<EditText
android:id="@+id/old_password"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="输入新建密码:"/>
<EditText
android:id="@+id/new_password"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="再次输入密码:"/>
<EditText
android:id="@+id/ack_password"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<Button
android:id="@+id/Bt_Acknowledged"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确认"/>
</LinearLayout>
</LinearLayout>

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="输入原有密码:"/>
<EditText
android:id="@+id/old_password"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<Button
android:id="@+id/Bt_Acknowledged"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确认"/>
</LinearLayout>
</LinearLayout>

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical">
<!-- <LinearLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:gravity="center">-->
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="用户:"/>-->
<!-- <EditText-->
<!-- android:id="@+id/lg_user"-->
<!-- android:layout_width="150dp"-->
<!-- android:layout_height="wrap_content" />-->
<!-- </LinearLayout>-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:"/>
<EditText
android:id="@+id/lg_password"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录"/>
<!-- <Button-->
<!-- android:id="@+id/lg_registered"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="注册"/>-->
</LinearLayout>
</LinearLayout>

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="新建密码:"/>
<EditText
android:id="@+id/rg_password01"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确认密码:"/>
<EditText
android:id="@+id/rg_password02"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<Button
android:id="@+id/rg_registered"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确认"/>
</LinearLayout>
</LinearLayout>

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/fullscreenBackgroundColor"
android:theme="@style/ThemeOverlay.Note.FullscreenContainer"
tools:context=".ui.SplashActivity">
<!-- The primary full-screen view. This can be replaced with whatever view
is needed to present your content, e.g. VideoView, SurfaceView,
TextureView, etc. -->
<TextView
android:id="@+id/fullscreen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/splash"
android:gravity="center"
android:keepScreenOn="true"
android:text="@string/dummy_content"
android:textColor="?attr/fullscreenTextColor"
android:textSize="50sp"
android:textStyle="bold" />
<!-- This FrameLayout insets its children based on system windows using
android:fitsSystemWindows. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/fullscreen_content_controls"
style="@style/Widget.Theme.Note.ButtonBar.Fullscreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal"
tools:ignore="UselessParent">
<Button
android:id="@+id/dummy_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dummy_button" />
</LinearLayout>
</FrameLayout>
</FrameLayout>

@ -31,6 +31,17 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/translate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#2196F3"
android:text="翻译" />
<ImageButton
android:id="@+id/add_img_btn"
android:layout_width="45dp"
android:layout_height="match_parent"
android:src="@android:drawable/ic_menu_gallery" />
<TextView
android:id="@+id/tv_modified_date"
android:layout_width="0dip"
@ -47,6 +58,13 @@
android:layout_gravity="center_vertical"
android:background="@drawable/title_alert" />
<TextView
android:id="@+id/text_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:layout_marginRight="8dip" />
<TextView
android:id="@+id/tv_alert_date"
android:layout_width="wrap_content"
@ -107,6 +125,7 @@
android:layout_marginLeft="-10dip"
android:visibility="gone" />
</LinearLayout>
</ScrollView>
<ImageView

@ -18,8 +18,9 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/list_background">
android:layout_height="fill_parent">
<!-- android:background="@drawable/list_background"> -->
<LinearLayout
android:layout_width="fill_parent"

@ -49,4 +49,13 @@
<item
android:id="@+id/menu_delete_remind"
android:title="@string/menu_remove_remind" />
<item
android:id="@+id/menu_font_setting"
android:title="@string/menu_font_setting"/> />
<item
android:id="@+id/menu_revoke"
android:title="@string/menu_revoke"/>
<item
android:id="@+id/menu_voice_speech"
android:title="@string/menu_voice_speech" />
</menu>

@ -32,8 +32,33 @@
<item
android:id="@+id/menu_setting"
android:title="@string/menu_setting" />
<item
android:id="@+id/menu_search"
android:title="@string/menu_search"/>
<!-- Background image switching -->
<item
android:id="@+id/menu_switch_to_picture1"
android:title="@string/menu_switch_to_picture1"/>
<item
android:id="@+id/menu_switch_to_picture2"
android:title="@string/menu_switch_to_picture2"/>
<item
android:id="@+id/menu_switch_to_picture3"
android:title="@string/menu_switch_to_picture3"/>
<item
android:id="@+id/menu_secret"
android:title="@string/menu_secret"/>
<item
android:id="@+id/menu_quit_secret"
android:title="@string/menu_quit_secret" />
<item
android:id="@+id/menu_createlogin"
android:title="@string/menu_createlogin" />
<item
android:id="@+id/menu_deletelogin"
android:title="@string/menu_deletelogin" />
<item
android:id="@+id/menu_changelogin"
android:title="@string/menu_changelogin" />
</menu>

@ -0,0 +1,7 @@
<resources>
<style name="ThemeOverlay.Note.FullscreenContainer" parent="">
<item name="fullscreenBackgroundColor">@color/light_blue_900</item>
<item name="fullscreenTextColor">@color/light_blue_A400</item>
</style>
</resources>

@ -122,5 +122,19 @@
<plurals name="search_results_title">
<item quantity="other"><xliff:g id="NUMBER">%1$s</xliff:g> 条符合“<xliff:g id="SEARCH">%2$s</xliff:g>”的搜索结果</item>
</plurals>
<string name="menu_revoke">撤销</string>
//中文
<string name="tips_of_revoke">提示</string>
<string name="can_not_revoke">您不能再执行撤销了</string>
<string name="have_not_input_anything">您还没有输入任何内容</string>
<string name="menu_voice_speech">朗读</string>
<string name="menu_font_setting">设置字体</string>
<string name="menu_switch_to_picture1">切换背景1</string>
<string name="menu_switch_to_picture2">切换背景2</string>
<string name="menu_switch_to_picture3">切换背景3</string>
<string name="menu_secret">私密模式</string>
<string name="menu_quit_secret">退出私密模式</string>
<string name="menu_createlogin">新建登录密码</string>
<string name="menu_deletelogin">删除登录密码</string>
<string name="menu_changelogin">修改登录密码</string>
</resources>

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)

@ -0,0 +1,6 @@
<resources>
<declare-styleable name="FullscreenAttrs">
<attr name="fullscreenBackgroundColor" format="color" />
<attr name="fullscreenTextColor" format="color" />
</declare-styleable>
</resources>

@ -17,4 +17,9 @@
<resources>
<color name="user_query_highlight">#335b5b5b</color>
<color name="light_blue_600">#FF039BE5</color>
<color name="light_blue_900">#FF01579B</color>
<color name="light_blue_A200">#FF40C4FF</color>
<color name="light_blue_A400">#FF00B0FF</color>
<color name="black_overlay">#66000000</color>
</resources>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="translate" type="id" />
<item name="num_word" type="id" />
<item name="iatBtn" type="id" />
</resources>

@ -15,8 +15,7 @@
limitations under the License.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Notes</string>
<string name="app_widget2x2">Notes 2x2</string>
<string name="app_widget4x4">Notes 4x4</string>
@ -39,6 +38,12 @@
<string name="file_path">/MIUI/notes/</string>
<string name="file_name_txt_format">notes_%s.txt</string>
<!-- notes list string -->
<!-- Background Switch -->
<string name="menu_switch_to_picture1">Switch_to_picture1</string>
<string name="menu_switch_to_picture2">Switch_to_picture2</string>
<string name="menu_switch_to_picture3">Switch_to_picture3</string>
<string name="format_folder_files_count">(%d)</string>
<string name="menu_create_folder">New Folder</string>
<string name="menu_export_text">Export text</string>
@ -127,9 +132,26 @@
<string name="datetime_dialog_ok">set</string>
<string name="datetime_dialog_cancel">cancel</string>
<plurals name="search_results_title">
<item quantity="one"><xliff:g id="number" example="1">%1$s</xliff:g> result for \"<xliff:g id="search" example="???">%2$s</xliff:g>\"</item>
<item quantity="one"><xliff:g example="1" id="number">%1$s</xliff:g> result for \"<xliff:g example="???" id="search">%2$s</xliff:g>\"</item>
<!-- Case of 0 or 2 or more results. -->
<item quantity="other"><xliff:g id="number" example="15">%1$s</xliff:g> results for \"<xliff:g id="search" example="???">%2$s</xliff:g>\"</item>
<item quantity="other"><xliff:g example="15" id="number">%1$s</xliff:g> results for \"<xliff:g example="???" id="search">%2$s</xliff:g>\"</item>
</plurals>
<string name="title_activity_fullscneen">FullscreenActivity</string>
<string name="dumny_button">Dummy Button</string>
<string name="dummy_content">写下你的快乐</string>
<string name="title_activity_splash">SplashActivity</string>
<string name="dummy_button" />
<string name="menu_revoke">Revoke</string>
<string name="menu_font_setting">Set font</string>
<string name="menu_voice_speech">voice speech</string>
<string name="tips_of_revoke">Tips</string>
<string name="can_not_revoke">You can not revoke any more</string>
<string name="have_not_input_anything">You haven not input anything</string>
<string name="menu_secret">Set_secret</string>
<string name="menu_quit_secret">Quit_secret</string>
<string name="menu_createlogin">CreateLogin</string>
<string name="menu_deletelogin">Deletelogin</string>
<string name="menu_changelogin">Changelogin</string>
</resources>

@ -16,18 +16,22 @@
-->
<resources>
<style name="TextAppearanceSuper">
<item name="android:textSize">@dimen/text_font_size_super</item>
<item name="android:textColorLink">#0000ff</item>
<item name="android:textColorLink">#002AFF</item>
</style>
<style name="TextAppearanceLarge">
<item name="android:textSize">@dimen/text_font_size_large</item>
<item name="android:textColorLink">#0000ff</item>
<item name="android:textColorLink">#B90000FF</item>
</style>
<style name="TextAppearanceMedium">
<item name="android:textSize">@dimen/text_font_size_medium</item>
<item name="android:textColorLink">#0000ff</item>
</style>
<style name="TextAppearanceNormal">
<item name="android:textSize">@dimen/text_font_size_normal</item>
<item name="android:textColorLink">#0000ff</item>
@ -35,7 +39,7 @@
<style name="TextAppearancePrimaryItem">
<item name="android:textSize">@dimen/text_font_size_normal</item>
<item name="android:textColor">@color/primary_text_dark</item>
<item name="android:textColor">@color/secondary_text_dark</item>
</style>
<style name="TextAppearanceSecondaryItem">
@ -49,7 +53,7 @@
</style>
<style name="HighlightTextAppearancePrimary">
<item name="android:textSize">@dimen/text_font_size_normal</item>
<item name="android:textSize">@dimen/text_font_size_normal</item>
<item name="android:textColor">@color/primary_text_dark</item>
</style>
@ -64,6 +68,15 @@
<style name="NoteActionBarStyle" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
<item name="android:displayOptions" />
<item name="android:visibility">gone</item>
<item name="android:visibility">visible</item>
</style>
<style name="Widget.Theme.Note.ActionBar.Fullscreen" parent="Widget.AppCompat.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
<style name="Widget.Theme.Note.ButtonBar.Fullscreen" parent="">
<item name="android:background">@color/black_overlay</item>
<item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item>
</style>
</resources>

@ -0,0 +1,15 @@
<resources>
<style name="Theme.Note" parent="Theme.AppCompat.Light" />
<style name="Theme.Note.Fullscreen" parent="Theme.Note">
<item name="android:actionBarStyle">@style/Widget.Theme.Note.ActionBar.Fullscreen</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@null</item>
</style>
<style name="ThemeOverlay.Note.FullscreenContainer" parent="">
<item name="fullscreenBackgroundColor">@color/light_blue_600</item>
<item name="fullscreenTextColor">@color/light_blue_A200</item>
</style>
</resources>

@ -36,19 +36,18 @@ import java.util.HashMap;
*/
public class Contact {
private static HashMap<String, String> sContactCache;//定义了一个静态的HashMap变量sContactCache
private static final String TAG = "Contact";//定义了一个静态的字符串常量TAG
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 "
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"
+ " AND " + Data.RAW_CONTACT_ID + " IN "
+ "(SELECT raw_contact_id "
+ " FROM phone_lookup"
+ " WHERE min_match = '+')";
/*
*CALLER_ID_SELECTION,
*使PHONE_NUMBERS_EQUAL,使ID.
*/
*/
/**
* getContact,

@ -53,168 +53,168 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static NotesDatabaseHelper mInstance;
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";//这是用于创建便签表的SQL语句定义了便签表的结构包含便签各种属性和字段存储了用户创建的所有便签的信息。
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";//这是用于创建便签表的SQL语句定义了便签表的结构包含便签各种属性和字段存储了用户创建的所有便签的信息。
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";//这是用于定义数据表结构的SQL语句存储了与便签相关的数据信息包括了各种附加数据用来扩展便签功能。
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";//这是用于定义数据表结构的SQL语句存储了与便签相关的数据信息包括了各种附加数据用来扩展便签功能。
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
/**
* 便便
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
"CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
/**
* 便便
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
/**
* 便便
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
/**
* 便便
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
/**
* 便{@link DataConstants#NOTE}
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
/**
* Update note's content when data with {@link DataConstants#NOTE} type has changed
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
/**
* Update note's content when data with {@link DataConstants#NOTE} type has deleted
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END";
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END";
/**
* 便
*/
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END";
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END";
/**
* 便
*/
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
/**
* 便
*/
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);

@ -29,22 +29,14 @@ import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import net.micode.notes.R;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
import net.micode.notes.R;//包含了应用程序的资源文件(如布局、图片等)
import net.micode.notes.data.Notes.DataColumns;//定义了一些常量,表示数据库表的列名。
import net.micode.notes.data.Notes.NoteColumns;//定义了一些常量,表示笔记表的列名。
import net.micode.notes.data.NotesDatabaseHelper.TABLE;//定义了一个枚举类型,表示数据库表的名称。
/**
* @Package: net.micode.notes.data
* @ClassName: NotesProvider
* @Description:
* ContentProvider,便,
*
* @Author: Dong Jiaqi
* @CreateDate: 12/23/2023 2327 PM
*/
public class NotesProvider extends ContentProvider {
private static final UriMatcher mMatcher;
public class NotesProvider extends ContentProvider {//android中的ContentProvider类
private static final UriMatcher mMatcher;//riMatcher是Android中的一个类用于匹配URI。
private NotesDatabaseHelper mHelper;
@ -58,70 +50,54 @@ public class NotesProvider extends ContentProvider {
private static final int URI_SEARCH = 5;
private static final int URI_SEARCH_SUGGEST = 6;
/**
* UriMatcher
* addURI()mMatcherUriMatcher
*/
static {
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);//
//创建一个UriMatcher对象mMatcher初始值为UriMatcher.NO_MATCH表示没有任何匹配规则。
mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE);
//第一个参数是authority授权第二个参数是路径第三个参数是匹配的URI类型。
mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA);
mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH);
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST);
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST);
}
}//根据不同的URI路径确定应该调用哪个处理程序来处理请求
//例如,当用户访问"http://example.com/note"时mMatcher会匹配到第一个规则
/**
* x'0A' represents the '\n' character in sqlite. For title and content in the search result,
* we will trim '\n' and white space in order to show more information.
*/
private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + ","
+ NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + ","
+ R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + ","
+ "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + ","
+ "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA;
private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + ","
+ NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + ","
+ R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + ","
+ "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + ","
+ "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA;
//用于搜索笔记的投影字段列表。这个投影字段列表可以用于构建SQL查询语句以便在数据库中搜索和检索相关笔记。
private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION
+ " FROM " + TABLE.NOTE
+ " FROM " + TABLE.NOTE//从名为TABLE.NOTE的表中检索数据
+ " WHERE " + NoteColumns.SNIPPET + " LIKE ?"
+ " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
+ " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
/**
* onCreate()
* @return true
*/
//是一个SQL查询语句用于从数据库中检索与给定搜索条件匹配的笔记
@Override
public boolean onCreate() {
mHelper = NotesDatabaseHelper.getInstance(getContext());
return true;
}
/**
* query(),URI,
* @param uri URI
* @param projection
* @param selection
* @param selectionArgs selection
* @param sortOrder
* @return (Cursor)(c)
*/
@Override
//查询uri在数据库的位置
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
Cursor c = null;
//获取可读数据库
SQLiteDatabase db = mHelper.getReadableDatabase();
String id = null;
/**
* switchURI
* 3URIURIILLegalArgumentExceptionURI
* URIURIAndroid ContentProvider
*/
switch (mMatcher.match(uri)) {
//匹配数据库中相应条目
case URI_NOTE:
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder);
@ -143,6 +119,7 @@ public class NotesProvider extends ContentProvider {
case URI_SEARCH:
case URI_SEARCH_SUGGEST:
if (sortOrder != null || projection != null) {
//异常情况
throw new IllegalArgumentException(
"do not specify sortOrder, selection, selectionArgs, or projection" + "with this query");
}
@ -160,11 +137,6 @@ public class NotesProvider extends ContentProvider {
return null;
}
/**
* URI_SEARCH URI_SEARCH_SUGGEST rawQuery Cursor
* IllegalStateException Log.e() 便
*
*/
try {
searchString = String.format("%%%s%%", searchString);
c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY,
@ -182,17 +154,13 @@ public class NotesProvider extends ContentProvider {
return c;
}
/**
* URI
* @param uri URI
* @param values
* @return URIContentUris.withAppendedId(uri, insertedId)
*/
@Override
//插入uri
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = mHelper.getWritableDatabase();
long dataId = 0, noteId = 0, insertedId = 0;
SQLiteDatabase db = mHelper.getWritableDatabase();//获取可写的数据库
long dataId = 0, noteId = 0, insertedId = 0;//初始化
switch (mMatcher.match(uri)) {
//新增条目
case URI_NOTE:
insertedId = noteId = db.insert(TABLE.NOTE, null, values);
break;
@ -208,6 +176,7 @@ public class NotesProvider extends ContentProvider {
throw new IllegalArgumentException("Unknown URI " + uri);
}
// Notify the note uri
//通知Android系统中的Notes应用程序某个笔记或数据已经发生了变化
if (noteId > 0) {
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);
@ -218,18 +187,15 @@ public class NotesProvider extends ContentProvider {
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);
}
//它通过调用getContentResolver().notifyChange()方法来实现这个功能。
//在这段代码中首先检查noteId和dataId是否大于0以确保它们是有效的ID。然后使用ContentUris.withAppendedId()方法来构建对应的URI
// 其中Notes.CONTENT_NOTE_URI和Notes.CONTENT_DATA_URI分别表示笔记和数据的URI。
// 最后调用getContext().getContentResolver().notifyChange()方法并传入构建好的URI以通知系统该URI所对应的资源已经发生了变化。
return ContentUris.withAppendedId(uri, insertedId);
}
/**
* URI
* @param uri URI
* @param selection
* @param selectionArgs selection
* @return
*/
@Override
//删除一个uri操作与上面差不多
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
String id = null;
@ -266,6 +232,7 @@ public class NotesProvider extends ContentProvider {
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
//通知系统相关数据已经发生变化,以便进行相应的更新或处理。
if (count > 0) {
if (deleteData) {
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
@ -275,25 +242,13 @@ public class NotesProvider extends ContentProvider {
return count;
}
/**
* URI
* @param uri URI
* @param values
* @param selection
* @param selectionArgs selection
* @return
*/
@Override
//更新uri
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0;
String id = null;
SQLiteDatabase db = mHelper.getWritableDatabase();
boolean updateData = false;
/**
* URIUniform Resource Identifier
* URI URI
* switch-case URI
*/
switch (mMatcher.match(uri)) {
case URI_NOTE:
increaseNoteVersion(-1, selection, selectionArgs);
@ -328,23 +283,13 @@ public class NotesProvider extends ContentProvider {
return count;
}
/**
* SQLWHERE
* @param selection
* @return
*/
private String parseSelection(String selection) {
return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
}
/**
* 便
* @param id 便ID
* @param selection 便
* @param selectionArgs
*/
//这段代码是一个私有方法,用于增加笔记的版本号。
// 它接受三个参数id笔记的ID、selection查询条件和selectionArgs查询条件的参数
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
StringBuilder sql = new StringBuilder(120);
StringBuilder sql = new StringBuilder(120);//sql对象构建SQL语句
sql.append("UPDATE ");
sql.append(TABLE.NOTE);
sql.append(" SET ");
@ -352,12 +297,14 @@ public class NotesProvider extends ContentProvider {
sql.append("=" + NoteColumns.VERSION + "+1 ");
if (id > 0 || !TextUtils.isEmpty(selection)) {
sql.append(" WHERE ");
sql.append(" WHERE ");//那么在WHERE子句中添加相应的条件
}
if (id > 0) {
sql.append(NoteColumns.ID + "=" + String.valueOf(id));
////将笔记ID等于给定id的条件添加到WHERE子句中
}
if (!TextUtils.isEmpty(selection)) {
//那么将解析后的查询条件添加到WHERE子句中。
String selectString = id > 0 ? parseSelection(selection) : selection;
for (String args : selectionArgs) {
selectString = selectString.replaceFirst("\\?", args);
@ -368,10 +315,6 @@ public class NotesProvider extends ContentProvider {
mHelper.getWritableDatabase().execSQL(sql.toString());
}
/**
*
* @param uri URI
*/
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub

@ -24,33 +24,13 @@ import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: MetaData
* @Description:
* MetaData Task
* GID JSON
* 访使
* @Author: Dong Jiaqi
* @CreateDate: 12/24/2023 9:53 AM
*/
public class MetaData extends Task {
private final static String TAG = MetaData.class.getSimpleName();
private String mRelatedGid = null;
/**
* GID
* @param gid Global Task ID
* @param metaInfo JSONObject
*/
public void setMeta(String gid, JSONObject metaInfo) {
/**
* metaInfo JSONObject GTaskStringUtils.META_HEAD_GTASK_ID gid
* 使 try-catch JSONException
*
* Java JSONObject put JSONException put 使 try-catch
*/
try {
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
} catch (JSONException e) {
@ -60,29 +40,19 @@ public class MetaData extends Task {
setName(GTaskStringUtils.META_NOTE_NAME);
}
//作用是获取任务的相关 GID并返回其字符串形式。
public String getRelatedGid() {
return mRelatedGid;//返回值是一个字符串类型的变量 mRelatedGid表示相关 GIDGlobal Task ID。mRelatedGid 是一个成员变量,它保存了在任务的元数据信息中提取出来的相关 GID。
return mRelatedGid;
}
//作用是判断任务是否值得保存。它通过检查任务的注释信息是否为null来确定任务是否值得保存。
@Override
public boolean isWorthSaving() {
return getNotes() != null;//如果注释信息不为null则返回true表示任务值得保存反之如果注释信息为null则返回false表示任务不值得保存。
return getNotes() != null;
}
/**
* JSON Task
* @param js JSONObject
*/
@Override
public void setContentByRemoteJSON(JSONObject js) {
super.setContentByRemoteJSON(js);
if (getNotes() != null) {
/**
* GID mRelatedGid
* 使try-catch
*/
try {
JSONObject metaInfo = new JSONObject(getNotes().trim());
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
@ -96,7 +66,7 @@ public class MetaData extends Task {
@Override
public void setContentByLocalJSON(JSONObject js) {
// this function should not be called
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");//抛出一个IllegalAccessError异常并且提供异常的详细描述信息
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");
}
@Override

@ -20,33 +20,24 @@ import android.database.Cursor;
import org.json.JSONObject;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: Node
* @Description:
* Node
* *
* @Author: Dong Jiaqi
* @CreateDate: 12/24/2023 10:23 AM
*/
public abstract class Node {
public static final int SYNC_ACTION_NONE = 0;//表示没有同步操作。
public static final int SYNC_ACTION_NONE = 0;
public static final int SYNC_ACTION_ADD_REMOTE = 1;//表示远程添加操作。
public static final int SYNC_ACTION_ADD_REMOTE = 1;
public static final int SYNC_ACTION_ADD_LOCAL = 2;//表示本地添加操作。
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_REMOTE = 3;
public static final int SYNC_ACTION_DEL_LOCAL = 4;//表示本地删除操作。
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_REMOTE = 5;
public static final int SYNC_ACTION_UPDATE_LOCAL = 6;//表示本地更新操作。
public static final int SYNC_ACTION_UPDATE_LOCAL = 6;
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;//表示更新冲突操作。
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;
public static final int SYNC_ACTION_ERROR = 8;//表示同步错误操作。
public static final int SYNC_ACTION_ERROR = 8;
private String mGid;
@ -75,66 +66,34 @@ public abstract class Node {
public abstract int getSyncAction(Cursor c);
/**
* gid
* @param gid
*/
public void setGid(String gid) {
this.mGid = gid;
}
/**
* name mName
* @param name
*/
public void setName(String name) {
this.mName = name;
}
/**
* lastModified mLastModified
* @param lastModified
*/
public void setLastModified(long lastModified) {
this.mLastModified = lastModified;
}
/**
* deleted mDeleted
* @param deleted true false
*/
public void setDeleted(boolean deleted) {
this.mDeleted = deleted;
}
/**
* gid mGid
* @return this.mGid
*/
public String getGid() {
return this.mGid;
}
/**
* mName
* @return this.mName
*/
public String getName() {
return this.mName;
}
/**
* mLastModified
* @return this.mLastModified
*/
public long getLastModified() {
return this.mLastModified;
}
/**
* mDeleted
* @return true false
*/
public boolean getDeleted() {
return this.mDeleted;
}

@ -34,33 +34,26 @@ import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: SqlData
* @Description:
*
* @Author: Dong Jiaqi
* @CreateDate: 12/24/2023 10:58 AM
*/
public class SqlData {
private static final String TAG = SqlData.class.getSimpleName();
private static final int INVALID_ID = -99999;//定义了一个名为 INVALID_ID 的私有静态整型常量,并赋值为 -99999被用来表示无效的 ID 值。
private static final int INVALID_ID = -99999;
public static final String[] PROJECTION_DATA = new String[] {
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3
};//定义了一个名为 PROJECTION_DATA 的字符串数组,其中包含了一组列名
};
public static final int DATA_ID_COLUMN = 0;//表示数据的 ID 在数据列中的索引位置,即第一列。
public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1;//表示数据的 MIME 类型在数据列中的索引位置,即第二列。
public static final int DATA_MIME_TYPE_COLUMN = 1;
public static final int DATA_CONTENT_COLUMN = 2;//表示数据的内容在数据列中的索引位置,即第三列。
public static final int DATA_CONTENT_COLUMN = 2;
public static final int DATA_CONTENT_DATA_1_COLUMN = 3;//表示数据的内容数据1在数据列中的索引位置即第四列。
public static final int DATA_CONTENT_DATA_1_COLUMN = 3;
public static final int DATA_CONTENT_DATA_3_COLUMN = 4;//表示数据的内容数据3在数据列中的索引位置即第五列。
public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
private ContentResolver mContentResolver;
@ -78,54 +71,36 @@ public class SqlData {
private ContentValues mDiffDataValues;
/**
* Context
* @param context 便
*/
public SqlData(Context context) {
mContentResolver = context.getContentResolver();//这是构造方法的定义,表明这是一个公共的构造方法,并且接受一个 Context 类型的参数。
mContentResolver = context.getContentResolver();
mIsCreate = true;
mDataId = INVALID_ID;
mDataMimeType = DataConstants.NOTE;
mDataContent = "";//成员变量初始化
mDataContent = "";
mDataContentData1 = 0;
mDataContentData3 = "";
mDiffDataValues = new ContentValues();//创建新的ContentValues对象
mDiffDataValues = new ContentValues();
}
/**
* ContextCursorCursor
* @param context 便
* @param c Cursor
*/
public SqlData(Context context, Cursor c) {
mContentResolver = context.getContentResolver();
mIsCreate = false;
loadFromCursor(c);//调用 loadFromCursor() 方法,将传入的 Cursor 对象作为参数,以从 Cursor 对象中加载数据库中的数据到 SqlData 对象的成员变量中。
loadFromCursor(c);
mDiffDataValues = new ContentValues();
}
/**
* Cursor SqlData
* @param c Cursor
*/
private void loadFromCursor(Cursor c) {
mDataId = c.getLong(DATA_ID_COLUMN);//从 Cursor 对象中获取指定列索引为 DATA_ID_COLUMN 的长整型数据,并赋值给 mDataId 成员变量。
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);//从 Cursor 对象中获取指定列索引为 DATA_MIME_TYPE_COLUMN 的字符串数据,并赋值给 mDataMimeType 成员变量。
mDataId = c.getLong(DATA_ID_COLUMN);
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
mDataContent = c.getString(DATA_CONTENT_COLUMN);
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
/**
* JSONJSONmDiffDataValues
* @param js JSONObject
* @throws JSONException
*/
public void setContent(JSONObject js) throws JSONException {
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;//检查 JSON 对象 js 中是否包含名为 DataColumns.ID 的字段,如果包含则将其转换为 long 类型并赋给 dataId否则将 INVALID_ID 赋给 dataId。
if (mIsCreate || mDataId != dataId) {//检查是否正在创建新数据mIsCreate 为 true或者已有数据的 dataId 是否与新获取的 dataId 不同。
mDiffDataValues.put(DataColumns.ID, dataId);//如果满足条件,则将 DataColumns.ID 和对应的 dataId 放入 mDiffDataValues 中。
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
if (mIsCreate || mDataId != dataId) {
mDiffDataValues.put(DataColumns.ID, dataId);
}
mDataId = dataId;
@ -155,53 +130,42 @@ public class SqlData {
mDataContentData3 = dataContentData3;
}
/**
* JSON
* @return JSONObject SqlData 使 null
* @throws JSONException
*/
public JSONObject getContent() throws JSONException {
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
JSONObject js = new JSONObject();
js.put(DataColumns.ID, mDataId);//将类的成员变量 mDataId 的值存储到 js 对象中,使用键名 DataColumns.ID。
js.put(DataColumns.MIME_TYPE, mDataMimeType);//将类的成员变量 mDataMimeType 的值存储到 js 对象中,使用键名 DataColumns.MIME_TYPE
js.put(DataColumns.ID, mDataId);
js.put(DataColumns.MIME_TYPE, mDataMimeType);
js.put(DataColumns.CONTENT, mDataContent);
js.put(DataColumns.DATA1, mDataContentData1);
js.put(DataColumns.DATA3, mDataContentData3);
return js;
}
/**
* IDmDiffDataValues
* @param noteId 便ID便ID
* @param validateVersion
* @param version
*/
public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) {//如果数据是新创建的
if (mIsCreate) {
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
mDiffDataValues.remove(DataColumns.ID);
}
mDiffDataValues.put(DataColumns.NOTE_ID, noteId); //设置便签的ID
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);//向数据库中插入数据
mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
try {
mDataId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
} else {//如果不是新创建的数据
} else {
if (mDiffDataValues.size() > 0) {
int result = 0;
if (!validateVersion) {//如果不用验证版本,直接更新数据
if (!validateVersion) {
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else {//如果要验证版本,根据版本号更新数据
} else {
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
" ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
@ -215,14 +179,10 @@ public class SqlData {
}
}
mDiffDataValues.clear();//提交后清空数据
mDiffDataValues.clear();
mIsCreate = false;
}
/**
* mDataId
* @return ID
*/
public long getId() {
return mDataId;
}

@ -37,14 +37,7 @@ import org.json.JSONObject;
import java.util.ArrayList;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: SqlNote
* @Description:
* SqlNote便便
* @Author: Dong Jiaqi
* @CreateDate: 12/24/2023 1718 PM
*/
public class SqlNote {
private static final String TAG = SqlNote.class.getSimpleName();
@ -59,9 +52,9 @@ public class SqlNote {
NoteColumns.VERSION
};
public static final int ID_COLUMN = 0;//便签的ID列的索引为0
public static final int ID_COLUMN = 0;
public static final int ALERTED_DATE_COLUMN = 1;//提醒日期列的索引为1
public static final int ALERTED_DATE_COLUMN = 1;
public static final int BG_COLOR_ID_COLUMN = 2;
@ -127,12 +120,8 @@ public class SqlNote {
private ContentValues mDiffNoteValues;
private ArrayList<SqlData> mDataList;//用Java中的ArrayList类定义了一个SqlData对象 mDataList用于存储从数据库查询中返回的便签数据
private ArrayList<SqlData> mDataList;
/**
* SqlNote SqlNote
* @param context 使
*/
public SqlNote(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
@ -154,50 +143,33 @@ public class SqlNote {
mDataList = new ArrayList<SqlData>();
}
/**
* SqlNote Cursor
* @param context 使
* @param c
*/
public SqlNote(Context context, Cursor c) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = false;
loadFromCursor(c);
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
if (mType == Notes.TYPE_NOTE) {
loadDataContent();
}
mDiffNoteValues = new ContentValues();
}
/**
* SqlNote ID
* @param context 使
* @param id 便ID
*/
public SqlNote(Context context, long id) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = false;
loadFromCursor(id);
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
if (mType == Notes.TYPE_NOTE) {
loadDataContent();
}
mDiffNoteValues = new ContentValues();
}
/**
* ID 便 SqlNote
* @param id 便 ID
*/
private void loadFromCursor(long id) {
Cursor c = null;
/**
* try-finally
*
* finally
*/
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[] {
@ -210,15 +182,12 @@ public class SqlNote {
Log.w(TAG, "loadFromCursor: cursor = null");
}
} finally {
if (c != null)
if (c != null) {
c.close();
}
}
}
/**
* 便 SqlNote
* @param c
*/
private void loadFromCursor(Cursor c) {
mId = c.getLong(ID_COLUMN);
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
@ -234,17 +203,9 @@ public class SqlNote {
mVersion = c.getLong(VERSION_COLUMN);
}
/**
* ID
* 便
*/
private void loadDataContent() {
Cursor c = null;
mDataList.clear();
/**
* ID mDataList
*
*/
try {
c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA,
"(note_id=?)", new String[] {
@ -263,24 +224,13 @@ public class SqlNote {
Log.w(TAG, "loadDataContent: cursor = null");
}
} finally {
if (c != null)
if (c != null) {
c.close();
}
}
}
/**
* JSONObject
* JSONObjectmDiffNoteValues
* @param js JSONObject
* @return truefalse
*/
public boolean setContent(JSONObject js) {
/**
* tryJSONJSONExceptioncatch
* catchfalse
*
*/
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
@ -291,14 +241,14 @@ public class SqlNote {
.getString(NoteColumns.SNIPPET) : "";
if (mIsCreate || !mSnippet.equals(snippet)) {
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
}//判断是否需要更新笔记的摘要snippet。它通过比较当前对象的mSnippet属性和传入的参数snippet如果两者不相等则将新的摘要值存储在mDiffNoteValues中。
}
mSnippet = snippet;
int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE)
: Notes.TYPE_NOTE;
if (mIsCreate || mType != type) {
mDiffNoteValues.put(NoteColumns.TYPE, type);
}//检查是否正在创建新的笔记mIsCreate为true或者当前笔记的类型与传入的类型值不相等mType != type。如果满足其中一个条件就会将新的类型值存储在mDiffNoteValues中。
}
mType = type;
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
@ -413,10 +363,6 @@ public class SqlNote {
return true;
}
/**
* JSON
* @return JSONObject
*/
public JSONObject getContent() {
try {
JSONObject js = new JSONObject();
@ -465,74 +411,39 @@ public class SqlNote {
return null;
}
/**
* IDmDiffNoteValues
* @param id longID
*/
public void setParentId(long id) {
mParentId = id;
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
}
/**
* Google TasksIDgidmDiffNoteValues便
* @param gid Google TasksID
*/
public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
}
/**
* IDsyncIdmDiffNoteValues便
* @param syncId longID
*/
public void setSyncId(long syncId) {
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
}
/**
*
*/
public void resetLocalModified() {
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
}
/**
* ID
* @return ID
*/
public long getId() {
return mId;
}
/**
* ID
* @return ID
*/
public long getParentId() {
return mParentId;
}
/**
*
* @return
*/
public String getSnippet() {
return mSnippet;
}
/**
* 便
* @return 便便truefalse
*/
public boolean isNoteType() {
return mType == Notes.TYPE_NOTE;
}
/**
*
* @param validateVersion true
*/
public void commit(boolean validateVersion) {
if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
@ -589,8 +500,9 @@ public class SqlNote {
// refresh local info
loadFromCursor(mId);
if (mType == Notes.TYPE_NOTE)
if (mType == Notes.TYPE_NOTE) {
loadDataContent();
}
mDiffNoteValues.clear();
mIsCreate = false;

@ -31,16 +31,7 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: Task
* @Description:
* TaskNodeGoogle使
*
* JSON便Google
* @Author: Dong Jiaqi
* @CreateDate: 12/24/2023 1948 PM
*/
public class Task extends Node {
private static final String TAG = Task.class.getSimpleName();
@ -54,27 +45,17 @@ public class Task extends Node {
private TaskList mParent;
/**
*
* null
*/
public Task() {
super();//调用父类Node的构造方法确保父类的属性得到正确初始化
mCompleted = false;//任务完成状态设置为未完成
mNotes = null;//暂时没有便签笔记
mPriorSibling = null;//当前任务没有前节点
mParent = null;//当前任务没有父节点
mMetaInfo = null;//当前任务没有元数据信息
super();
mCompleted = false;
mNotes = null;
mPriorSibling = null;
mParent = null;
mMetaInfo = null;
}
/**
* JSON
* JSONActionFailureException
* @param actionId
* @return JSONObject
*/
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();//创建一个空的JSONObject对象。
JSONObject js = new JSONObject();
try {
// action_type
@ -116,17 +97,12 @@ public class Task extends Node {
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("fail to generate task-create jsonobject");//抛出异常
throw new ActionFailureException("fail to generate task-create jsonobject");
}
return js;
}
/**
* JSON
* @param actionId
* @return JSONObject
*/
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
@ -159,11 +135,6 @@ public class Task extends Node {
return js;
}
/**
* JSONObject
* JSON
* @param js JSONObject
*/
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
@ -204,25 +175,17 @@ public class Task extends Node {
}
}
/**
* JSONObject
* @param js
*/
public void setContentByLocalJSON(JSONObject js) {
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)
|| !js.has(GTaskStringUtils.META_HEAD_DATA)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
}
/**
* JSONObject
* 便便
*/
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {//检查便签类型是不是普通便签
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {
Log.e(TAG, "invalid type");
return;
}
@ -241,11 +204,6 @@ public class Task extends Node {
}
}
/**
* JSONObject
* @return JSONObjectjs
* mMetaInfo
*/
public JSONObject getLocalJSONFromContent() {
String name = getName();
try {
@ -289,10 +247,6 @@ public class Task extends Node {
}
}
/**
*
* @param metaData MetaData
*/
public void setMetaInfo(MetaData metaData) {
if (metaData != null && metaData.getNotes() != null) {
try {
@ -304,16 +258,6 @@ public class Task extends Node {
}
}
/**
* Cursor
* @param c Cursorc
* @return
* SYNC_ACTION_NONE
* SYNC_ACTION_UPDATE_LOCAL
* SYNC_ACTION_UPDATE_REMOTE
* SYNC_ACTION_UPDATE_CONFLICT
* SYNC_ACTION_ERROR
*/
public int getSyncAction(Cursor c) {
try {
JSONObject noteInfo = null;
@ -367,80 +311,39 @@ public class Task extends Node {
return SYNC_ACTION_ERROR;
}
/**
*
* @return booleantruefalse
*/
public boolean isWorthSaving() {
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)
|| (getNotes() != null && getNotes().trim().length() > 0);
}
/**
*
* 便
* @param completed boolean
*/
public void setCompleted(boolean completed) {
this.mCompleted = completed;
}
/**
*
* 便
* @param notes String
*/
public void setNotes(String notes) {
this.mNotes = notes;
}
/**
*
*
* @param priorSibling Task
*/
public void setPriorSibling(Task priorSibling) {
this.mPriorSibling = priorSibling;
}
/**
*
*
* @param parent TaskList
*/
public void setParent(TaskList parent) {
this.mParent = parent;
}
/**
*
* 便
* @return booleantruefalse
*/
public boolean getCompleted() {
return this.mCompleted;
}
/**
*
* @return String
*/
public String getNotes() {
return this.mNotes;
}
/**
*
* @return Tasknull
*/
public Task getPriorSibling() {
return this.mPriorSibling;
}
/**
*
* @return TaskListnull
*/
public TaskList getParent() {
return this.mParent;
}

@ -30,36 +30,19 @@ import org.json.JSONObject;
import java.util.ArrayList;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: TaskList
* @Description:
* TaskListNode
* JSON
* @Author: Dong Jiaqi
* @CreateDate: 12/24/2023 2048 PM
*/
public class TaskList extends Node {
private static final String TAG = TaskList.class.getSimpleName();//私有静态常量,用于在日志和调试中标识类名。
private static final String TAG = TaskList.class.getSimpleName();
private int mIndex;//私有整型变量,表示任务列表的索引。
private int mIndex;
private ArrayList<Task> mChildren;//私有ArrayList存储Task对象表示该任务列表下的子任务列表。
private ArrayList<Task> mChildren;
/**
* mChildrenTaskmIndex1
*/
public TaskList() {
super();
mChildren = new ArrayList<Task>();
mIndex = 1;
}
/**
* actionIdJSONObject
* @param actionId ID
* @return JSONObject
*/
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
@ -91,11 +74,6 @@ public class TaskList extends Node {
return js;
}
/**
* actionIdJSONObject
* @param actionId ID
* @return JSONObject
*/
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
@ -125,10 +103,6 @@ public class TaskList extends Node {
return js;
}
/**
* JSON
* @param js JSONObject
*/
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
@ -155,10 +129,6 @@ public class TaskList extends Node {
}
}
/**
* JSON
* @param js JSONObject
*/
public void setContentByLocalJSON(JSONObject js) {
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
@ -171,13 +141,14 @@ public class TaskList extends Node {
String name = folder.getString(NoteColumns.SNIPPET);
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name);
} else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER)
if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) {
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT);
else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER)
} else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) {
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX
+ GTaskStringUtils.FOLDER_CALL_NOTE);
else
} else {
Log.e(TAG, "invalid system folder");
}
} else {
Log.e(TAG, "error type");
}
@ -187,10 +158,6 @@ public class TaskList extends Node {
}
}
/**
* JSON
* @return JSONObject
*/
public JSONObject getLocalJSONFromContent() {
try {
JSONObject js = new JSONObject();
@ -217,17 +184,6 @@ public class TaskList extends Node {
}
}
/**
*
* @param c Cursor
* @return
* SYNC_ACTION_NONE
* SYNC_ACTION_UPDATE_LOCAL
* SYNC_ACTION_ERROR
* SYNC_ACTION_UPDATE_REMOTEID,
* SYNC_ACTION_UPDATE_REMOTEID,
* SYNC_ACTION_ERROR
*/
public int getSyncAction(Cursor c) {
try {
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
@ -261,19 +217,10 @@ public class TaskList extends Node {
return SYNC_ACTION_ERROR;
}
/**
*
* @return
*/
public int getChildTaskCount() {
return mChildren.size();
}
/**
*
* @param task
* @return boolean:truefalse
*/
public boolean addChildTask(Task task) {
boolean ret = false;
if (task != null && !mChildren.contains(task)) {
@ -288,12 +235,6 @@ public class TaskList extends Node {
return ret;
}
/**
*
* @param task
* @param index 0
* @return boolean:truefalse
*/
public boolean addChildTask(Task task, int index) {
if (index < 0 || index > mChildren.size()) {
Log.e(TAG, "add child task: invalid index");
@ -320,11 +261,6 @@ public class TaskList extends Node {
return true;
}
/**
*
* @param task
* @return boolean:truefalse
*/
public boolean removeChildTask(Task task) {
boolean ret = false;
int index = mChildren.indexOf(task);
@ -346,12 +282,6 @@ public class TaskList extends Node {
return ret;
}
/**
*
* @param task
* @param index 0
* @return boolean:truefalse
*/
public boolean moveChildTask(Task task, int index) {
if (index < 0 || index >= mChildren.size()) {
@ -370,11 +300,6 @@ public class TaskList extends Node {
return (removeChildTask(task) && addChildTask(task, index));
}
/**
*
* @param gid gid()
* @return Taskgidnull
*/
public Task findChildTaskByGid(String gid) {
for (int i = 0; i < mChildren.size(); i++) {
Task t = mChildren.get(i);
@ -385,20 +310,10 @@ public class TaskList extends Node {
return null;
}
/**
*
* @param task
* @return int:0-1
*/
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task);
}
/**
*
* @param index 0
* @return Tasknull
*/
public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index");
@ -407,11 +322,6 @@ public class TaskList extends Node {
return mChildren.get(index);
}
/**
*
* @param gid gid
* @return Taskgidnull
*/
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))
@ -420,26 +330,14 @@ public class TaskList extends Node {
return null;
}
/**
*
* @return ArrayList<Task>ArrayList
*/
public ArrayList<Task> getChildTaskList() {
return this.mChildren;
}
/**
*
* @param index
*/
public void setIndex(int index) {
this.mIndex = index;
}
/**
*
* @return
*/
public int getIndex() {
return this.mIndex;
}

@ -352,9 +352,9 @@ public class GTaskClient {
}
InputStream input = entity.getContent();
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {
if (contentEncoding != null && "gzip".equalsIgnoreCase(contentEncoding)) {
input = new GZIPInputStream(entity.getContent());
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {
} else if (contentEncoding != null && "deflate".equalsIgnoreCase(contentEncoding)) {
Inflater inflater = new Inflater(true);
input = new InflaterInputStream(entity.getContent(), inflater);
}
@ -520,8 +520,9 @@ public class GTaskClient {
commitUpdate();
}
if (mUpdateArray == null)
if (mUpdateArray == null) {
mUpdateArray = new JSONArray();
}
mUpdateArray.put(node.getUpdateAction(getActionId()));
}
}

@ -206,8 +206,9 @@ public class GTaskManager {
*@return void
*/
private void initGTaskList() throws NetworkFailureException {
if (mCancelled)
if (mCancelled) {
return;
}
//getInstance即为创建一个实例client应指远端客户机用于与远程服务器进行通信
GTaskClient client = GTaskClient.getInstance();
try {
@ -461,8 +462,9 @@ public class GTaskManager {
mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid);
// for system folder, only update remote name if necessary
if (!node.getName().equals(
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT))
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) {
doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);
}
} else {
doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);
}
@ -494,8 +496,9 @@ public class GTaskManager {
// necessary
if (!node.getName().equals(
GTaskStringUtils.MIUI_FOLDER_PREFFIX
+ GTaskStringUtils.FOLDER_CALL_NOTE))
+ GTaskStringUtils.FOLDER_CALL_NOTE)) {
doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);
}
} else {
doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);
}
@ -558,8 +561,9 @@ public class GTaskManager {
}
}
if (!mCancelled)
if (!mCancelled) {
GTaskClient.getInstance().commitUpdate();
}
}
/**
@ -769,12 +773,13 @@ public class GTaskManager {
// we need to skip folder if it has already existed
String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX;
if (sqlNote.getId() == Notes.ID_ROOT_FOLDER)
if (sqlNote.getId() == Notes.ID_ROOT_FOLDER) {
folderName += GTaskStringUtils.FOLDER_DEFAULT;
else if (sqlNote.getId() == Notes.ID_CALL_RECORD_FOLDER)
} else if (sqlNote.getId() == Notes.ID_CALL_RECORD_FOLDER) {
folderName += GTaskStringUtils.FOLDER_CALL_NOTE;
else
} else {
folderName += sqlNote.getSnippet();
}
//iterator迭代器通过统一的接口迭代所有的map元素
Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();

@ -280,7 +280,9 @@ public class WorkingNote {
mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId));
}
}
public void setmContent(String text){
mContent = text;
}
public void setWorkingText(String text) {
if (!TextUtils.equals(mContent, text)) {
mContent = text;

@ -0,0 +1,24 @@
package net.micode.notes.translate;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
//源URL https://fanyi-api.baidu.com/api/trans/vip/translate
//参数如下
// String q 英文单词/中文
// String from 原始语种 zh中文/eh英文
// String to 目标语种 zh中文/eh英文
// String from zh中文/eh英文
// String appid 你的appid
// String salt 随机数(整形转字符串)
// String sign 签名 32位字母小写MD5编码的 appid+q+salt+密钥
public interface BaiduTranslateService {
//翻译接口
//表示提交表单数据,@Field注解键名
//适用于数据量少的情况
@POST("translate")
@FormUrlEncoded
Call<RespondBean> translate(@Field("q") String q, @Field("from") String from, @Field("to") String to, @Field("appid") String appid, @Field("salt") String salt,
@Field("sign") String sign);
}

@ -0,0 +1,35 @@
package net.micode.notes.translate;
import java.security.MessageDigest;
/**
* () MD5
*/
public class MD5Utils {
/**
* MD5使
*
* @param info String
* @return String
*/
public static String getMD5Code(String info) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(info.getBytes("utf-8"));//设置编码格式
byte[] encryption = md5.digest();
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < encryption.length; i++) {
if (Integer.toHexString(0xff & encryption[i]).length() == 1) {
stringBuffer.append("0").append(Integer.toHexString(0xff & encryption[i]));
} else {
stringBuffer.append(Integer.toHexString(0xff & encryption[i]));
}
}
return stringBuffer.toString();
} catch (Exception e) {
return "MD5加密异常";
}
}
}

@ -0,0 +1,65 @@
package net.micode.notes.translate;
import java.util.List;
public class RespondBean {
/**
* from : zh
* to : en
* trans_result : [{"src":"你好","dst":"Hello"}]
*/
private String from;
private String to;
private List<TransResultBean> trans_result;
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public List<TransResultBean> getTrans_result() {
return trans_result;
}
public void setTrans_result(List<TransResultBean> trans_result) {
this.trans_result = trans_result;
}
public static class TransResultBean {
/**
* src :
* dst : Hello
*/
private String src;
private String dst;
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
public String getDst() {
return dst;
}
public void setDst(String dst) {
this.dst = dst;
}
}
}

@ -39,77 +39,36 @@ import net.micode.notes.tool.DataUtils;
import java.io.IOException;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: AlarmAlertActivity
* @Description: AlarmAlertActivity
* 便AlarmAlertActivity
*
*
* @Author: xumingyang
* @CreateDate: 2023-12-24 10:33
* @UpdateUser:
* @UpdateDate: 2023-12-24 10:33
* @UpdateRemark:
* @Version: 1.0
*/
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
private long mNoteId; //文本在数据库存储中的ID号
private String mSnippet; //闹钟提示时出现的文本片段
private long mNoteId;
private String mSnippet;
private static final int SNIPPET_PREW_MAX_LEN = 60;
MediaPlayer mPlayer;
/**
* @method onCreate
* @description :
*
*
* Intent便ID
* 使便ID便
* MediaPlayer
* 便便
* 便
* 便
* @date: 2023-12-24 10:41
* @author: xumingyang
* @param
* @return
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Bundle类型的数据与Map类型的数据相似都是以key-value的形式存储数据的
//onsaveInstanceState方法是用来保存Activity的状态的
//能从onCreate的参数savedInsanceState中获得状态数
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();
try {
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);
//根据ID从数据库中获取标签的内容
//getContentResolver是实现数据共享实例存储。
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;
@ -118,41 +77,20 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
mPlayer = new MediaPlayer();
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
showActionDialog();
//弹出对话框
playAlarmSound();
//闹钟提示音激发
} else {
finish();
//完成闹钟动作
}
}
/**
* @method isScreenOn
* @description
* @date: 2023-12-24 10:45
* @author: xumingyang
* @param
* @return bool
*/
private boolean isScreenOn() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
return pm.isScreenOn();
}
/**
* @method playAlarmSound
* @description:
*
*
* @date: 2023-12-24 10:47
* @author: xumingyang
* @param
* @return
*/
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);
@ -163,19 +101,12 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
}
try {
mPlayer.setDataSource(this, url);
//方法setDataSource(Context context, Uri uri)
//解释:无返回值,设置多媒体数据来源【根据 Uri】
mPlayer.prepare();
//准备同步
mPlayer.setLooping(true);
//设置是否循环播放
mPlayer.start();
//开始播放
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//e.printStackTrace()函数功能是抛出异常, 还将显示出更深的调用信息
//System.out.println(e),这个方法打印出异常,并且输出在哪里出现的异常
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@ -188,99 +119,39 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
}
}
/**
* @method showActionDialog
* @description
* AlertDialog.BuilderR.string.app_name
* mSnippet
* Positive ButtonR.string.notealert_ok
* isScreenOn()Negative ButtonR.string.notealert_enter
* dialog.show().setOnDismissListener(this)
* @date: 2023-12-24 10:51
* @author: xumingyang
* @param
* @return
*/
private void showActionDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
/*
* AlertDialogProtected
* newAlertDialogAlertDialog
* AlertDialogAlertDialog.Buildercreate()
* dialogAlertDialog
*/
dialog.setTitle(R.string.app_name);
//为对话框设置标题
dialog.setMessage(mSnippet);
//为对话框设置内容
dialog.setPositiveButton(R.string.notealert_ok, this);
//给对话框添加"Yes"按钮
if (isScreenOn()) {
dialog.setNegativeButton(R.string.notealert_enter, this);
}//对话框添加"No"按钮
}
dialog.show().setOnDismissListener(this);
}
/**
* @method onClick
* @description :
*
* 便idActivity
* @date: 2023-12-24 10:55
* @author: xumingyang
* @param
* @return
*/
public void onClick(DialogInterface dialog, int which) {
switch (which) {
//用which来选择click后下一步的操作
case DialogInterface.BUTTON_NEGATIVE:
//这是取消操作
Intent intent = new Intent(this, NoteEditActivity.class);
//实现两个类间的数据传输
intent.setAction(Intent.ACTION_VIEW);
//设置动作属性
intent.putExtra(Intent.EXTRA_UID, mNoteId);
//实现key-value对
//EXTRA_UID为keymNoteId为键
startActivity(intent);
//开始动作
break;
default:
//这是确定操作'
break;
}
}
/**
* @method onDismiss
* @description Activity
* @date: 2023-12-24 10:57
* @author: xumingyang
* @param
* @return
*/
public void onDismiss(DialogInterface dialog) {
stopAlarmSound();
//停止闹钟声音
finish();
//完成该动作
}
/**
* @method stopAlarmSound
* @description
* @date: 2023-12-24 10:58
* @author: xumingyang
* @param
* @return
*/
private void stopAlarmSound() {
if (mPlayer != null) {
mPlayer.stop();
//停止播放
mPlayer.release();
//释放MediaPlayer对象
mPlayer = null;
}
}

@ -27,21 +27,6 @@ import android.database.Cursor;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: AlarmInitReceiver
* @Description: AlarmInitReceiver便广BroadcastReceiver
* 广
* @Author: xumingyang
* @CreateDate: 2023-12-24 11:11
* @UpdateUser:
* @UpdateDate: 2023-12-24 11:11
* @UpdateRemark:
* @Version: 1.0
*/
public class AlarmInitReceiver extends BroadcastReceiver {
@ -49,35 +34,19 @@ public class AlarmInitReceiver extends BroadcastReceiver {
NoteColumns.ID,
NoteColumns.ALERTED_DATE
};
//对数据库的操作调用标签ID和闹钟时间
private static final int COLUMN_ID = 0;
private static final int COLUMN_ALERTED_DATE = 1;
/**
* @method onReceive
* @description
* 便
* @date: 2023-12-24 11:26
* @author: xumingyang
* @param *Cursor
* alertDate
* Intentsender广AlarmReceiver
* PendingIntent使getBroadcast()广PendingIntentpendingIntent
* @return Cursorc
*/
@Override
public void onReceive(Context context, Intent intent) {
long currentDate = System.currentTimeMillis();
//System.currentTimeMillis()产生一个当前的毫秒
//这个毫秒其实就是自1970年1月1日0时起的毫秒数
Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE,
new String[] { String.valueOf(currentDate) },
//将long变量currentDate转化为字符串
null);
//Cursor在这里的作用是通过查找数据库中的标签内容找到和当前系统时间相等的标签
if (c != null) {
if (c.moveToFirst()) {
do {
@ -93,9 +62,4 @@ public class AlarmInitReceiver extends BroadcastReceiver {
c.close();
}
}
/*
*
* IntentPendingIntentAlarmManager
*
*/
}

@ -20,37 +20,11 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: AlarmReceiver
* @Description: AlarmReceiver便
*
* @Author: xumingyang
* @CreateDate: 2023-12-24 12:46
* @UpdateUser:
* @UpdateDate: 2023-12-24 12:46
* @UpdateRemark:
* @Version: 1.0
*/
/**
* @method
* @description 广AlarmAlertActivity
* @param *Context contextIntent intentcontextintent广
* @return
*/
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//重写了onReceive()方法,该方法在接收到广播时会被调用
intent.setClass(context, AlarmAlertActivity.class);
////启动AlarmAlertActivity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
////activity要存在于activity的栈中而非activity的途径启动activity时必然不存在一个activity的栈
//所以要新起一个栈装入启动的activity
context.startActivity(intent);
}
}

@ -0,0 +1,81 @@
package net.micode.notes.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import net.micode.notes.R;
public class ChangePassword extends Activity{
EditText OldPassword;//声明了旧密码的文本编辑框
EditText NewPassword;
EditText AckPassword;//确认密码
Button Acknowledged;//声明了一个确认按钮
@SuppressLint("MissingInflatedId")//使用注解忽略缺少的布局资源ID的警告。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);//调用父类的onCreate方法
setContentView(R.layout.activity_change_loginpassword);//按照所给的布局文件进行当前页面布局
//设置软键盘的显示模式通过findViewById方法来获取布局文件中各种文本编辑框和按钮
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
OldPassword=(EditText) findViewById(R.id.old_password);
NewPassword=(EditText) findViewById(R.id.new_password);
AckPassword=(EditText) findViewById(R.id.ack_password);
Acknowledged=(Button)findViewById(R.id.Bt_Acknowledged);
//给确认按钮设置了点击监听
Acknowledged.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String old_password = OldPassword.getText().toString();//获取文本框中输入内容
String new_password = NewPassword.getText().toString();
String ack_password = AckPassword.getText().toString();
//用getSharedPreferences方法来获取名为“user management”的对象用来存储数据
//从SharedPreferences中来获取密码值作为登录密码
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
String login_password=pref.getString("password","");
if(old_password.equals("")==true || new_password.equals("")==true || ack_password.equals("")==true) {
Toast.makeText(ChangePassword.this, "密码不能为空", Toast.LENGTH_SHORT).show();//进行一个消息提示
}
else if (new_password.equals(ack_password) == false) {
Toast.makeText(ChangePassword.this, "新建密码与重复密码不匹配,请重新输入密码", Toast.LENGTH_SHORT).show();
AckPassword.setText("");//清空文本框
}
else if(old_password.equals(login_password) == false){
Toast.makeText(ChangePassword.this, "原有密码错误,请重新输入密码", Toast.LENGTH_SHORT).show();
OldPassword.setText("");
}
else if (new_password.equals(ack_password) == true && old_password.equals(login_password) == true){
SharedPreferences.Editor editor=getSharedPreferences("user management", MODE_PRIVATE).edit();
editor.putString("password",new_password);//把新的密码保存起来
editor.apply();//提交修改
Toast.makeText(ChangePassword.this, "修改密码成功", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(ChangePassword.this,NotesListActivity.class);//创建一个意图对象
startActivity(intent);//用该意图对象来启动NotesListActivity类
finish();//结束当前的活动
}
}
});
}
/*
@Override
public void onBackPressed() {
Intent intent=new Intent(ChangePassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
*/
}

@ -0,0 +1,71 @@
package net.micode.notes.ui;
import android.annotation.SuppressLint;
import android.view.View;//可视化界面
import android.app.Activity;//完成函数周期
import android.view.WindowManager;
import android.widget.Button;//实现按钮
import android.widget.EditText;//输入显示
import android.widget.Toast;//设计让登录界面无法被跳过
import android.os.Bundle;//获取输入密码
import android.content.SharedPreferences;
import android.content.Intent;//数据交互
import android.util.Log;
import net.micode.notes.R;
public class CreatePassword extends Activity {
EditText password01;
EditText password02;
Button registered;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_set_loginpassword);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
password01=(EditText) findViewById(R.id.rg_password01);
password02=(EditText) findViewById(R.id.rg_password02);
registered=(Button)findViewById(R.id.rg_registered);
registered.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String text02 = password01.getText().toString();
String text03 = password02.getText().toString();
if(text02.equals("")==true) {
Toast.makeText(CreatePassword.this, "密码不能为空", Toast.LENGTH_SHORT).show();
}
else if (text02.equals(text03) == false) {
Toast.makeText(CreatePassword.this, "密码不匹配,请重新输入密码", Toast.LENGTH_SHORT).show();
password02.setText("");
}
else if (text02.equals(text03) == true){
SharedPreferences.Editor editor=getSharedPreferences("user management",
MODE_PRIVATE).edit();
editor.putBoolean("user",true);//true表示已经设置登录密码
editor.putString("password",text02);
editor.apply();
Log.d("RegisterLoginPassword","password is "+text02);
Toast.makeText(CreatePassword.this, "设置密码成功", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(CreatePassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
}
});
}
/*
@Override
public void onBackPressed() {
Intent intent=new Intent(CreatePassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
*/
}

@ -28,23 +28,8 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.NumberPicker;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: DateTimePicker
* @Description:
* 使NumberPicker便
* @Author: xumingyang
* @CreateDate: 2023-12-24 12:58
* @UpdateUser:
* @UpdateDate: 2023-12-24 12:58
* @UpdateRemark:
* @Version: 1.0
*/
public class DateTimePicker extends FrameLayout {
//FrameLayout是布局模板之一
//所有的子元素全部在屏幕的右上方
private static final boolean DEFAULT_ENABLE_STATE = true;
private static final int HOURS_IN_HALF_DAY = 12;
@ -60,15 +45,13 @@ public class DateTimePicker extends FrameLayout {
private static final int MINUT_SPINNER_MAX_VAL = 59;
private static final int AMPM_SPINNER_MIN_VAL = 0;
private static final int AMPM_SPINNER_MAX_VAL = 1;
//初始化控件
private final NumberPicker mDateSpinner;
private final NumberPicker mHourSpinner;
private final NumberPicker mMinuteSpinner;
private final NumberPicker mAmPmSpinner;
//NumberPicker是数字选择器
//这里定义的四个变量全部是在设置闹钟时需要选择的变量(如日期、时、分、上午或者下午)
private Calendar mDate;
//定义了Calendar类型的变量mDate用于操作时间
private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK];
private boolean mIsAm;
@ -89,22 +72,8 @@ public class DateTimePicker extends FrameLayout {
onDateTimeChanged();
}
};
//OnValueChangeListener这是时间改变监听器这里主要是对日期的监听
//将现在日期的值传递给mDateupdateDateControl是同步操作
private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() {
//这里是对 小时Hour 的监听
/**
* @method onValueChange
* @description NumberPicker
*
* 24
* @date: 2023-12-24 13:03
* @author: xumingyang
* @param *Calendarcal便
* @return isdateChanged bool
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
boolean isDateChanged = false;
@ -114,33 +83,29 @@ public class DateTimePicker extends FrameLayout {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, 1);
isDateChanged = true;
//这里是对于12小时制时晚上11点和12点交替时对日期的更改
} else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, -1);
isDateChanged = true;
}//这里是对于12小时制时晚上11点和12点交替时对日期的更改
}
if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY ||
oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {
mIsAm = !mIsAm;
updateAmPmControl();
}//这里是对于12小时制时中午11点和12点交替时对AM和PM的更改
}
} else {
if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, 1);
isDateChanged = true;
//这里是对于24小时制时晚上11点和12点交替时对日期的更改
} else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, -1);
isDateChanged = true;
}
}//这里是对于12小时制时凌晨11点和12点交替时对日期的更改
}
int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY);
//通过数字选择器对newHour的赋值
mDate.set(Calendar.HOUR_OF_DAY, newHour);
//通过set函数将新的Hour值传给mDate
onDateTimeChanged();
if (isDateChanged) {
setCurrentYear(cal.get(Calendar.YEAR));
@ -151,25 +116,16 @@ public class DateTimePicker extends FrameLayout {
};
private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() {
/**
* @method onValueChange
* @description NumberPicker
*
* @param *picker NumberPicker oldVal newVal
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
int minValue = mMinuteSpinner.getMinValue();
int maxValue = mMinuteSpinner.getMaxValue();
int offset = 0;
//设置offset作为小时改变的一个记录数据
if (oldVal == maxValue && newVal == minValue) {
offset += 1;
} else if (oldVal == minValue && newVal == maxValue) {
offset -= 1;
}
//如果原值为59新值为0则offset加1
//如果原值为0新值为59则offset减1
if (offset != 0) {
mDate.add(Calendar.HOUR_OF_DAY, offset);
mHourSpinner.setValue(getCurrentHour());
@ -189,15 +145,9 @@ public class DateTimePicker extends FrameLayout {
};
private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() {
/**
* @method onValueChange
* @description NumberPicker
* /
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
mIsAm = !mIsAm;
//对AM和PM的监听
if (mIsAm) {
mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY);
} else {
@ -216,25 +166,18 @@ public class DateTimePicker extends FrameLayout {
public DateTimePicker(Context context) {
this(context, System.currentTimeMillis());
}
//通过对数据库的访问,获取当前的系统时间
public DateTimePicker(Context context, long date) {
this(context, date, DateFormat.is24HourFormat(context));
}
//上面函数的得到的是一个天文数字1970至今的秒数需要DateFormat将其变得有意义
public DateTimePicker(Context context, long date, boolean is24HourView) {
super(context);
//获取系统时间
mDate = Calendar.getInstance();
mInitialising = true;
mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY;
inflate(context, R.layout.datetime_picker, this);
/*
* Activitylayoutlayout
* layoutinflate()layout
* findViewById()
*/
mDateSpinner = (NumberPicker) findViewById(R.id.date);
mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL);
mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL);
@ -271,28 +214,17 @@ public class DateTimePicker extends FrameLayout {
mInitialising = false;
}
/**
* @method setEnabled
* @description
* @param * enabled
* @return mIsEnabled enabled
*/
@Override
public void setEnabled(boolean enabled) {
if (mIsEnabled == enabled) {
return;
}
/*
* enabled mIsEnabled
*
*/
super.setEnabled(enabled);
mDateSpinner.setEnabled(enabled);
mMinuteSpinner.setEnabled(enabled);
mHourSpinner.setEnabled(enabled);
mAmPmSpinner.setEnabled(enabled);
mIsEnabled = enabled;
//将 mIsEnabled 的值更新为传入的 enabled以保持状态同步
}
@Override
@ -307,7 +239,7 @@ public class DateTimePicker extends FrameLayout {
*/
public long getCurrentDateInTimeMillis() {
return mDate.getTimeInMillis();
}//实现函数——得到当前的秒数
}
/**
* Set the current date
@ -319,7 +251,7 @@ public class DateTimePicker extends FrameLayout {
cal.setTimeInMillis(date);
setCurrentDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH),
cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE));
}//实现函数功能——设置当前的时间参数是date
}
/**
* Set the current date
@ -337,14 +269,13 @@ public class DateTimePicker extends FrameLayout {
setCurrentDay(dayOfMonth);
setCurrentHour(hourOfDay);
setCurrentMinute(minute);
}//实现函数功能——设置当前的时间,参数是各详细的变量
}
/**
* Get current year
*
* @return The current year
*/
//下面是得到year、month、day等值
public int getCurrentYear() {
return mDate.get(Calendar.YEAR);
}
@ -515,7 +446,7 @@ public class DateTimePicker extends FrameLayout {
mDateSpinner.setDisplayedValues(mDateDisplayValues);
mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2);
mDateSpinner.invalidate();
}// 对于星期几的算法
}
private void updateAmPmControl() {
if (mIs24HourView) {
@ -525,7 +456,7 @@ public class DateTimePicker extends FrameLayout {
mAmPmSpinner.setValue(index);
mAmPmSpinner.setVisibility(View.VISIBLE);
}
}// 对于上下午操作的算法
}
private void updateHourControl() {
if (mIs24HourView) {
@ -535,7 +466,7 @@ public class DateTimePicker extends FrameLayout {
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW);
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW);
}
}// 对与小时的算法
}
/**
* Set the callback that indicates the 'Set' button has been pressed.

@ -29,43 +29,21 @@ import android.content.DialogInterface.OnClickListener;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
/**
*
* @ProjectName: DateTimePickerDialog
* @Package: net.micode.notes.ui
* @ClassName: DateTimePickerDialog
* @Description: DateTimePickerDialog
* 便
* DateTimePickerDialog 便使便
* @Author: xumingyang
* @CreateDate: 2023-12-24 13:52
* @UpdateUser:
* @UpdateDate: 2023-12-24 13:52
* @UpdateRemark:
* @Version: 1.0
*/
public class DateTimePickerDialog extends AlertDialog implements OnClickListener {
private Calendar mDate = Calendar.getInstance();
//创建一个Calendar类型的变量 mDate方便时间的操作
private boolean mIs24HourView;
private OnDateTimeSetListener mOnDateTimeSetListener;
//声明一个时间日期滚动选择控件 mOnDateTimeSetListener
private DateTimePicker mDateTimePicker;
//DateTimePicker控件控件一般用于让用户可以从日期列表中选择单个值。
//运行时,单击控件边上的下拉箭头,会显示为两个部分:一个下拉列表,一个用于选择日期的
public interface OnDateTimeSetListener {
void OnDateTimeSet(AlertDialog dialog, long date);
}
public DateTimePickerDialog(Context context, long date) {
//对该界面对话框的实例化
super(context);
//对数据库的操作
mDateTimePicker = new DateTimePicker(context);
setView(mDateTimePicker);
//添加一个子视图
mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() {
public void onDateTimeChanged(DateTimePicker view, int year, int month,
int dayOfMonth, int hourOfDay, int minute) {
@ -74,21 +52,15 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
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);
//得到系统时间
mDate.set(Calendar.SECOND, 0);
//将秒数设置为0 对日期时间进行标准化处理
mDateTimePicker.setCurrentDate(mDate.getTimeInMillis());
//将日期时间选择器设置为当前设置的日期时间。
setButton(context.getString(R.string.datetime_dialog_ok), this);
setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener)null);
//设置按钮
set24HourView(DateFormat.is24HourFormat(this.getContext()));
//时间标准化打印
updateTitle(mDate.getTimeInMillis());
}
@ -98,7 +70,7 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
mOnDateTimeSetListener = callBack;
}//将时间日期滚动选择控件实例化
}
private void updateTitle(long date) {
int flag =
@ -107,13 +79,12 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
DateUtils.FORMAT_SHOW_TIME;
flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR;
setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));
}//android开发中常见日期管理工具类API——DateUtils按照上下午显示时间
}
public void onClick(DialogInterface arg0, int arg1) {
if (mOnDateTimeSetListener != null) {
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
}
}//第一个参数arg0是接收到点击事件的对话框
//第二个参数arg1是该对话框上的按钮
}
}

@ -0,0 +1,65 @@
package net.micode.notes.ui;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import net.micode.notes.R;
public class DeletePassword extends Activity{
EditText password01;
Button Acknowledged;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_delete_loginpassword);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
password01=(EditText) findViewById(R.id.old_password);
Acknowledged=(Button)findViewById(R.id.Bt_Acknowledged);
Acknowledged.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String text02 = password01.getText().toString();
if(text02.equals("")==true) {
Toast.makeText(DeletePassword.this, "密码不能为空", Toast.LENGTH_SHORT).show();
}
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
String password = pref.getString("password","");
if(password.equals("")==false&&password.equals(text02)==true){
SharedPreferences.Editor editor=getSharedPreferences("user management",
MODE_PRIVATE).edit();
editor.putBoolean("user",false);//false表示已经设置登录密码
editor.putString("password","");
editor.apply();
Toast.makeText(DeletePassword.this, "已经删除登录密码", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(DeletePassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
else{
Toast.makeText(DeletePassword.this, "密码错误", Toast.LENGTH_SHORT).show();
password01.setText("");//把密码框内输入过的错误密码清空
}
}
});
}
/*
@Override
public void onBackPressed() {
Intent intent=new Intent(DeletePassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
*/
}

@ -27,38 +27,17 @@ import android.widget.PopupMenu.OnMenuItemClickListener;
import net.micode.notes.R;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: DropdownMenu
* @Description: DropdownMenu
* DropdownMenu
* 1.使DropdownMenu便
* 2.使DropdownMenu
* 3.使DropdownMenu
* @Author: xumingyang
* @CreateDate: 2023-12-24 13:57
* @UpdateUser:
* @UpdateDate: 2023-12-24 13:57
* @UpdateRemark:
* @Version: 1.0
*/
public class DropdownMenu {
private Button mButton;
private PopupMenu mPopupMenu;
//声明一个下拉菜单
private Menu mMenu;
public DropdownMenu(Context context, Button button, int menuId) {
mButton = button;
mButton.setBackgroundResource(R.drawable.dropdown_icon);
//设置这个view的背景
mPopupMenu = new PopupMenu(context, mButton);
mMenu = mPopupMenu.getMenu();
mPopupMenu.getMenuInflater().inflate(menuId, mMenu);
//MenuInflater是用来实例化Menu目录下的Menu布局文件
//根据ID来确认menu的内容选项
mButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mPopupMenu.show();
@ -70,13 +49,13 @@ public class DropdownMenu {
if (mPopupMenu != null) {
mPopupMenu.setOnMenuItemClickListener(listener);
}
}//设置菜单的监听
}
public MenuItem findItem(int id) {
return mMenu.findItem(id);
}
//对于菜单选项的初始化,根据索引搜索菜单需要的选项
public void setTitle(CharSequence title) {
mButton.setText(title);
}
}//布局文件,设置标题
}

@ -28,54 +28,25 @@ import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: FoldersListAdapter
* @Description: FoldersListAdapter
* @Author: xumingyang
* @CreateDate: 2023-12-24 14:05
* @UpdateUser:
* @UpdateDate: 2023-12-24 14:05
* @UpdateRemark:
* @Version: 1.0
*/
public class FoldersListAdapter extends CursorAdapter {
/*
* CursorAdapterCursorListView
* FoldersListAdapterCursorAdapter
* 便
* folder
*/
public static final String [] PROJECTION = {
NoteColumns.ID,
NoteColumns.SNIPPET
};//调用数据库中便签的ID和片段
};
public static final int ID_COLUMN = 0;
public static final int NAME_COLUMN = 1;
/**
* @method FoldersListAdapter
* @description FoldersListAdapter
* @param context
* c Cursor
*/
public FoldersListAdapter(Context context, Cursor c) {
super(context, c);
// TODO Auto-generated constructor stub
}//数据库操作
}
/**
* @method newView
* @description
* @return 使
*/
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new FolderListItem(context);
}//创建一个文件夹,对于各文件夹中子标签的初始化
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
@ -84,23 +55,20 @@ public class FoldersListAdapter extends CursorAdapter {
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
((FolderListItem) view).bind(folderName);
}
}//将各个布局文件绑定起来
}
public String getFolderName(Context context, int position) {
Cursor cursor = (Cursor) getItem(position);
return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
}//根据数据库中标签的ID得到标签的各项内容
}
private class FolderListItem extends LinearLayout {
private TextView mName;
public FolderListItem(Context context) {
super(context);
//操作数据库
inflate(context, R.layout.folder_list_item, this);
//根据布局文件的名字等信息将其找出来
mName = (TextView) findViewById(R.id.tv_folder_name);
}

@ -0,0 +1,68 @@
package net.micode.notes.ui;
import android.view.View;//可视化界面
import android.app.Activity;//完成函数周期
import android.view.WindowManager;
import android.widget.Button;//实现按钮
import android.widget.EditText;//输入显示
import android.widget.Toast;//设计让登录界面无法被跳过
import android.os.Bundle;//获取输入密码
import android.content.SharedPreferences;
import android.content.Intent;//数据交互
import net.micode.notes.R;
public class LoginActivity extends Activity {
EditText lg_password;
Button lg_login;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
SharedPreferences pref = getSharedPreferences("user management", MODE_PRIVATE);
boolean User_boolean =pref.getBoolean("user",false);//是否有密码
//没有密码直接进入
if(User_boolean==false){
Intent intent=new Intent(LoginActivity.this,NotesListActivity.class);
startActivity(intent);
finish();
}
setContentView(R.layout.activity_login);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
);
lg_password =(EditText)findViewById(R.id.lg_password);
lg_login=(Button)findViewById(R.id.login);
lg_login.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
String password=pref.getString("password","");
if(password.equals("")==false&&password.equals(lg_password.getText().toString())==true){
Intent intent=new Intent(LoginActivity.this,NotesListActivity.class);
startActivity(intent);
finish();
}
else{
Toast.makeText(LoginActivity.this,"密码错误",Toast.LENGTH_SHORT).show();
lg_password.setText("");
}
}
});
}
public void onClick(View v) {
SharedPreferences pref =getSharedPreferences("user management",MODE_PRIVATE);
String password =pref.getString("password","");
if(password.equals("")==false && password.equals(lg_password.getText().toString())==true) {
Intent intent = new Intent(LoginActivity.this, NotesListActivity.class);
startActivity(intent);
finish();
}
else{
Toast.makeText(LoginActivity.this,"密码错误",Toast.LENGTH_SHORT).show();
lg_password.setText("");
}
}
}

@ -37,27 +37,6 @@ import net.micode.notes.R;
import java.util.HashMap;
import java.util.Map;
/**
*
* @ProjectName: 便
* @Package: net.micode.notes.ui
* @ClassName: NoteEditText
* @Description:
*
*
* OnTextViewChangeListener
* OnTextViewChangeListener
* URLSpan
* @Author: xumingyang
* @CreateDate: 2024-01-06 8:13
* @UpdateUser:
* @UpdateDate: 2024-01-06 8:13
* @UpdateRemark:
* @Version: 1.0
*/
//继承edittext设置便签设置文本框
public class NoteEditText extends EditText {
private static final String TAG = "NoteEditText";
private int mIndex;
@ -67,7 +46,6 @@ public class NoteEditText extends EditText {
private static final String SCHEME_HTTP = "http:" ;
private static final String SCHEME_EMAIL = "mailto:" ;
//建立一个字符和整数的hash表用于链接电话网站还有邮箱
private static final Map<String, Integer> sSchemaActionResMap = new HashMap<String, Integer>();
static {
sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel);
@ -78,20 +56,17 @@ public class NoteEditText extends EditText {
/**
* Call by the {@link NoteEditActivity} to delete or add edit text
*/
//在NoteEditActivity中删除或添加文本的操作可以看做是一个文本是否被变的标记英文注释已说明的很清楚
public interface OnTextViewChangeListener {
/**
* Delete current edit text when {@link KeyEvent#KEYCODE_DEL} happens
* and the text is null
*/
//处理删除按键时的操作
void onEditTextDelete(int index, String text);
/**
* Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER}
* happen
*/
//处理进入按键时的操作
void onEditTextEnter(int index, String text);
/**
@ -102,206 +77,141 @@ public class NoteEditText extends EditText {
private OnTextViewChangeListener mOnTextViewChangeListener;
//根据context设置文本
public NoteEditText(Context context) {
super(context, null);//用super引用父类变量
super(context, null);
mIndex = 0;
}
//设置当前光标
public void setIndex(int index) {
mIndex = index;
}
//初始化文本修改标记
public void setOnTextViewChangeListener(OnTextViewChangeListener listener) {
mOnTextViewChangeListener = listener;
}
//AttributeSet 百度了一下是自定义空控件属性,用于维护便签动态变化的属性
//初始化便签
public NoteEditText(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.editTextStyle);
}
// 根据defstyle自动初始化
public NoteEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
/**
* @method onTouchEvent
* @description 便
* @param *event
*
* @return super.onTouchEvent(event)
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
//重写了需要处理屏幕被按下的事件
case MotionEvent.ACTION_DOWN:
//更新当前坐标值
int x = (int) event.getX();
int y = (int) event.getY();
x -= getTotalPaddingLeft();
y -= getTotalPaddingTop();
x += getScrollX();
y += getScrollY();
//用布局控件layout根据x,y的新值设置新的位置
Layout layout = getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
Selection.setSelection(getText(), off);
break;
}
//更新光标新的位置
return super.onTouchEvent(event);
}
/**
* @method onKeyDown
* @description
* @param
* @return super.onKeyDown(keyCode, event)
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
//根据按键的 Unicode 编码值来处理
case KeyEvent.KEYCODE_ENTER:
//“进入”按键
if (mOnTextViewChangeListener != null) {
return false;
//如果设置了则返回false否则交给父类处理。
}
break;
case KeyEvent.KEYCODE_DEL:
//“删除”按键
mSelectionStartBeforeDelete = getSelectionStart();
//通过getSelectionStart()方法获取当前光标的位置,并记录下来 break;
break;
default:
break;
}
//继续执行父类的其他点击事件
return super.onKeyDown(keyCode, event);
}
/**
* @method onKeyUp
* @description
* @param keyCode keyevent
* @return super.onKeyUp(keyCode, event)
*/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch(keyCode) {
//根据按键的 Unicode 编码值来处理有删除和进入2种操作
case KeyEvent.KEYCODE_DEL:
//若是被修改过
if (mOnTextViewChangeListener != null) {
//若之前有被修改并且文档不为空
if (0 == mSelectionStartBeforeDelete && mIndex != 0) {
mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString());
//利用上文OnTextViewChangeListener对KEYCODE_DEL按键情况的删除函数进行删除
return true;
}
} else {
Log.d(TAG, "OnTextViewChangeListener was not seted");
//其他情况报错,文档的改动监听器并没有建立
}
break;
case KeyEvent.KEYCODE_ENTER:
//同上也是分为监听器是否建立2种情况
if (mOnTextViewChangeListener != null) {
int selectionStart = getSelectionStart();
//获取当前位置
String text = getText().subSequence(selectionStart, length()).toString();
//获取当前文本
setText(getText().subSequence(0, selectionStart));
//根据获取的文本设置当前文本
mOnTextViewChangeListener.onEditTextEnter(mIndex + 1, text);
//当{@link KeyEvent#KEYCODE_ENTER}添加新文本
} else {
Log.d(TAG, "OnTextViewChangeListener was not seted");
//其他情况报错,文档的改动监听器并没有建立
}
break;
default:
break;
}
//继续执行父类的其他按键弹起的事件
return super.onKeyUp(keyCode, event);
}
/**
* @method onFocusChanged
* @description TextViewTextViewonTextChange()
* @param * focusedViewFocusedtruefalse
* direction
* @return Viewnull
*/
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (mOnTextViewChangeListener != null) {
//若监听器已经建立
if (!focused && TextUtils.isEmpty(getText())) {
//获取到焦点并且文本不为空
mOnTextViewChangeListener.onTextChange(mIndex, false);
//mOnTextViewChangeListener子函数置false隐藏事件选项
} else {
mOnTextViewChangeListener.onTextChange(mIndex, true);
//mOnTextViewChangeListener子函数置true显示事件选项
}
}
//继续执行父类的其他焦点变化的事件
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
/**
* @method onCreateContextMenu
* @description Context MenuURL
*/
@Override
protected void onCreateContextMenu(ContextMenu menu) {
if (getText() instanceof Spanned) {
//有文本存在
int selStart = getSelectionStart();
int selEnd = getSelectionEnd();
//获取文本开始和结尾位置
int min = Math.min(selStart, selEnd);
int max = Math.max(selStart, selEnd);
//获取开始到结尾的最大值和最小值
final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class);
//设置url的信息的范围值
if (urls.length == 1) {
int defaultResId = 0;
for(String schema: sSchemaActionResMap.keySet()) {
//获取计划表中所有的key值
if(urls[0].getURL().indexOf(schema) >= 0) {
//若url可以添加则在添加后将defaultResId置为key所映射的值
defaultResId = sSchemaActionResMap.get(schema);
break;
}
}
if (defaultResId == 0) {
//defaultResId == 0则说明url并没有添加任何东西所以置为连接其他SchemaActionResMap的值
defaultResId = R.string.note_link_other;
}
//建立菜单
menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener(
new OnMenuItemClickListener() {
//新建按键监听器
public boolean onMenuItemClick(MenuItem item) {
// goto a new intent
urls[0].onClick(NoteEditText.this);
//根据相应的文本设置菜单的按键
return true;
}
});
}
}
//继续执行父类的其他菜单创建的事件
super.onCreateContextMenu(menu);
}
}

@ -25,20 +25,7 @@ import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: NoteItemData
* @Description: 便便便
* 便ID
* @Author: xumingyang
* @CreateDate: 2024-01-06 8:46
* @UpdateUser:
* @UpdateDate: 2024-01-06 8:46
* @UpdateRemark:
* @Version: 1.0
*/
public class NoteItemData {
static final String [] PROJECTION = new String [] {
NoteColumns.ID,
@ -55,7 +42,6 @@ public class NoteItemData {
NoteColumns.WIDGET_TYPE,
};
//常量标记和数据就不一一标记了,意义翻译基本就知道
private static final int ID_COLUMN = 0;
private static final int ALERTED_DATE_COLUMN = 1;
private static final int BG_COLOR_ID_COLUMN = 2;
@ -90,9 +76,7 @@ public class NoteItemData {
private boolean mIsOneNoteFollowingFolder;
private boolean mIsMultiNotesFollowingFolder;
//初始化NoteItemData主要利用光标cursor获取的东西
public NoteItemData(Context context, Cursor cursor) {
//getxxx为转换格式
mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN);
@ -107,7 +91,7 @@ public class NoteItemData {
mType = cursor.getInt(TYPE_COLUMN);
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
//初始化电话号码的信息
mPhoneNumber = "";
if (mParentId == Notes.ID_CALL_RECORD_FOLDER) {
mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId);
@ -125,35 +109,31 @@ public class NoteItemData {
checkPostion(cursor);
}
///根据鼠标的位置设置标记,和位置
private void checkPostion(Cursor cursor) {
//初始化几个标记
mIsLastItem = cursor.isLast() ? true : false;
mIsFirstItem = cursor.isFirst() ? true : false;
mIsOnlyOneItem = (cursor.getCount() == 1);
//初始化“多重子文件”“单一子文件”2个标记
mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false;
//主要是设置上述2标记
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {//若是note格式并且不是第一个元素
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
int position = cursor.getPosition();
if (cursor.moveToPrevious()) {//获取光标位置后看上一行
if (cursor.moveToPrevious()) {
if (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER
|| cursor.getInt(TYPE_COLUMN) == Notes.TYPE_SYSTEM) {//若光标满足系统或note格式
|| cursor.getInt(TYPE_COLUMN) == Notes.TYPE_SYSTEM) {
if (cursor.getCount() > (position + 1)) {
mIsMultiNotesFollowingFolder = true;//若是数据行数大于但前位置+1则设置成正确
mIsMultiNotesFollowingFolder = true;
} else {
mIsOneNoteFollowingFolder = true;
}
}
if (!cursor.moveToNext()) {//若不能再往下走则报错
if (!cursor.moveToNext()) {
throw new IllegalStateException("cursor move to previous but can't move back");
}
}
}
}
//以下都是获取标记
public boolean isOneFollowingFolder() {
return mIsOneNoteFollowingFolder;
}
@ -234,7 +214,6 @@ public class NoteItemData {
return (mAlertDate > 0);
}
//若数据父id为保存至文件夹模式的id且满足电话号码单元不为空则isCallRecord为true
public boolean isCallRecord() {
return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber));
}

@ -78,20 +78,13 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: NotesListActivity
* @Description: 便
* @Author: xumingyang
* @CreateDate: 2024-01-09 11:02
* @UpdateUser:
* @UpdateDate: 2024-01-09 11:02
* @UpdateRemark:
* @Version: 1.0
*/
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
/*
*/
private int background = -1;
public static int secret_mode = 0;//初始化为0表示进入隐私模式
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
@ -148,66 +141,39 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private final static int REQUEST_CODE_OPEN_NODE = 102;
private final static int REQUEST_CODE_NEW_NODE = 103;
/**
* @method onCreate
* @description
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
/*
final Javafinal
finalfinalfinal
final
final
final
*/
super.onCreate(savedInstanceState);
// 调用父类的onCreate函数
setContentView(R.layout.note_list);
//绑定视图
initResources();
//调用初始化函数进行初始化 包括数据和视图的关联
getWindow().setBackgroundDrawableResource(R.drawable.picture1);
/**
* Insert an introduction when user firstly use this application
*/
setAppInfoFromRawRes();
}
/**
* @method onActivityResult
* @description Activity
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// 结果值 和 要求值 符合要求
if (resultCode == RESULT_OK
&& (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) {
mNotesListAdapter.changeCursor(null);
} else {
super.onActivityResult(requestCode, resultCode, data);
// 调用 Activity 的onActivityResult
}
}
/**
* @method setAppInfoFromRawRes
* @description 便
*/
private void setAppInfoFromRawRes() {
// Android平台给我们提供了一个SharedPreferences类它是一个轻量级的存储类特别适合用于保存软件配置参数。
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
StringBuilder sb = new StringBuilder();
InputStream in = null;
try {
// 把资源文件放到应用程序的/raw/raw下那么就可以在应用中使用getResources获取资源后,
// 以openRawResource方法不带后缀的资源文件名打开这个文件。
in = getResources().openRawResource(R.raw.introduction);
in = getResources().openRawResource(R.raw.introduction);
if (in != null) {
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
char [] buf = new char[1024]; // 自行定义的数值,使用者不知道有什么意义
char [] buf = new char[1024];
int len = 0;
while ((len = br.read(buf)) > 0) {
sb.append(buf, 0, len);
@ -220,7 +186,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
e.printStackTrace();
return;
} finally {
if (in != null) {
if(in != null) {
try {
in.close();
} catch (IOException e) {
@ -230,13 +196,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
// 创建空的WorkingNote
WorkingNote note = WorkingNote.createEmptyNote(this, Notes.ID_ROOT_FOLDER,
AppWidgetManager.INVALID_APPWIDGET_ID, Notes.TYPE_WIDGET_INVALIDE,
ResourceParser.RED);
note.setWorkingText(sb.toString());
if (note.saveNote()) {
// 更新保存note的信息
sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit();
} else {
Log.e(TAG, "Save introduction note error");
@ -245,30 +209,17 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
* @method onStart
* @description UI
*/
@Override
protected void onStart() {
super.onStart();
//调用父类的 onStart() 方法
startAsyncNotesListQuery();
}
/**
* @method initResources
* @description
*/
private void initResources() {
mContentResolver = this.getContentResolver();
// 获取应用程序的数据,得到类似数据表的东西
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
// findViewById 是安卓编程的定位函数,主要是引用.R文件里的引用名
mNotesListView = (ListView) findViewById(R.id.notes_list);
// 绑定XML中的ListView作为Item的容器
mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null),
null, false);
mNotesListView.setOnItemClickListener(new OnListItemClickListener());
@ -276,7 +227,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mNotesListAdapter = new NotesListAdapter(this);
mNotesListView.setAdapter(mNotesListAdapter);
mAddNewNote = (Button) findViewById(R.id.btn_new_note);
// 在activity中要获取该按钮
mAddNewNote.setOnClickListener(this);
mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener());
mDispatch = false;
@ -287,7 +237,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mModeCallBack = new ModeCallback();
}
// 继承自ListView.MultiChoiceModeListener 和 OnMenuItemClickListener
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
private DropdownMenu mDropDownMenu;
private ActionMode mActionMode;
@ -326,22 +275,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
/**
* @method updateMenu
* @description
*
*/
private void updateMenu() {
int selectedCount = mNotesListAdapter.getSelectedCount();
//取已选择的项目数量。
// Update dropdown menu
String format = getResources().getString(R.string.menu_select_title, selectedCount);
//获取一个格式化的字符串,其中包含已选择的项目数量。然后,将该字符串设置为下拉菜单的标题
mDropDownMenu.setTitle(format); // 更改标题
mDropDownMenu.setTitle(format);
MenuItem item = mDropDownMenu.findItem(R.id.action_select_all);
if (item != null) {
if (mNotesListAdapter.isAllSelected()) {
//检查是否所有项目都被选择。
item.setChecked(true);
item.setTitle(R.string.menu_deselect_all);
} else {
@ -350,73 +291,40 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
/**
* @method onPrepareActionMode
* @description
* @return false
*/
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
/**
* @method onActionItemClicked
* @description
* @param mode item mode item
* @return false true
*/
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
return false;
}
/**
* @method onDestroyActionMode
* @description ActionMode.Callback
*/
public void onDestroyActionMode(ActionMode mode) {
mNotesListAdapter.setChoiceMode(false);
//取消列表的选择模式。
mNotesListView.setLongClickable(true);
//重新启用列表项的长按事件。
mAddNewNote.setVisibility(View.VISIBLE);
//将新建笔记按钮设置为可见状态。
}
//用于结束当前的操作模式。
public void finishActionMode() {
mActionMode.finish();
//在调用 finish() 方法之前,需要确保当前存在一个有效的操作模式对象 mActionMode。
// 如果当前不存在任何操作模式对象,则调用 finish() 方法将抛出异常。
}
/**
* @method onItemCheckedStateChanged
* @description ActionMode.Callback
* @param mode position id checked
*/
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
boolean checked) {
mNotesListAdapter.setCheckedItem(position, checked);
//将列表项的选中状态传递给列表适配器,在适配器中更新相应的数据。
updateMenu();
//根据当前选中的列表项的数量,更新操作模式的菜单项。
}
/**
* @method onMenuItemClick
* @description MenuItem.OnMenuItemClickListener
* @param * item
*/
public boolean onMenuItemClick(MenuItem item) {
if (mNotesListAdapter.getSelectedCount() == 0) {
Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none),
Toast.LENGTH_SHORT).show();
return true;
}
//根据被单击的菜单项 ID执行不同的操作。
int itemId = item.getItemId();
if (itemId == R.id.delete) {
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
@ -437,17 +345,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
startQueryDestinationFolders();
} else {
return false;
//如果被单击的菜单项不是删除或移动菜单项,则返回 false
}
return true;
//如果成功处理了菜单项,则返回 true。
}
}
/**
* @method
* @description OnTouchListener
*/
private class NewNoteOnTouchListener implements OnTouchListener {
public boolean onTouch(View v, MotionEvent event) {
@ -458,7 +360,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
int newNoteViewHeight = mAddNewNote.getHeight();
int start = screenHeight - newNoteViewHeight;
int eventY = start + (int) event.getY();
//首先获取屏幕高度和新笔记视图的高度,并计算出起始位置。如果当前状态是子文件夹状态,则还需减去标题栏的高度。
/**
* Minus TitleBar's height
*/
@ -476,7 +377,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
* also change. This is very bad, just for the UI designer's strong requirement.
*/
if (event.getY() < (event.getX() * (-0.12) + 94)) {
//通过判断触摸点的坐标是否在"New Note"按钮的透明部分上方,来决定是否将事件转发给位于按钮后面的列表视图。
View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
- mNotesListView.getFooterViewsCount());
if (view != null && view.getBottom() > start
@ -495,7 +395,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mDispatchY += (int) event.getY() - mOriginY;
event.setLocation(event.getX(), mDispatchY);
return mNotesListView.dispatchTouchEvent(event);
//当动作为ACTION_MOVE移动如果之前已经开始转发事件则更新转发的Y坐标并将事件重新定位后转发给列表视图。
}
break;
}
@ -504,7 +403,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
event.setLocation(event.getX(), mDispatchY);
mDispatch = false;
return mNotesListView.dispatchTouchEvent(event);
//如果没有进行事件转发则返回false表示本类未处理该事件。
}
break;
}
@ -514,24 +412,37 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
/**
* @method startAsyncNotesListQuery
* @description UI
* @param
* *FOLDER_NOTE_LIST_QUERY_TOKENID
* null
* URINotes.CONTENT_NOTE_URIURI
* NoteItemData.PROJECTION
* selection使
*
*/
private void startAsyncNotesListQuery() {
String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
: NORMAL_SELECTION;
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {
String.valueOf(mCurrentFolderId)
}, NoteColumns.TOP+" DESC,"+NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
String str1 = "123456789";
String[] PROJECTION = new String[]{ //定义一个新的PROJECTION数组只换掉SNIPPET
NoteColumns.ID,
NoteColumns.ALERTED_DATE,
NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE,
NoteColumns.HAS_ATTACHMENT,
NoteColumns.MODIFIED_DATE,
NoteColumns.NOTES_COUNT,
NoteColumns.PARENT_ID,
//NoteColumns.SNIPPET,
str1,
NoteColumns.TYPE,
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
};
if(secret_mode == 0) {
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[]{
String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
else {
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, PROJECTION, selection, new String[]{
String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
}
private final class BackgroundQueryHandler extends AsyncQueryHandler {
@ -539,27 +450,17 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
super(contentResolver);
}
/**
* @method onQueryComplete
* @description
* @param token token
*/
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch (token) {
case FOLDER_NOTE_LIST_QUERY_TOKEN:
//表示文件夹笔记列表查询完成。
mNotesListAdapter.changeCursor(cursor);
//更新笔记列表的显示内容。
break;
case FOLDER_LIST_QUERY_TOKEN:
//表示文件夹列表查询完成。
if (cursor != null && cursor.getCount() > 0) {
showFolderListMenu(cursor);
//调用showFolderListMenu(cursor)方法,显示文件夹列表菜单。
} else {
Log.e(TAG, "Query folder failed");
//在日志中记录查询文件夹失败的错误信息。
}
break;
default:
@ -568,48 +469,32 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
* @method showFolderListMenu
* @description
*/
private void showFolderListMenu(Cursor cursor) {
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(R.string.menu_title_select_folder);
final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor);
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
//设置对话框的列表项和点击事件监听器。
//将适配器设置为对话框的列表项,并在点击列表项时执行相应的操作。
public void onClick(DialogInterface dialog, int which) {
DataUtils.batchMoveToFolder(mContentResolver,
mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which));
Toast.makeText(
//显示一条消息,内容为移动的笔记数量和所选文件夹的名称。
NotesListActivity.this,
getString(R.string.format_move_notes_to_folder,
mNotesListAdapter.getSelectedCount(),
adapter.getFolderName(NotesListActivity.this, which)),
Toast.LENGTH_SHORT).show();
mModeCallBack.finishActionMode();
//结束动作模式Action Mode即退出多选模式。
}
});
builder.show();
//显示文件夹列表菜单对话框
}
/**
* @method createNewNote
* @description
* @param * intent NoteEditActivity
* ACTION_INSERT_OR_EDIT
* Notes.INTENT_EXTRA_FOLDER_IDID
*/
private void createNewNote() {
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
//通过startActivityForResult方法启动活动并传递了一个请求码REQUEST_CODE_NEW_NOTE以便在活动返回结果时进行区分。
}
private void batchDelete() {
@ -649,28 +534,16 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}.execute();
}
/**
* @method deleteFolder
* @description
* @date: 2024-01-09 14:54
* @author:
* @param folderIdID
* @return
*/
private void deleteFolder(long folderId) {
if (folderId == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Wrong folder id, should not happen " + folderId);
return;
//在方法内部首先通过条件判断检查folderId是否等于Notes.ID_ROOT_FOLDER根文件夹的ID
// 如果是根文件夹的ID则记录错误日志并返回不执行删除操作。
}
HashSet<Long> ids = new HashSet<Long>();
ids.add(folderId);
//创建一个HashSet<Long>对象并将folderId添加到该集合中
HashSet<AppWidgetAttribute> widgets = DataUtils.getFolderNoteWidget(mContentResolver,
folderId);
//调用DataUtils.getFolderNoteWidget()方法获取与该文件夹相关联的小部件。将结果保存在widgets变量中。
if (!isSyncMode()) {
// if not synced, delete folder directly
DataUtils.batchDeleteNotes(mContentResolver, ids);
@ -683,16 +556,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) {
updateWidget(widget.widgetId, widget.widgetType);
//遍历widgets集合中的每个小部件并根据小部件的ID和类型调用updateWidget()方法进行小部件的更新操作。
}
}
}
}
/**
* @method openNode
* @description
*/
private void openNode(NoteItemData data) {
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_VIEW);
@ -700,45 +568,29 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE);
}
/**
* @method openFolder
* @description
* @param data
* @return
*/
private void openFolder(NoteItemData data) {
mCurrentFolderId = data.getId();
//将当前文件夹的ID设置为参数data的ID并调用startAsyncNotesListQuery()方法开始异步查询当前文件夹下的笔记列表。
startAsyncNotesListQuery();
//根据文件夹的ID判断当前状态
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
mState = ListEditState.CALL_RECORD_FOLDER;
mAddNewNote.setVisibility(View.GONE);
//如果文件夹的ID为Notes.ID_CALL_RECORD_FOLDER则将状态设置为ListEditState.CALL_RECORD_FOLDER并隐藏添加新笔记按钮
} else {
mState = ListEditState.SUB_FOLDER;
//将状态设置为ListEditState.SUB_FOLDER。
}
//根据文件夹的ID设置标题栏的文本
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
mTitleBar.setText(R.string.call_record_folder_name);
//如果文件夹的ID为Notes.ID_CALL_RECORD_FOLDER则设置标题栏的文本为字符串资源R.string.call_record_folder_name
} else {
mTitleBar.setText(data.getSnippet());
//否则设置标题栏的文本为文件夹的名称通过调用data.getSnippet()方法获取)。
}
mTitleBar.setVisibility(View.VISIBLE);
//将标题栏设置为可见状态。
}
//当按钮控件的 id 为 btn_new_note 的按钮被点击时,该方法会调用 createNewNote() 方法。
public void onClick(View v) {
if (v.getId() == R.id.btn_new_note) {
createNewNote();
}
}
//显示软键盘
private void showSoftInput() {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
@ -746,30 +598,18 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
//隐藏软键盘
private void hideSoftInput(View view) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
/**
* @method showCreateOrModifyFolderDialog
* @description
* @param *create
*/
private void showCreateOrModifyFolderDialog(final boolean create) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null);
//在方法内部首先创建一个AlertDialog.Builder对象并通过LayoutInflater从XML布局文件中实例化一个视图。
final EditText etName = (EditText) view.findViewById(R.id.et_foler_name);
showSoftInput();
//获取EditText对象用于输入文件夹名称并调用showSoftInput()方法显示软键盘。
//根据create参数的值判断是创建文件夹还是修改文件夹。如果是修改文件夹
if (!create) {
if (mFocusNoteDataItem != null) {
etName.setText(mFocusNoteDataItem.getSnippet());
// 从mFocusNoteDataItem中获取文件夹名称并设置对话框的标题为对应的修改文件夹名称
builder.setTitle(getString(R.string.menu_folder_change_name));
} else {
Log.e(TAG, "The long click data item is null");
@ -778,7 +618,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
} else {
etName.setText("");
builder.setTitle(this.getString(R.string.menu_create_folder));
// 如果是创建文件夹则将EditText的文本设置为空并设置对话框的标题为创建文件夹。
}
builder.setPositiveButton(android.R.string.ok, null);
@ -808,7 +647,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
values.put(NoteColumns.LOCAL_MODIFIED, 1);
mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID
+ "=?", new String[] {
String.valueOf(mFocusNoteDataItem.getId())//获取文件夹名称,并设置对话框的标题为对应的修改文件夹名称;
String.valueOf(mFocusNoteDataItem.getId())
});
}
} else if (!TextUtils.isEmpty(name)) {
@ -821,6 +660,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
});
if (TextUtils.isEmpty(etName.getText())) {
positive.setEnabled(false);
}
@ -848,27 +688,15 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
});
}
/**
* @method onBackPressed
* @description
*/
@Override
public void onBackPressed() {
switch (mState) {
//通过switch语句检查当前的状态mState
case SUB_FOLDER:
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
mState = ListEditState.NOTE_LIST;
startAsyncNotesListQuery();
mTitleBar.setVisibility(View.GONE);
break;
/*
SUB_FOLDER
mCurrentFolderIdIDNotes.ID_ROOT_FOLDER
ListEditState.NOTE_LIST
startAsyncNotesListQuery()
mTitleBar.setVisibility(View.GONE)
*/
case CALL_RECORD_FOLDER:
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
mState = ListEditState.NOTE_LIST;
@ -876,42 +704,27 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mTitleBar.setVisibility(View.GONE);
startAsyncNotesListQuery();
break;
/*
CALL_RECORD_FOLDER
mCurrentFolderIdID
mAddNewNote.setVisibility(View.VISIBLE)
startAsyncNotesListQuery()
*/
case NOTE_LIST:
super.onBackPressed();
//调用父类的onBackPressed()方法,执行默认的返回操作。
break;
default:
break;
}
}
/**
* @method updateWidget
* @description widget
*/
private void updateWidget(int appWidgetId, int appWidgetType) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
//根据appWidgetType的不同值设置不同的NoteWidgetProvider类作为接收广播的目标。
if (appWidgetType == Notes.TYPE_WIDGET_2X) {
intent.setClass(this, NoteWidgetProvider_2x.class);
//设置NoteWidgetProvider_2x类作为目标
} else if (appWidgetType == Notes.TYPE_WIDGET_4X) {
intent.setClass(this, NoteWidgetProvider_4x.class);
//则设置NoteWidgetProvider_4x类作为目标。
} else {
Log.e(TAG, "Unspported widget type");
//不匹配任何已知的类型,则记录一个错误日志并返回
return;
}
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
appWidgetId//将appWidgetId作为额外参数放入意图中并通过sendBroadcast方法发送广播。
appWidgetId
});
sendBroadcast(intent);
@ -929,29 +742,17 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
};
/**
* @method onContextMenuClosed
* @description
*/
@Override
public void onContextMenuClosed(Menu menu) {
if (mNotesListView != null) {
mNotesListView.setOnCreateContextMenuListener(null);
//然后通过调用 setOnCreateContextMenuListener(null) 方法将上下文菜单的创建监听器设置为 null即移除了上下文菜单的创建监听器。
}
super.onContextMenuClosed(menu);
//调用 super.onContextMenuClosed(menu) 方法来执行父类的相应操作。
}
/**
* @method onContextItemSelected
* @description
* @return true false
*/
@Override
public boolean onContextItemSelected(MenuItem item) {
if (mFocusNoteDataItem == null) {
//通过检查mFocusNoteDataItem是否为空来确保当前长按操作的数据项不为空
Log.e(TAG, "The long click data item is null");
return false;
}
@ -959,7 +760,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
case MENU_FOLDER_VIEW:
openFolder(mFocusNoteDataItem);
break;
//如果用户选择了“查看文件夹”菜单项则调用openFolder()方法打开该文件夹。
case MENU_FOLDER_DELETE:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.alert_title_delete));
@ -974,12 +774,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
break;
//如果用户选择了“删除文件夹”菜单项,则弹出一个提示对话框,
// 并在用户确认删除操作后调用deleteFolder()方法执行相应的数据库操作。
case MENU_FOLDER_CHANGE_NAME:
showCreateOrModifyFolderDialog(false);
break;
//如果用户选择了“重命名文件夹”菜单项则调用showCreateOrModifyFolderDialog()方法显示创建或修改文件夹的对话框。
default:
break;
}
@ -987,18 +784,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
/**
* @method onPrepareOptionsMenu
* @description
* mState
* @return true
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
//通过调用menu.clear()方法清除菜单中的所有项。
//根据mState的不同值使用getMenuInflater().inflate()方法加载对应的菜单布局文件。
if (mState == ListEditState.NOTE_LIST) {
getMenuInflater().inflate(R.menu.note_list, menu);
// set sync or sync_cancel
@ -1011,17 +799,53 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
} else {
Log.e(TAG, "Wrong state:" + mState);
}
if (background == -1)
{
menu.findItem(R.id.menu_switch_to_picture3).setVisible(false);
}else if (background == 0){
menu.findItem(R.id.menu_switch_to_picture2).setVisible(false);
}else if (background == 1){
menu.findItem(R.id.menu_switch_to_picture3).setVisible(false);
}
if(secret_mode ==1){
menu.findItem(R.id.menu_secret).setVisible(false);
}
else{
menu.findItem(R.id.menu_quit_secret).setVisible(false);
}
return true;
}
/**
* @method onOptionsItemSelected
* @description Android MenuItem
*/
private void change_password() {
Intent intent=new Intent(NotesListActivity.this,ChangePassword.class);
startActivity(intent);
finish();
}
private void delete_password() {
Intent intent=new Intent(NotesListActivity.this, DeletePassword.class);
startActivity(intent);
finish();
}
private void set_login_password() {
Intent intent=new Intent(NotesListActivity.this, CreatePassword.class);
startActivity(intent);
finish();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int login_mode=-1;
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
boolean User_boolean = pref.getBoolean("user",false);
if(User_boolean==true){
login_mode=1;
}
else{
login_mode=0;
}
int itemId = item.getItemId();
//该方法首先获取被选中菜单项的ID然后根据不同的ID执行相应的操作。
if (itemId == R.id.menu_new_folder) {
showCreateOrModifyFolderDialog(true);
} else if (itemId == R.id.menu_export_text) {
@ -1042,31 +866,74 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
createNewNote();
} else if (itemId == R.id.menu_search) {
onSearchRequested();
}else if (itemId == R.id.menu_switch_to_picture3) {
background = 1;
getWindow().setBackgroundDrawableResource(R.drawable.picture1);
}else if (itemId == R.id.menu_switch_to_picture2) {
background = 0;
getWindow().setBackgroundDrawableResource(R.drawable.picture2);
}else if (itemId == R.id.menu_switch_to_picture1) {
background = -1;
getWindow().setBackgroundDrawableResource(R.drawable.picture3);
}
else if (itemId == R.id.menu_createlogin) { //设置登录密码功能
if(login_mode == 0) {//没有设置密码
set_login_password();
}
else{
Toast.makeText(NotesListActivity.this,"您已经设置了密码",Toast.LENGTH_SHORT).show();
}
}
else if (itemId == R.id.menu_deletelogin){
if(login_mode==1) {
delete_password();
}
else {
Toast.makeText(NotesListActivity.this, "您还没有设置密码", Toast.LENGTH_SHORT).show();
}
}
else if (itemId ==R.id.menu_changelogin) {
if (login_mode == 1) {
change_password();
}
else{
Toast.makeText(NotesListActivity.this,"您还没有设置密码",Toast.LENGTH_SHORT).show();
}
}
else if (itemId == R.id.menu_secret){
secret_mode = 1;
startAsyncNotesListQuery();
Toast.makeText(this,"您已进入隐私模式",Toast.LENGTH_SHORT).show();
}
else if (itemId == R.id.menu_quit_secret){
secret_mode = 0;
AlertDialog.Builder dialog = new AlertDialog.Builder(NotesListActivity.this);
dialog.setTitle("提醒");
dialog.setMessage("您确认退出隐私模式吗?");
dialog.setCancelable(false);
dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAsyncNotesListQuery();
Toast.makeText(NotesListActivity.this,"您已退出隐私模式",Toast.LENGTH_SHORT).show();
}
});
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which){}
});
dialog.show();
}
return true;
/*
* R.id.menu_new_foldershowCreateOrModifyFolderDialog(true)
* R.id.menu_export_textexportNoteToText()
* R.id.menu_syncisSyncMode()GTaskSyncServicestartPreferenceActivity
* R.id.menu_settingstartPreferenceActivity
* R.id.menu_new_notecreateNewNote
* R.id.menu_searchonSearchRequested
*/
}
/**
* @method onSearchRequested
* @description nSearchRequested
* @param *null
* false
* null
* false
*/
@Override
public boolean onSearchRequested() {
startSearch(null, false, null /* appData */, false);
return true;
}
private void exportNoteToText() {
final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this);
new AsyncTask<Void, Void, Integer>() {
@ -1109,22 +976,13 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}.execute();
}
//用于检查是否处于同步模式
private boolean isSyncMode() {
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}
/**
* @method startPreferenceActivity
* @description
* @param
* @return
*/
private void startPreferenceActivity() {
Activity from = getParent() != null ? getParent() : this;
//通过检查父活动是否存在来确定从哪个活动中启动偏好设置屏幕。
Intent intent = new Intent(from, NotesPreferenceActivity.class);
//创建一个新的意图Intent对象并将其目标设置为NotesPreferenceActivity类。
from.startActivityIfNeeded(intent, -1);
}
@ -1169,18 +1027,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
/**
* @method startQueryDestinationFolders
* @description
* @param
* *FOLDER_LIST_QUERY_TOKEN
* nullnull
* Notes.CONTENT_NOTE_URIURI
* FoldersListAdapter.PROJECTION
* selection
* new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER), String.valueOf(mCurrentFolderId) }
* NoteColumns.MODIFIED_DATE + " DESC"
*/
private void startQueryDestinationFolders() {
String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?";
selection = (mState == ListEditState.NOTE_LIST) ? selection:
@ -1199,31 +1045,20 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
NoteColumns.MODIFIED_DATE + " DESC");
}
/**
* @method onItemLongClick
* @description
* @return false便
*/
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (view instanceof NotesListItem) {
//通过检查view是否是NotesListItem的实例来确定长按的列表项类型。
mFocusNoteDataItem = ((NotesListItem) view).getItemData();
if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) {
if (mNotesListView.startActionMode(mModeCallBack) != null) {
mModeCallBack.onItemCheckedStateChanged(null, position, id, true);
//调用mModeCallBack.onItemCheckedStateChanged()方法更新选择状态。
mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
//调用mNotesListView.performHapticFeedback()方法进行触觉反馈,表示长按操作已触发。
} else {
Log.e(TAG, "startActionMode fails");
}
} else if (mFocusNoteDataItem.getType() == Notes.TYPE_FOLDER) {
mNotesListView.setOnCreateContextMenuListener(mFolderOnCreateContextMenuListener);
//如果数据项的类型为文件夹类型(Notes.TYPE_FOLDER),则设置列表视图的上下文菜单创建监听器(mFolderOnCreateContextMenuListener)。
}
}
return false;
//返回false表示事件未被消耗以便继续处理其他可能的事件。
}
}

@ -30,110 +30,56 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: NotesListAdapter
* @Description: CursorAdapter
*
* ID
* @Author: xumingyang
* @CreateDate: 2024-01-07 23:46
* @UpdateUser:
* @UpdateDate: 2024-01-07 23:46
* @UpdateRemark:
* @Version: 1.0
*/
public class NotesListAdapter extends CursorAdapter {
private static final String TAG = "NotesListAdapter";
private Context mContext;
private HashMap<Integer, Boolean> mSelectedIndex;
private int mNotesCount;//便签数
private boolean mChoiceMode;//选择模式标记
private int mNotesCount;
private boolean mChoiceMode;
//桌面widget的属性包括编号和类型
public static class AppWidgetAttribute {
public int widgetId;
public int widgetType;
};
/**
* @method NotesListAdapter
* @description 便
*/
public NotesListAdapter(Context context) {
super(context, null);//父类对象置空
mSelectedIndex = new HashMap<Integer, Boolean>();//新建选项下标的hash表
super(context, null);
mSelectedIndex = new HashMap<Integer, Boolean>();
mContext = context;
mNotesCount = 0;
}
/**
* @method newView
* @description
* return
*/
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new NotesListItem(context);
//使用兄弟类NotesListItem新建一个项目选项
}
/**
* @method bindView
* @description
*/
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof NotesListItem) {
//若view是NotesListItem的一个实例
NoteItemData itemData = new NoteItemData(context, cursor);
((NotesListItem) view).bind(context, itemData, mChoiceMode,
isSelectedItem(cursor.getPosition()));
//则新建一个项目选项并且用bind跟将view和鼠标内容便签数据捆绑在一起
}
}
/**
* @method setCheckedItem
* @description
*/
public void setCheckedItem(final int position, final boolean checked) {
mSelectedIndex.put(position, checked);
//根据定位和是否勾选设置下标
notifyDataSetChanged();
//在修改后刷新activity
}
//判断单选按钮是否勾选
public boolean isInChoiceMode() {
return mChoiceMode;
}
/**
* @method setChoiceMode
* @description
*/
public void setChoiceMode(boolean mode) {
mSelectedIndex.clear();
//重置下标并且根据参数mode设置选项
mChoiceMode = mode;
}
/*
*
*
*/
/**
* @method selectAll
* @description
* @param *cursor
*/
public void selectAll(boolean checked) {
Cursor cursor = getCursor();
//获取光标位置
for (int i = 0; i < getCount(); i++) {
if (cursor.moveToPosition(i)) {
if (NoteItemData.getNoteType(cursor) == Notes.TYPE_NOTE) {
@ -141,49 +87,30 @@ public class NotesListAdapter extends CursorAdapter {
}
}
}
//遍历所有光标可用的位置在判断为便签类型之后勾选单项框
}
/**
* @method getSelectedItemIds
* @description
* @param *hashset hash
* @return itemSet
*/
public HashSet<Long> getSelectedItemIds() {
HashSet<Long> itemSet = new HashSet<Long>();
//建立hash表
for (Integer position : mSelectedIndex.keySet()) {
//遍历所有的关键
if (mSelectedIndex.get(position) == true) {
//若光标位置可用
Long id = getItemId(position);
if (id == Notes.ID_ROOT_FOLDER) {
//原文件不需要添加
Log.d(TAG, "Wrong item id, should not happen");
} else {
itemSet.add(id);
}
//则将id该下标假如选项集合中
}
}
return itemSet;
}
/**
* @method getSelectedWidget
* @description Widget
* @param *hashset hash
* @return itemSet Widget
*/
public HashSet<AppWidgetAttribute> getSelectedWidget() {
HashSet<AppWidgetAttribute> itemSet = new HashSet<AppWidgetAttribute>();
for (Integer position : mSelectedIndex.keySet()) {
if (mSelectedIndex.get(position) == true) {
Cursor c = (Cursor) getItem(position);
//以上4句和getSelectedItemIds一样不再重复
if (c != null) {
//光标位置可用的话就建立新的Widget属性并编辑下标和类型最后添加到选项集中
AppWidgetAttribute widget = new AppWidgetAttribute();
NoteItemData item = new NoteItemData(mContext, c);
widget.widgetId = item.getWidgetId();
@ -201,80 +128,57 @@ public class NotesListAdapter extends CursorAdapter {
return itemSet;
}
/**
* @method getSelectedCount
* @description
* @return count
*/
public int getSelectedCount() {
Collection<Boolean> values = mSelectedIndex.values();
//首先获取选项下标的值
if (null == values) {
return 0;
}
Iterator<Boolean> iter = values.iterator();
//初始化叠加器
int count = 0;
while (iter.hasNext()) {
if (true == iter.next()) {
//若value值为真计数+1
count++;
}
}
return count;
}
//函数功能:判断是否全部选中
public boolean isAllSelected() {
int checkedCount = getSelectedCount();
return (checkedCount != 0 && checkedCount == mNotesCount);
//获取选项数看是否等于便签的个数
}
//函数功能:判断是否为选项表
public boolean isSelectedItem(final int position) {
if (null == mSelectedIndex.get(position)) {
return false;
}
return mSelectedIndex.get(position);
}//通过传递的下标来确定
}
@Override
//函数功能在activity内容发生局部变动的时候回调该函数计算便签的数量
protected void onContentChanged() {
super.onContentChanged();
//执行基类函数
calcNotesCount();
}
@Override
//函数功能在activity光标发生局部变动的时候回调该函数计算便签的数量
public void changeCursor(Cursor cursor) {
super.changeCursor(cursor);
//执行基类函数
calcNotesCount();
}
//函数功能:计算便签数量
private void calcNotesCount() {
mNotesCount = 0;
for (int i = 0; i < getCount(); i++) {
//获取总数同时遍历
Cursor c = (Cursor) getItem(i);
if (c != null) {
if (NoteItemData.getNoteType(c) == Notes.TYPE_NOTE) {
mNotesCount++;
//若该位置不为空并且文本类型为便签就+1
}
} else {
Log.e(TAG, "Invalid cursor");
return;
}
//否则报错
}
}
}

@ -1,3 +1,19 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.ui;
import android.content.Context;
@ -14,52 +30,37 @@ import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser.NoteItemBgResources;
//创建便签列表项目选项
public class NotesListItem extends LinearLayout {
private ImageView mAlert;
//闹钟图片
private TextView mTitle;
//标题
private TextView mTime;
//时间
private TextView mCallName;
private NoteItemData mItemData;
//标签数据
private CheckBox mCheckBox;
//打钩框
/*初始化基本信息*/
public NotesListItem(Context context) {
super(context);
//super()它的主要作用是调整调用父类构造函数的顺序
inflate(context, R.layout.note_item, this);
//Inflate可用于将一个xml中定义的布局控件找出来,这里的xml是r。layout
//findViewById用于从contentView中查找指定ID的View转换出来的形式根据需要而定;
mAlert = (ImageView) findViewById(R.id.iv_alert_icon);
mTitle = (TextView) findViewById(R.id.tv_title);
mTime = (TextView) findViewById(R.id.tv_time);
mCallName = (TextView) findViewById(R.id.tv_name);
mCheckBox = (CheckBox) findViewById(android.R.id.checkbox);
}
///根据data的属性对各个控件的属性的控制主要是可见性Visibility内容setText格式setTextAppearance
public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) {
if (choiceMode && data.getType() == Notes.TYPE_NOTE) {
mCheckBox.setVisibility(View.VISIBLE);
//设置可见行为可见
mCheckBox.setChecked(checked);
//格子打钩
} else {
mCheckBox.setVisibility(View.GONE);
}
mItemData = data;
//设置控件属性一共三种情况由data的id和父id是否与保存到文件夹的id一致来决定
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
mCallName.setVisibility(View.GONE);
mAlert.setVisibility(View.VISIBLE);
//设置该textview的style
mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
//settext为设置内容
mTitle.setText(context.getString(R.string.call_record_folder_name)
+ context.getString(R.string.format_folder_files_count, data.getNotesCount()));
mAlert.setImageResource(R.drawable.call_record);
@ -68,9 +69,8 @@ public class NotesListItem extends LinearLayout {
mCallName.setText(data.getCallName());
mTitle.setTextAppearance(context,R.style.TextAppearanceSecondaryItem);
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
//关于闹钟的设置
if (data.hasAlert()) {
mAlert.setImageResource(R.drawable.clock);//图片来源的设置
mAlert.setImageResource(R.drawable.clock);
mAlert.setVisibility(View.VISIBLE);
} else {
mAlert.setVisibility(View.GONE);
@ -78,48 +78,45 @@ public class NotesListItem extends LinearLayout {
} else {
mCallName.setVisibility(View.GONE);
mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
//设置title格式
if (data.getType() == Notes.TYPE_FOLDER) {
mTitle.setText(data.getSnippet()
+ context.getString(R.string.format_folder_files_count,
data.getNotesCount()));
data.getNotesCount()));
mAlert.setVisibility(View.GONE);
} else {
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
if (data.hasAlert()) {
mAlert.setImageResource(R.drawable.clock);///设置图片来源
mAlert.setImageResource(R.drawable.clock);
mAlert.setVisibility(View.VISIBLE);
} else {
mAlert.setVisibility(View.GONE);
}
}
}
//设置内容获取相关时间从data里编辑的日期中获取
mTime. setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate()));
mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate()));
setBackground(data);
}
//根据data的文件属性来设置背景
private void setBackground(NoteItemData data) {
int id = data.getBgColorId();
//若是note型文件则4种情况对于4种不同情况的背景来源
if (data.getType() == Notes.TYPE_NOTE) {
//单个数据并且只有一个子文件夹
if (data.isSingle() || data.isOneFollowingFolder()) {
setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id));
} else if (data.isLast()) {//是最后一个数据
} else if (data.isLast()) {
setBackgroundResource(NoteItemBgResources.getNoteBgLastRes(id));
} else if (data.isFirst() || data.isMultiFollowingFolder()) {//是一个数据并有多个子文件夹
} else if (data.isFirst() || data.isMultiFollowingFolder()) {
setBackgroundResource(NoteItemBgResources.getNoteBgFirstRes(id));
} else {
setBackgroundResource(NoteItemBgResources.getNoteBgNormalRes(id));
}
} else {
//若不是note直接调用文件夹的背景来源
setBackgroundResource(NoteItemBgResources.getFolderBgRes());
}
}
public NoteItemData getItemData() {
return mItemData;
}
}
}

@ -47,102 +47,66 @@ import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.remote.GTaskSyncService;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: NotesPreferenceActivity
* @Description: /
*
* NotesPreferenceActivity便
* PreferenceActivityActivity
* @Author: xumingyang
* @CreateDate: 2024-01-08 18:03
* @UpdateUser:
* @UpdateDate: 2024-01-08 18:03
* @UpdateRemark:
* @Version: 1.0
*/
public class NotesPreferenceActivity extends PreferenceActivity {
public static final String PREFERENCE_NAME = "notes_preferences";
//优先名
public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name";
//同步账号
public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time";
//同步时间
public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear";
private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key";
//同步密码
private static final String AUTHORITIES_FILTER_KEY = "authorities";
//本地密码
private PreferenceCategory mAccountCategory;
//账户分组
private GTaskReceiver mReceiver;
//同步任务接收器
private Account[] mOriAccounts;
//账户
private boolean mHasAddedAccount;
//账户的hash标记
private boolean mHasAddedAccount;
/**
* @method onCreate
* @description activity
* @param *Bundle icicle activity
*/
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
//先执行父类的创建函数
/* using the app icon for navigation */
getActionBar().setDisplayHomeAsUpEnabled(true);
//给左上角图标的左边加上一个返回的图标
addPreferencesFromResource(R.xml.preferences);
//添加xml来源并显示 xml
mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);
//根据同步账户关键码来初始化分组
mReceiver = new GTaskReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME);
registerReceiver(mReceiver, filter);
//初始化同步组件
mOriAccounts = null;
View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);
//获取listvivewListView的作用:用于列出所有选择
getListView().addHeaderView(header, null, true);
//在listview组件上方添加其他组件
}
/**
* @method onResume
* @description activity
*/
@Override
protected void onResume() {
//先执行父类 的交互实现
super.onResume();
// need to set sync account automatically if user has added a new
// account
if (mHasAddedAccount) {
//若用户新加了账户则自动设置同步账户
Account[] accounts = getGoogleAccounts();
//获取google同步账户
if (mOriAccounts != null && accounts.length > mOriAccounts.length) {
//若原账户不为空且当前账户有增加
for (Account accountNew : accounts) {
boolean found = false;
for (Account accountOld : mOriAccounts) {
if (TextUtils.equals(accountOld.name, accountNew.name)) {
//更新账户
found = true;
break;
}
}
if (!found) {
setSyncAccount(accountNew.name);
//若是没有找到旧的账户,那么同步账号中就只添加新账户
break;
}
}
@ -150,82 +114,58 @@ public class NotesPreferenceActivity extends PreferenceActivity {
}
refreshUI();
//刷新标签界面
}
/**
* @method onDestroy
* @description activity
*/
@Override
protected void onDestroy() {
if (mReceiver != null) {
unregisterReceiver(mReceiver);
//注销接收器
}
super.onDestroy();
//执行父类的销毁动作
}
/**
* @method loadAccountPreference
* @description
*/
private void loadAccountPreference() {
mAccountCategory.removeAll();
//销毁所有的分组
Preference accountPref = new Preference(this);
//建立首选项
final String defaultAccount = getSyncAccountName(this);
accountPref.setTitle(getString(R.string.preferences_account_title));
accountPref.setSummary(getString(R.string.preferences_account_summary));
//设置首选项的大标题和小标题
accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
//建立监听器
if (!GTaskSyncService.isSyncing()) {
if (TextUtils.isEmpty(defaultAccount)) {
// the first time to set account
//若是第一次建立账户显示选择账户提示对话框
showSelectAccountAlertDialog();
} else {
// if the account has already been set, we need to promp
// user about the risk
//若是已经建立则显示修改对话框并进行修改操作
showChangeAccountConfirmAlertDialog();
}
} else {
//若在没有同步的情况下则在toast中显示不能修改
Toast.makeText(NotesPreferenceActivity.this,
R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT)
R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT)
.show();
}
return true;
}
});
//根据新建首选项编辑新的账户分组
mAccountCategory.addPreference(accountPref);
}
/**
* @method loadSyncButton
* @description
*/
private void loadSyncButton() {
Button syncButton = (Button) findViewById(R.id.preference_sync_button);
TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
//获取同步按钮控件和最终同步时间的的窗口
// set button state
//设置按钮的状态
if (GTaskSyncService.isSyncing()) {
//若是在同步状态下
syncButton.setText(getString(R.string.preferences_button_sync_cancel));
syncButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
GTaskSyncService.cancelSync(NotesPreferenceActivity.this);
}
});
//设置按钮显示的文本为“取消同步”以及监听器
} else {
syncButton.setText(getString(R.string.preferences_button_sync_immediately));
syncButton.setOnClickListener(new View.OnClickListener() {
@ -233,69 +173,50 @@ public class NotesPreferenceActivity extends PreferenceActivity {
GTaskSyncService.startSync(NotesPreferenceActivity.this);
}
});
//若是不同步则设置按钮显示的文本为“立即同步”以及对应监听器
}
syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this)));
//设置按键可用还是不可用
// set last sync time
// 设置最终同步时间
if (GTaskSyncService.isSyncing()) {
//若是在同步的情况下
lastSyncTimeView.setText(GTaskSyncService.getProgressString());
lastSyncTimeView.setVisibility(View.VISIBLE);
// 根据当前同步服务器设置时间显示框的文本以及可见性
} else {
//若是非同步情况
long lastSyncTime = getLastSyncTime(this);
if (lastSyncTime != 0) {
lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time,
DateFormat.format(getString(R.string.preferences_last_sync_time_format),
lastSyncTime)));
lastSyncTimeView.setVisibility(View.VISIBLE);
//则根据最后同步时间的信息来编辑时间显示框的文本内容和可见性
} else {
//若时间为空直接设置为不可见状态
lastSyncTimeView.setVisibility(View.GONE);
}
}
}
/**
* @method refreshUI
* @description
*/
private void refreshUI() {
loadAccountPreference();
loadSyncButton();
//调用上文设置账号和设置按键两个函数来实现
}
/**
* @method showSelectAccountAlertDialog
* @description
*/
private void showSelectAccountAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
//创建一个新的对话框
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(getString(R.string.preferences_dialog_select_account_title));
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));
//设置标题以及子标题的内容
dialogBuilder.setCustomTitle(titleView);
dialogBuilder.setPositiveButton(null, null);
//设置对话框的自定义标题建立一个YES的按钮
Account[] accounts = getGoogleAccounts();
String defAccount = getSyncAccountName(this);
//获取同步账户信息
mOriAccounts = accounts;
mHasAddedAccount = false;
if (accounts.length > 0) {
//若账户不为空
CharSequence[] items = new CharSequence[accounts.length];
final CharSequence[] itemMapping = items;
int checkedItem = -1;
@ -303,119 +224,83 @@ public class NotesPreferenceActivity extends PreferenceActivity {
for (Account account : accounts) {
if (TextUtils.equals(account.name, defAccount)) {
checkedItem = index;
//在账户列表中查询到所需账户
}
items[index++] = account.name;
}
dialogBuilder.setSingleChoiceItems(items, checkedItem,
//在对话框建立一个单选的复选框
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
setSyncAccount(itemMapping[which].toString());
dialog.dismiss();
//取消对话框
refreshUI();
}
//设置点击后执行的事件,包括检录新同步账户和刷新标签界面
});
//建立对话框网络版的监听器
}
View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null);
dialogBuilder.setView(addAccountView);
//给新加账户对话框设置自定义样式
final AlertDialog dialog = dialogBuilder.show();
//显示对话框
addAccountView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mHasAddedAccount = true;
//将新加账户的hash置true
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
//建立网络建立组件
intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {
"gmail-ls"
"gmail-ls"
});
startActivityForResult(intent, -1);
//跳回上一个选项
dialog.dismiss();
}
});
//建立新加账户对话框的监听器
}
/**
* @method showChangeAccountConfirmAlertDialog
* @description
*/
private void showChangeAccountConfirmAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
//创建一个新的对话框
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(getString(R.string.preferences_dialog_change_account_title,
getSyncAccountName(this)));
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg));
//根据同步修改的账户信息设置标题以及子标题的内容
dialogBuilder.setCustomTitle(titleView);
//设置对话框的自定义标题
CharSequence[] menuItemArray = new CharSequence[] {
getString(R.string.preferences_menu_change_account),
getString(R.string.preferences_menu_remove_account),
getString(R.string.preferences_menu_cancel)
};
//定义一些标记字符串
dialogBuilder.setItems(menuItemArray, new DialogInterface.OnClickListener() {
//设置对话框要显示的一个list用于显示几个命令时,即changeremovecancel
public void onClick(DialogInterface dialog, int which) {
//按键功能由which来决定
if (which == 0) {
//进入账户选择对话框
showSelectAccountAlertDialog();
} else if (which == 1) {
//删除账户并且跟新便签界面
removeSyncAccount();
refreshUI();
}
}
});
dialogBuilder.show();
//显示对话框
}
/**
* @method getGoogleAccounts
* @description
*/
private Account[] getGoogleAccounts() {
AccountManager accountManager = AccountManager.get(this);
return accountManager.getAccountsByType("com.google");
//通过账户管理器直接获取
}
/**
* @method setSyncAccount
* @description
*/
private void setSyncAccount(String account) {
if (!getSyncAccountName(this).equals(account)) {
//假如该账号不在同步账号列表中
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
//编辑共享的首选项
if (account != null) {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account);
} else {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
//将该账号加入到首选项中
editor.commit();
//提交修改的数据
// clean up last sync time
setLastSyncTime(this, 0);
//将最后同步时间清零
// clean up local gtask related info
new Thread(new Runnable() {
@ -426,116 +311,76 @@ public class NotesPreferenceActivity extends PreferenceActivity {
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
//重置当地同步任务的信息
Toast.makeText(NotesPreferenceActivity.this,
getString(R.string.preferences_toast_success_set_accout, account),
Toast.LENGTH_SHORT).show();
//将toast的文本信息置为“设置账户成功”并显示出来
}
}
/**
* @method removeSyncAccount
* @description
*/
private void removeSyncAccount() {
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
//设置共享首选项
if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) {
editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);
//假如当前首选项中有账户就删除
}
if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) {
editor.remove(PREFERENCE_LAST_SYNC_TIME);
//删除当前首选项中有账户时间
}
editor.commit();
//提交更新后的数据
// clean up local gtask related info
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, "");
values.put(NoteColumns.SYNC_ID, 0);
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
//重置当地同步任务的信息
}
/**
* @method getSyncAccountName
* @description
*/
private void removeSyncAccount() {
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) {
editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);
}
if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) {
editor.remove(PREFERENCE_LAST_SYNC_TIME);
}
editor.commit();
// clean up local gtask related info
new Thread(new Runnable() {
public void run() {
ContentValues values = new ContentValues();
values.put(NoteColumns.GTASK_ID, "");
values.put(NoteColumns.SYNC_ID, 0);
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
}
}).start();
}
public static String getSyncAccountName(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
//通过共享的首选项里的信息直接获取
return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
}
/**
* @method setLastSyncTime
* @description
*/
public static void setLastSyncTime(Context context, long time) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
// 从共享首选项中找到相关账户并获取其编辑器
editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
editor.commit();
//编辑最终同步时间并提交更新
}
/**
* @method getLastSyncTime
* @description
*/
public static long getLastSyncTime(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE);
//通过共享的首选项里的信息直接获取
return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
}
/**
* @method
* @description
*/
private class GTaskReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
refreshUI();
if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) {
//获取随广播而来的Intent中的同步服务的数据
TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
syncStatus.setText(intent
.getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));
//通过获取的数据在设置系统的状态
}
}
}
/**
* @method onOptionsItemSelected
* @description
* @param *MenuItem
*/
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
//根据选项的id选择这里只有一个主页
case android.R.id.home:
Intent intent = new Intent(this, NotesListActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
//在主页情况下在创建连接组件intent发出清空的信号并开始一个相应的activity
default:
return false;
}

@ -0,0 +1,36 @@
package net.micode.notes.ui;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
import net.micode.notes.databinding.ActivitySplashBinding;
import net.micode.notes.R;
public class SplashActivity extends AppCompatActivity {
Handler mHandler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //加载启动界面
setContentView(R.layout.activity_splash); //加载启动图片
// 当计时结束时跳转至NotesListActivity
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent=new Intent();
intent.setClass(SplashActivity.this, LoginActivity.class);
startActivity(intent);
finish(); //销毁欢迎页面
}
}, 2000); // 2 秒后跳转
}
}
Loading…
Cancel
Save