diff --git a/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java b/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java index f221202..1bad7e3 100644 --- a/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java +++ b/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java @@ -31,8 +31,8 @@ import net.micode.notes.data.Notes.NoteColumns; public class AlarmInitReceiver extends BroadcastReceiver { private static final String [] PROJECTION = new String [] { - NoteColumns.ID, - NoteColumns.ALERTED_DATE + NoteColumns.ID, + NoteColumns.ALERTED_DATE }; private static final int COLUMN_ID = 0; diff --git a/app/src/main/java/net/micode/notes/ui/DateTimePicker.java b/app/src/main/java/net/micode/notes/ui/DateTimePicker.java index 496b0cd..bb13d8e 100644 --- a/app/src/main/java/net/micode/notes/ui/DateTimePicker.java +++ b/app/src/main/java/net/micode/notes/ui/DateTimePicker.java @@ -160,7 +160,7 @@ public class DateTimePicker extends FrameLayout { public interface OnDateTimeChangedListener { void onDateTimeChanged(DateTimePicker view, int year, int month, - int dayOfMonth, int hourOfDay, int minute); + int dayOfMonth, int hourOfDay, int minute); } public DateTimePicker(Context context) { @@ -263,7 +263,7 @@ public class DateTimePicker extends FrameLayout { * @param minute The current minute */ public void setCurrentDate(int year, int month, - int dayOfMonth, int hourOfDay, int minute) { + int dayOfMonth, int hourOfDay, int minute) { setCurrentYear(year); setCurrentMonth(month); setCurrentDay(dayOfMonth); diff --git a/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java b/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java index 2c47ba4..6209488 100644 --- a/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java +++ b/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java @@ -46,7 +46,7 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener setView(mDateTimePicker); mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() { public void onDateTimeChanged(DateTimePicker view, int year, int month, - int dayOfMonth, int hourOfDay, int minute) { + int dayOfMonth, int hourOfDay, int minute) { mDate.set(Calendar.YEAR, year); mDate.set(Calendar.MONTH, month); mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); @@ -74,9 +74,9 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener private void updateTitle(long date) { int flag = - DateUtils.FORMAT_SHOW_YEAR | - DateUtils.FORMAT_SHOW_DATE | - DateUtils.FORMAT_SHOW_TIME; + DateUtils.FORMAT_SHOW_YEAR | + DateUtils.FORMAT_SHOW_DATE | + DateUtils.FORMAT_SHOW_TIME; flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR; setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); } diff --git a/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java b/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java index 96b77da..1ea0fc8 100644 --- a/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java +++ b/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java @@ -31,8 +31,8 @@ import net.micode.notes.data.Notes.NoteColumns; public class FoldersListAdapter extends CursorAdapter { public static final String [] PROJECTION = { - NoteColumns.ID, - NoteColumns.SNIPPET + NoteColumns.ID, + NoteColumns.SNIPPET }; public static final int ID_COLUMN = 0; diff --git a/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java index 702ca39..0237f9d 100644 --- a/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java +++ b/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java @@ -27,18 +27,14 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Paint; import android.os.Bundle; import android.preference.PreferenceManager; -import android.text.Editable; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.style.BackgroundColorSpan; -import android.text.style.ImageSpan; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -56,6 +52,8 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import androidx.appcompat.app.AppCompatActivity; + import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.TextNote; @@ -76,7 +74,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class NoteEditActivity extends Activity implements OnClickListener, +public class NoteEditActivity extends AppCompatActivity implements OnClickListener, NoteSettingChangedListener, OnTextViewChangeListener { private class HeadViewHolder { public TextView tvModified; @@ -86,6 +84,10 @@ public class NoteEditActivity extends Activity implements OnClickListener, public TextView tvAlertDate; public ImageView ibSetBgColor; + + public ImageView ivLocked; + + public ImageView ivUnlocked; } private static final Map sBgSelectorBtnsMap = new HashMap(); @@ -153,8 +155,6 @@ public class NoteEditActivity extends Activity implements OnClickListener, private String mUserQuery; private Pattern mPattern; - private static final int PHOTO_REQUEST = 2;// 从相册中选择 - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -317,6 +317,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteHeaderHolder.tvAlertDate.setVisibility(View.GONE); mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE); }; + if(mWorkingNote.getIsLocked()){ + mNoteHeaderHolder.ivUnlocked.setVisibility(View.GONE); + mNoteHeaderHolder.ivLocked.setVisibility(View.VISIBLE); + }else{ + mNoteHeaderHolder.ivUnlocked.setVisibility(View.VISIBLE); + mNoteHeaderHolder.ivLocked.setVisibility(View.GONE); + } + } @Override @@ -365,8 +373,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, || ev.getX() > (x + view.getWidth()) || ev.getY() < y || ev.getY() > (y + view.getHeight())) { - return false; - } + return false; + } return true; } @@ -378,6 +386,10 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date); mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color); mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this); + + mNoteHeaderHolder.ivLocked = (ImageView) findViewById(R.id.tv_locked); + mNoteHeaderHolder.ivUnlocked = (ImageView) findViewById(R.id.tv_unlocked); + mNoteEditor = (EditText) findViewById(R.id.note_edit_view); mNoteEditorPanel = findViewById(R.id.sv_note_edit); mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector); @@ -425,7 +437,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { - mWorkingNote.getWidgetId() + mWorkingNote.getWidgetId() }); sendBroadcast(intent); @@ -459,6 +471,20 @@ public class NoteEditActivity extends Activity implements OnClickListener, } } + public void onChangeLock(View v){ + int id = v.getId(); + switch (id){ + case R.id.tv_locked: + mWorkingNote.setLock(false); + break; + case R.id.tv_unlocked: + + mWorkingNote.setLock(true); + break; + } + showAlertHeader(); + } + @Override public void onBackPressed() { if(clearSettingState()) { @@ -487,8 +513,34 @@ public class NoteEditActivity extends Activity implements OnClickListener, mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId()); } +// @Override +// public boolean onCreateOptionsMenu(Menu menu){ +// if (isFinishing()) { +// return true; +// } +// clearSettingState(); +// menu.clear(); +// if (mWorkingNote.getFolderId() == Notes.ID_CALL_RECORD_FOLDER) { +// getMenuInflater().inflate(R.menu.call_note_edit, menu); +// } else { +// getMenuInflater().inflate(R.menu.note_edit, menu); +// } +// if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { +// menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_normal_mode); +// } else { +// menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_list_mode); +// } +// if (mWorkingNote.hasClockAlert()) { +// menu.findItem(R.id.menu_alert).setVisible(false); +// } else { +// menu.findItem(R.id.menu_delete_remind).setVisible(false); +// } +// return true; +// } + @Override public boolean onPrepareOptionsMenu(Menu menu) { +// getMenuInflater().inflate(R.menu.call_note_edit, menu); if (isFinishing()) { return true; } @@ -512,7 +564,6 @@ public class NoteEditActivity extends Activity implements OnClickListener, return true; } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -595,6 +646,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } private void deleteCurrentNote() { + saveNote(); if (mWorkingNote.existInDatabase()) { HashSet ids = new HashSet(); long id = mWorkingNote.getNoteId(); @@ -604,9 +656,9 @@ public class NoteEditActivity extends Activity implements OnClickListener, Log.d(TAG, "Wrong note id, should not happen"); } if (!isSyncMode()) { - if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) { - Log.e(TAG, "Delete Note error"); - } +// if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) { +// Log.e(TAG, "Delete Note error"); +// } } else { if (!DataUtils.batchMoveToFolder(getContentResolver(), ids, Notes.ID_TRASH_FOLER)) { Log.e(TAG, "Move notes to trash folder error, should not happens"); @@ -617,7 +669,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, } private boolean isSyncMode() { - return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0; + return true; } public void onClockAlertChanged(long date, boolean set) { @@ -880,47 +932,4 @@ public class NoteEditActivity extends Activity implements OnClickListener, } - //路径字符串格式 转换为 图片image格式 - private void convertToImage() { - NoteEditText noteEditText = (NoteEditText) findViewById(R.id.note_edit_view); //获取当前的edit - Editable editable = noteEditText.getText();//1.获取text - String noteText = editable.toString(); //2.将note内容转换为字符串 - int length = editable.length(); //内容的长度 - //3.截取img片段 [local]+uri+[local],提取uri - for(int i = 0; i < length; i++) { - for(int j = i; j < length; j++) { - String img_fragment = noteText.substring(i, j+1); //img_fragment:关于图片路径的片段 - if(img_fragment.length() > 15 && img_fragment.endsWith("[/local]") && img_fragment.startsWith("[local]")){ - int limit = 7; //[local]为7个字符 - //[local][/local]共15个字符,剩下的为真正的path长度 - int len = img_fragment.length()-15; - //从[local]之后的len个字符就是path - String path = img_fragment.substring(limit,limit+len);//获取到了图片路径 - Bitmap bitmap = null; - Log.d(TAG, "图片的路径是:"+path); - try { - bitmap = BitmapFactory.decodeFile(path);//将图片路径解码为图片格式 - } catch (Exception e) { - e.printStackTrace(); - } - if(bitmap!=null){ //若图片存在 - Log.d(TAG, "图片不为null"); - ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap); - //4.创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像 - String ss = "[local]" + path + "[/local]"; - SpannableString spannableString = new SpannableString(ss); - //5.将指定的标记对象附加到文本的开始...结束范围 - spannableString.setSpan(imageSpan, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - Log.d(TAG, "Create spannable string success!"); - Editable edit_text = noteEditText.getEditableText(); - edit_text.delete(i,i+len+15); //6.删掉图片路径的文字 - edit_text.insert(i, spannableString); //7.在路径的起始位置插入图片 - } - } - } - } - } - - - } diff --git a/app/src/main/java/net/micode/notes/ui/NoteItemData.java b/app/src/main/java/net/micode/notes/ui/NoteItemData.java index 0f5a878..531bb34 100644 --- a/app/src/main/java/net/micode/notes/ui/NoteItemData.java +++ b/app/src/main/java/net/micode/notes/ui/NoteItemData.java @@ -28,18 +28,19 @@ import net.micode.notes.tool.DataUtils; public class NoteItemData { static final String [] PROJECTION = new String [] { - 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, - NoteColumns.TYPE, - NoteColumns.WIDGET_ID, - NoteColumns.WIDGET_TYPE, + 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, + NoteColumns.TYPE, + NoteColumns.WIDGET_ID, + NoteColumns.WIDGET_TYPE, + NoteColumns.LOCKED }; private static final int ID_COLUMN = 0; @@ -54,6 +55,10 @@ public class NoteItemData { private static final int TYPE_COLUMN = 9; private static final int WIDGET_ID_COLUMN = 10; private static final int WIDGET_TYPE_COLUMN = 11; + private static final int LOCKED_COLUMN = 12; + + private static final String LOCKED = "locked"; + private static final String UNLOCKED = "unlocked"; private long mId; private long mAlertDate; @@ -76,6 +81,8 @@ public class NoteItemData { private boolean mIsOneNoteFollowingFolder; private boolean mIsMultiNotesFollowingFolder; + private boolean mIsLocked; + public NoteItemData(Context context, Cursor cursor) { mId = cursor.getLong(ID_COLUMN); mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN); @@ -92,6 +99,8 @@ public class NoteItemData { mWidgetId = cursor.getInt(WIDGET_ID_COLUMN); mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN); + mIsLocked = !cursor.getString(LOCKED_COLUMN).equals(UNLOCKED); + mPhoneNumber = ""; if (mParentId == Notes.ID_CALL_RECORD_FOLDER) { mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId); @@ -221,4 +230,11 @@ public class NoteItemData { public static int getNoteType(Cursor cursor) { return cursor.getInt(TYPE_COLUMN); } + + public boolean getIsLocked(){ + return mIsLocked; + } + public void setIsLocked(boolean islocked){ + mIsLocked = islocked; + } } diff --git a/app/src/main/java/net/micode/notes/ui/NotesListActivity.java b/app/src/main/java/net/micode/notes/ui/NotesListActivity.java index eda2134..cb7246e 100644 --- a/app/src/main/java/net/micode/notes/ui/NotesListActivity.java +++ b/app/src/main/java/net/micode/notes/ui/NotesListActivity.java @@ -16,9 +16,11 @@ package net.micode.notes.ui; +import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; +import android.app.KeyguardManager; import android.appwidget.AppWidgetManager; import android.content.AsyncQueryHandler; import android.content.ContentResolver; @@ -28,10 +30,13 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; +import android.hardware.fingerprint.FingerprintManager; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; -import androidx.appcompat.app.AppCompatActivity; +import android.security.keystore.KeyGenParameterSpec; +import android.security.keystore.KeyProperties; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; @@ -61,6 +66,8 @@ import android.widget.PopupMenu; import android.widget.TextView; import android.widget.Toast; +import androidx.appcompat.app.AppCompatActivity; + import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; @@ -68,6 +75,7 @@ import net.micode.notes.gtask.remote.GTaskSyncService; import net.micode.notes.model.WorkingNote; import net.micode.notes.tool.BackupUtils; import net.micode.notes.tool.DataUtils; +import net.micode.notes.tool.FingerprintDialogFragment; import net.micode.notes.tool.ResourceParser; import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; import net.micode.notes.widget.NoteWidgetProvider_2x; @@ -77,8 +85,13 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.security.KeyStore; import java.util.HashSet; +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + public class NotesListActivity extends AppCompatActivity implements OnClickListener, OnItemLongClickListener { private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0; @@ -90,11 +103,13 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe private static final int MENU_FOLDER_CHANGE_NAME = 2; + private static final int MENU_FOLDER_MOVE_OUT = 3; + private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction"; private enum ListEditState { NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER - } + }; private ListEditState mState; @@ -136,11 +151,25 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe private final static int REQUEST_CODE_OPEN_NODE = 102; private final static int REQUEST_CODE_NEW_NODE = 103; + private static final String DEFAULT_KEY_NAME = "default_key"; + private static final int OPEN_NOTE = 0; + private static final int DELETE_NOTE = 1; + private static final int MOVE_NOTE = 2; + private static final int NONE_ACTION = -1; + KeyStore keyStore; + private NoteItemData mNoteDataItem; + private int mAuthenticatedType; + private long mAuthenticated_FOLDER; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.note_list); initResources(); + if (supportFingerprint()) { + initKey(); + } + /** * Insert an introduction when user firstly use this application @@ -161,46 +190,56 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe private void setAppInfoFromRawRes() { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) { - StringBuilder sb = new StringBuilder(); - InputStream in = null; - try { - in = getResources().openRawResource(R.raw.introduction); - if (in != null) { - InputStreamReader isr = new InputStreamReader(in); - BufferedReader br = new BufferedReader(isr); - char [] buf = new char[1024]; - int len = 0; - while ((len = br.read(buf)) > 0) { - sb.append(buf, 0, len); - } - } else { - Log.e(TAG, "Read introduction file error"); - return; - } - } catch (IOException e) { - e.printStackTrace(); - return; - } finally { - if(in != null) { - try { - in.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - 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()) { - sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit(); - } else { - Log.e(TAG, "Save introduction note error"); + if(!DataUtils.checkFolderId(mContentResolver,Long.valueOf(Notes.ID_TRASH_FOLER)) && !DataUtils.checkVisibleFolderName(mContentResolver,this.getString(R.string.trash_name))){ + ContentValues values = new ContentValues(); + values.put(NoteColumns.SNIPPET, this.getString(R.string.trash_name)); + values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); +// values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); + mContentResolver.insert(Notes.CONTENT_NOTE_URI, values); } +// StringBuilder sb = new StringBuilder(); +// InputStream in = null; +// try { +// in = getResources().openRawResource(R.raw.introduction); +// if (in != null) { +// InputStreamReader isr = new InputStreamReader(in); +// BufferedReader br = new BufferedReader(isr); +// char [] buf = new char[1024]; +// int len = 0; +// while ((len = br.read(buf)) > 0) { +// sb.append(buf, 0, len); +// } +// } else { +// Log.e(TAG, "Read introduction file error"); +// return; +// } +// } catch (IOException e) { +// e.printStackTrace(); +// return; +// } finally { +// if(in != null) { +// try { +// in.close(); +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } +// } +// +// 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()) { +// sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit(); +// } else { +// Log.e(TAG, "Save introduction note error"); +// return; +// } } + long id = DataUtils.getTrashIdByName(mContentResolver,this.getString(R.string.trash_name)); + Notes.setID_TRASH_FOLER((int)id); } @Override @@ -307,7 +346,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe } public void onItemCheckedStateChanged(ActionMode mode, int position, long id, - boolean checked) { + boolean checked) { mNotesListAdapter.setCheckedItem(position, checked); updateMenu(); } @@ -325,14 +364,14 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe builder.setTitle(getString(R.string.alert_title_delete)); builder.setIcon(android.R.drawable.ic_dialog_alert); builder.setMessage(getString(R.string.alert_message_delete_notes, - mNotesListAdapter.getSelectedCount())); + mNotesListAdapter.getSelectedCount())); builder.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - batchDelete(); - } - }); + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + batchDelete(); + } + }); builder.setNegativeButton(android.R.string.cancel, null); builder.show(); break; @@ -413,7 +452,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe : NORMAL_SELECTION; mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null, Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] { - String.valueOf(mCurrentFolderId) + String.valueOf(mCurrentFolderId) }, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC"); } @@ -441,6 +480,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe } } + private void showFolderListMenu(Cursor cursor) { AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); builder.setTitle(R.string.menu_title_select_folder); @@ -448,14 +488,27 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe 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(); + if(adapter.getItemId(which)==Notes.ID_TRASH_FOLER){ + Toast.makeText( + NotesListActivity.this, + R.string.forbidden_move_to_trash, + Toast.LENGTH_SHORT).show(); + }else{ + if(mNotesListAdapter.getHasLocked() && false){ + //not ready + initCipher(); + mAuthenticatedType = MOVE_NOTE; + }else { + 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(); } }); @@ -469,11 +522,12 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE); } - private void batchDelete() { + private void reallyBatchDelete(){ new AsyncTask>() { protected HashSet doInBackground(Void... unused) { HashSet widgets = mNotesListAdapter.getSelectedWidget(); - if (!isSyncMode()) { + HashSet folers = mNotesListAdapter.getSelectedFolderIds(); + if (folers.contains(new Long( Notes.ID_TRASH_FOLER))) { // if not synced, delete notes directly if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter .getSelectedItemIds())) { @@ -506,17 +560,22 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe }.execute(); } - private void deleteFolder(long folderId) { - if (folderId == Notes.ID_ROOT_FOLDER) { - Log.e(TAG, "Wrong folder id, should not happen " + folderId); - return; + private void batchDelete() { + if(ifHaveLocked()){ + initCipher(); + mAuthenticatedType = DELETE_NOTE; + }else { + reallyBatchDelete(); } + } + private void reallyDeleteFolder(long folderId){ HashSet ids = new HashSet(); + ids.add(folderId); HashSet widgets = DataUtils.getFolderNoteWidget(mContentResolver, folderId); - if (!isSyncMode()) { + if (DataUtils.getParentIdbyId(mContentResolver,folderId)==Notes.ID_TRASH_FOLER) { // if not synced, delete folder directly DataUtils.batchDeleteNotes(mContentResolver, ids); } else { @@ -533,34 +592,129 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe } } + + private void deleteFolder(long folderId) { + if (folderId == Notes.ID_ROOT_FOLDER) { + Log.e(TAG, "Wrong folder id, should not happen " + folderId); + return; + } + if(folderId == Notes.ID_TRASH_FOLER){ + Toast.makeText( + NotesListActivity.this, + R.string.forbidden_delete_trash, + Toast.LENGTH_SHORT).show(); + return; + } + + if(DataUtils.getHasLockedByFolderId(mContentResolver,folderId).contains(Notes.LOCKED)){ + initCipher(); + mAuthenticatedType = MOVE_NOTE; + mAuthenticated_FOLDER = folderId; + }else { + reallyDeleteFolder(folderId); + } + } + + private boolean ifHaveLocked(){ + return mNotesListAdapter.getHasLocked(); + } + + private void openNode(NoteItemData data) { - Intent intent = new Intent(this, NoteEditActivity.class); - intent.setAction(Intent.ACTION_VIEW); - intent.putExtra(Intent.EXTRA_UID, data.getId()); - this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE); + if(!data.getIsLocked()){ + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(Intent.EXTRA_UID, data.getId()); + this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE); + }else{ + this.openLockedNote(); + mNoteDataItem = data; + mAuthenticatedType = OPEN_NOTE; + } } - private void openFolder(NoteItemData data) { - mCurrentFolderId = data.getId(); - startAsyncNotesListQuery(); - if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { - mState = ListEditState.CALL_RECORD_FOLDER; - mAddNewNote.setVisibility(View.GONE); - } else { - mState = ListEditState.SUB_FOLDER; + private void openLockedNote(){ + initCipher(); + } + + public void onAuthenticated() { + switch (mAuthenticatedType){ + case OPEN_NOTE: + switch (mNoteDataItem.getType()){ + case Notes.TYPE_FOLDER: + mCurrentFolderId = mNoteDataItem.getId(); + startAsyncNotesListQuery(); + if (mNoteDataItem.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mState = ListEditState.CALL_RECORD_FOLDER; + mAddNewNote.setVisibility(View.GONE); + } else { + mState = ListEditState.SUB_FOLDER; + } + if (mNoteDataItem.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mTitleBar.setText(R.string.call_record_folder_name); + } else { + mTitleBar.setText(mNoteDataItem.getSnippet()); + } + mTitleBar.setVisibility(View.VISIBLE); + break; + case Notes.TYPE_NOTE: + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(Intent.EXTRA_UID, mNoteDataItem.getId()); + this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE); + break; + } + break; + case DELETE_NOTE: + reallyBatchDelete(); + break; + case MOVE_NOTE: + reallyDeleteFolder(mAuthenticated_FOLDER); + break; } - if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { - mTitleBar.setText(R.string.call_record_folder_name); - } else { - mTitleBar.setText(data.getSnippet()); + mNoteDataItem = null; + mAuthenticated_FOLDER = -1; + mAuthenticatedType = NONE_ACTION; + } + + public void onStopAuthenticated() { + mNoteDataItem = null; + } + + private void openFolder(NoteItemData data) { + if(!data.getIsLocked()){ + mCurrentFolderId = data.getId(); + startAsyncNotesListQuery(); + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mState = ListEditState.CALL_RECORD_FOLDER; + mAddNewNote.setVisibility(View.GONE); + } else { + mState = ListEditState.SUB_FOLDER; + } + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mTitleBar.setText(R.string.call_record_folder_name); + } else { + mTitleBar.setText(data.getSnippet()); + } + mTitleBar.setVisibility(View.VISIBLE); + }else{ + this.openLockedNote(); + mNoteDataItem = data; + mAuthenticatedType = OPEN_NOTE; } - mTitleBar.setVisibility(View.VISIBLE); } public void onClick(View v) { switch (v.getId()) { case R.id.btn_new_note: - createNewNote(); + if(mCurrentFolderId==Notes.ID_TRASH_FOLER){ + Toast.makeText( + NotesListActivity.this, + R.string.forbidden_add_in_trash, + Toast.LENGTH_SHORT).show(); + }else { + createNewNote(); + } break; default: break; @@ -586,8 +740,13 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe showSoftInput(); if (!create) { if (mFocusNoteDataItem != null) { - etName.setText(mFocusNoteDataItem.getSnippet()); - builder.setTitle(getString(R.string.menu_folder_change_name)); + if(mFocusNoteDataItem.getId()==(long)Notes.ID_TRASH_FOLER){ + Toast.makeText(this, R.string.forbidden_change_trash_name, Toast.LENGTH_SHORT).show(); + return; + }else{ + etName.setText(mFocusNoteDataItem.getSnippet()); + builder.setTitle(getString(R.string.menu_folder_change_name)); + } } else { Log.e(TAG, "The long click data item is null"); return; @@ -624,7 +783,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe 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)) { @@ -700,7 +859,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe } intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { - appWidgetId + appWidgetId }); sendBroadcast(intent); @@ -710,10 +869,16 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { if (mFocusNoteDataItem != null) { - menu.setHeaderTitle(mFocusNoteDataItem.getSnippet()); - menu.add(0, MENU_FOLDER_VIEW, 0, R.string.menu_folder_view); - menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete); - menu.add(0, MENU_FOLDER_CHANGE_NAME, 0, R.string.menu_folder_change_name); + if(mFocusNoteDataItem.getParentId()==Notes.ID_TRASH_FOLER){ + menu.setHeaderTitle(mFocusNoteDataItem.getSnippet()); + menu.add(0, MENU_FOLDER_MOVE_OUT, 0, R.string.menu_folder_move_out); + menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete); + }else { + menu.setHeaderTitle(mFocusNoteDataItem.getSnippet()); + menu.add(0, MENU_FOLDER_VIEW, 0, R.string.menu_folder_view); + menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete); + menu.add(0, MENU_FOLDER_CHANGE_NAME, 0, R.string.menu_folder_change_name); + } } } }; @@ -732,31 +897,56 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe Log.e(TAG, "The long click data item is null"); return false; } - switch (item.getItemId()) { - case MENU_FOLDER_VIEW: - openFolder(mFocusNoteDataItem); - break; - case MENU_FOLDER_DELETE: - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(getString(R.string.alert_title_delete)); - builder.setIcon(android.R.drawable.ic_dialog_alert); - builder.setMessage(getString(R.string.alert_message_delete_folder)); - builder.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - deleteFolder(mFocusNoteDataItem.getId()); - } - }); - builder.setNegativeButton(android.R.string.cancel, null); - builder.show(); - break; - case MENU_FOLDER_CHANGE_NAME: - showCreateOrModifyFolderDialog(false); - break; - default: - break; + if(mFocusNoteDataItem.getParentId()==Notes.ID_TRASH_FOLER){ + switch (item.getItemId()) { + case MENU_FOLDER_MOVE_OUT: + HashSet ids = new HashSet(); + ids.add(mFocusNoteDataItem.getId()); + DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_ROOT_FOLDER); + break; + case MENU_FOLDER_DELETE: + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_folder)); + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + deleteFolder(mFocusNoteDataItem.getId()); + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show(); + break; + default: + break; + } + }else { + switch (item.getItemId()) { + case MENU_FOLDER_VIEW: + openFolder(mFocusNoteDataItem); + break; + case MENU_FOLDER_DELETE: + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_folder)); + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + deleteFolder(mFocusNoteDataItem.getId()); + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show(); + break; + case MENU_FOLDER_CHANGE_NAME: + showCreateOrModifyFolderDialog(false); + break; + default: + break; + } } - return true; } @@ -806,7 +996,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe break; } case R.id.menu_new_note: { - createNewNote(); +// createNewNote(); break; } case R.id.menu_search: @@ -867,7 +1057,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe } private boolean isSyncMode() { - return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0; + return true; } private void startPreferenceActivity() { @@ -918,9 +1108,9 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe } private void startQueryDestinationFolders() { - String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?"; + String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>? AND "+ NoteColumns.ID + "<>?"; selection = (mState == ListEditState.NOTE_LIST) ? selection: - "(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")"; + "(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")"; mBackgroundQueryHandler.startQuery(FOLDER_LIST_QUERY_TOKEN, null, @@ -930,7 +1120,8 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER), - String.valueOf(mCurrentFolderId) + String.valueOf(mCurrentFolderId), + String.valueOf(Notes.ID_TRASH_FOLER) }, NoteColumns.MODIFIED_DATE + " DESC"); } @@ -951,4 +1142,68 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe } return false; } + + + + public boolean supportFingerprint() { + if (Build.VERSION.SDK_INT < 23) { + Toast.makeText(this, "您的系统版本过低,不支持指纹功能", Toast.LENGTH_SHORT).show(); + return false; + } else { + KeyguardManager keyguardManager = getSystemService(KeyguardManager.class); + FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class); + if (!fingerprintManager.isHardwareDetected()) { + Toast.makeText(this, "您的手机不支持指纹功能", Toast.LENGTH_SHORT).show(); + return false; + } else if (!keyguardManager.isKeyguardSecure()) { + Toast.makeText(this, "您还未设置锁屏,请先设置锁屏并添加一个指纹", Toast.LENGTH_SHORT).show(); + return false; + } else if (!fingerprintManager.hasEnrolledFingerprints()) { + Toast.makeText(this, "您至少需要在系统设置中添加一个指纹", Toast.LENGTH_SHORT).show(); + return false; + } + } + return true; + } + + @TargetApi(23) + private void initKey() { + try { + keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); + KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(DEFAULT_KEY_NAME, + KeyProperties.PURPOSE_ENCRYPT | + KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + .setUserAuthenticationRequired(true) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7); + keyGenerator.init(builder.build()); + keyGenerator.generateKey(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @TargetApi(23) + private void initCipher() { + try { + SecretKey key = (SecretKey) keyStore.getKey(DEFAULT_KEY_NAME, null); + Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + + KeyProperties.BLOCK_MODE_CBC + "/" + + KeyProperties.ENCRYPTION_PADDING_PKCS7); + cipher.init(Cipher.ENCRYPT_MODE, key); + showFingerPrintDialog(cipher); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void showFingerPrintDialog(Cipher cipher) { + FingerprintDialogFragment fragment = new FingerprintDialogFragment(); + fragment.setCipher(cipher); + fragment.show(getFragmentManager(), "fingerprint"); + } + + } diff --git a/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java b/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java index 51c9cb9..d266beb 100644 --- a/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java +++ b/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java @@ -99,12 +99,33 @@ public class NotesListAdapter extends CursorAdapter { } else { itemSet.add(id); } + } } return itemSet; } + public HashSet getSelectedFolderIds() { + HashSet itemSet = new HashSet(); + for (Integer position : mSelectedIndex.keySet()) { + if (mSelectedIndex.get(position) == true) { + Cursor c = (Cursor) getItem(position); + if (c != null) { + NoteItemData item = new NoteItemData(mContext, c); + itemSet.add(item.getFolderId()); + /** + * Don't close cursor here, only the adapter could close it + */ + } else { + Log.e(TAG, "Invalid cursor"); + return null; + } + } + } + return itemSet; + } + public HashSet getSelectedWidget() { HashSet itemSet = new HashSet(); for (Integer position : mSelectedIndex.keySet()) { @@ -128,6 +149,28 @@ public class NotesListAdapter extends CursorAdapter { return itemSet; } + public boolean getHasLocked(){ + HashSet itemSet = new HashSet(); + for (Integer position : mSelectedIndex.keySet()) { + if (mSelectedIndex.get(position) == true) { + Cursor c = (Cursor) getItem(position); + if (c != null) { + NoteItemData item = new NoteItemData(mContext, c); + if(item.getIsLocked()){ + return true; + } + /** + * Don't close cursor here, only the adapter could close it + */ + } else { + Log.e(TAG, "Invalid cursor"); + return true; + } + } + } + return false; + } + public int getSelectedCount() { Collection values = mSelectedIndex.values(); if (null == values) { diff --git a/app/src/main/java/net/micode/notes/ui/NotesListItem.java b/app/src/main/java/net/micode/notes/ui/NotesListItem.java index 1221e80..6dd5157 100644 --- a/app/src/main/java/net/micode/notes/ui/NotesListItem.java +++ b/app/src/main/java/net/micode/notes/ui/NotesListItem.java @@ -82,7 +82,7 @@ public class NotesListItem extends LinearLayout { 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())); @@ -101,6 +101,11 @@ public class NotesListItem extends LinearLayout { private void setBackground(NoteItemData data) { int id = data.getBgColorId(); +// setBackgroundResource(R.color.user_query_highlight); +// setBackgroundColor(0xFF888888); +// setX(500); +// setWeightSum((float)1); +// setw if (data.getType() == Notes.TYPE_NOTE) { if (data.isSingle() || data.isOneFollowingFolder()) { setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id)); diff --git a/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java b/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java index 07c5f7e..bbb0492 100644 --- a/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java +++ b/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java @@ -144,7 +144,7 @@ public class NotesPreferenceActivity extends PreferenceActivity { } } else { 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; @@ -246,7 +246,7 @@ public class NotesPreferenceActivity extends PreferenceActivity { mHasAddedAccount = 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(); diff --git a/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java b/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java index ec6f819..2bdb5c2 100644 --- a/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java +++ b/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java @@ -34,9 +34,9 @@ import net.micode.notes.ui.NotesListActivity; public abstract class NoteWidgetProvider extends AppWidgetProvider { public static final String [] PROJECTION = new String [] { - NoteColumns.ID, - NoteColumns.BG_COLOR_ID, - NoteColumns.SNIPPET + NoteColumns.ID, + NoteColumns.BG_COLOR_ID, + NoteColumns.SNIPPET }; public static final int COLUMN_ID = 0; @@ -70,7 +70,7 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { } private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, - boolean privacyMode) { + boolean privacyMode) { for (int i = 0; i < appWidgetIds.length; i++) { if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { int bgId = ResourceParser.getDefaultBgId(context); diff --git a/local.properties b/local.properties index 502d540..cab809e 100644 --- a/local.properties +++ b/local.properties @@ -2,6 +2,7 @@ # as it contains information specific to your local configuration. # # Location of the SDK. This is only used by Gradle. -# -#Fri Feb 24 19:59:47 CST 2023 -sdk.dir=D\:\\Environment\\Android\\Sdk +# For customization when using a Version Control System, please read the +# header note. +#Wed Mar 08 18:43:32 CST 2023 +sdk.dir=D\:\\Environment\\Sdk