commit 8586e313b2a1c39b7a838c334a43833db60b39a1 Author: sonichy Date: Sun Oct 1 16:39:09 2023 +0800 first diff --git a/README.md b/README.md new file mode 100644 index 0000000..568b870 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# 记事本 \ No newline at end of file diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml new file mode 100644 index 0000000..e2eda7d --- /dev/null +++ b/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/java/com/hty/event/DBHelper.java b/main/java/com/hty/event/DBHelper.java new file mode 100644 index 0000000..b7bc046 --- /dev/null +++ b/main/java/com/hty/event/DBHelper.java @@ -0,0 +1,86 @@ +package com.hty.event; + +import java.io.File; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +public class DBHelper extends SQLiteOpenHelper { + public static final String filename = "event.db"; + public static final String DATABASE_NAME = MainActivity.dir + File.separator + filename; + private final static int VERSION = 1; + static String TableName = "event"; + private SQLiteDatabase db; + private static DBHelper mInstance = null; + + public DBHelper(Context context) { + super(context, DATABASE_NAME, null, VERSION); + } + + public static synchronized DBHelper getInstance(Context context) { + if (mInstance == null) { + mInstance = new DBHelper(context); + } + return mInstance; + } + + @Override + public void onCreate(SQLiteDatabase db) { + this.db = db; + db.execSQL("CREATE TABLE "+ TableName + " (_id INTEGER PRIMARY KEY , time INTEGER, location TEXT, event TEXT)"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + // db.execSQL("DROP TABLE IF EXISTS battery"); + // onCreate(db); + switch (newVersion) { + case 6: + break; + } + } + + public void insert(ContentValues values) { + db = getWritableDatabase(); + db.insert(TableName, null, values); + db.close(); + } + + public Cursor query(String s) { + db = getWritableDatabase(); + Cursor c; + if (s.equals("")) { + c = db.query(TableName, null, null, null, null, null, "time desc"); + } else { + c = db.query(TableName, null, "location LIKE '%" + s + "%' or event LIKE '%" + s + "%'", null, null, null, "time desc"); + } + return c; + } + + public Cursor query(long date_start, long date_end) { + db = getWritableDatabase(); + Cursor c; + if (date_start != date_end) + c = db.query(TableName, null, "time >= " + date_start + " and time <= " + (date_end + 24*60*60*1000), null, null, null, "time asc"); + else + c = db.query(TableName, null, "time >= " + date_start + " and time <= " + (date_start + 24*60*60*1000), null, null, null, "time asc"); + return c; + } + + public void del(String id) { + if (db == null) + db = getWritableDatabase(); + db.delete(TableName, "_id=?", new String[] { id }); + // Log.e("id", id + ""); + // db.ExecuteNonQuery(CommandType.Text, "VACUUM"); + } + + @Override + public void close() { + if (db != null) + db.close(); + } +} \ No newline at end of file diff --git a/main/java/com/hty/event/MainActivity.java b/main/java/com/hty/event/MainActivity.java new file mode 100644 index 0000000..561cfbc --- /dev/null +++ b/main/java/com/hty/event/MainActivity.java @@ -0,0 +1,615 @@ +package com.hty.event; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.SearchManager; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.DatePicker; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.SimpleCursorAdapter; +import android.widget.TextView; +import android.widget.TimePicker; +import android.widget.Toast; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.lang.reflect.Field; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class MainActivity extends Activity { + static File dir; + EditText editText_search; + ImageButton imageButton_clear; + ListView listView; + SimpleCursorAdapter adapter; + InputMethodManager IMM; + SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()); + SimpleDateFormat SDF_date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); + int position1 = 0; + String[] from = { "_id", "time", "location", "event" }; + int[] to = { R.id.textView_id, R.id.textView_time, R.id.textView_location, R.id.textView_event }; + SimpleCursorAdapter.ViewBinder viewBinder; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "HTY" + File.separator + "Event"; + dir = new File(path); + if (!dir.exists()) { + boolean b = dir.mkdirs(); + if (!b) + Toast.makeText(MainActivity.this, "创建文件夹 " + path + " 失败!", Toast.LENGTH_SHORT).show(); + } + setContentView(R.layout.activity_main); + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); + IMM = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); + + editText_search = (EditText) findViewById(R.id.editText_search); + editText_search.addTextChangedListener(new TextWatcher(){ + @Override + public void beforeTextChanged(CharSequence s, int start, int count,int after) { + } + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + @Override + public void afterTextChanged(Editable s) { + if (s.toString().equals("")) { + imageButton_clear.setVisibility(View.GONE); + } else { + imageButton_clear.setVisibility(View.VISIBLE); + } + search(s.toString()); + } + }); + + imageButton_clear = (ImageButton) findViewById(R.id.imageButton_clear); + imageButton_clear.setVisibility(View.GONE); + imageButton_clear.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + editText_search.setText(""); + } + }); + + listView = (ListView) findViewById(R.id.listView); + + viewBinder = new SimpleCursorAdapter.ViewBinder() { + public boolean setViewValue(View view, Cursor cursor, int columnIndex){ + //Log.e(Thread.currentThread().getStackTrace()[2] + "", view.toString() + columnIndex); + if (view.getId() == R.id.textView_time) { + Date date = new Date(cursor.getLong(columnIndex)); + ((TextView) view).setText(SDF.format(date)); + return true; + } + return false; + } + }; + + search(""); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + String[] sm = { "添加", "日期范围搜索", "分享数据库", "导出HTML", "导出CSV", "更新日志", "关于", "退出" }; + for (int i=0; i= date_start.getTime()) { + DBHelper helper = new DBHelper(MainActivity.this); + Cursor cursor = helper.query(date_start.getTime(), date_end.getTime()); + int count = cursor.getCount(); + if (date_end.getTime() > date_start.getTime()) + setTitle(SDF_date.format(date_start) + "到" + SDF_date.format(date_end) + "的事件" + count); + else + setTitle(SDF_date.format(date_start) + "的事件" + count); + adapter = new SimpleCursorAdapter(MainActivity.this, R.layout.item_event, cursor, from, to, 0); + adapter.setViewBinder(viewBinder); + listView.setAdapter(adapter); + try { //关闭 + field.set(dialog, true); + dialog.dismiss(); + } catch (Exception e) { + Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(getApplicationContext(), "结束日期比开始日期早!", Toast.LENGTH_SHORT).show(); + try { //设置dialog不可关闭 + field.set(dialog, false); + dialog.dismiss(); + } catch (Exception e) { + Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show(); + } + } + } + }); + builder1.setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Field field = null; + try { + //通过反射获取dialog中的私有属性mShowing + field = dialog.getClass().getSuperclass().getDeclaredField("mShowing"); + field.setAccessible(true);//设置该属性可以访问 + } catch (Exception ex) { + } + try { + field.set(dialog, true); + dialog.dismiss(); + } catch (Exception e) { + Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show(); + } + } + }); + builder1.create().show(); + break; + case 2: + File file = new File(DBHelper.DATABASE_NAME); + if (file.exists()) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_SEND); + intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); + intent.setType("*/*"); + startActivity(Intent.createChooser(intent, "分享 " + DBHelper.filename)); + } else { + Toast.makeText(getApplicationContext(), "数据库文件不存在", Toast.LENGTH_SHORT).show(); + } + break; + case 3: + String s = "\n\n\n事件\n\n\n\n

事件" + adapter.getCount() + "

\n\n\n"; + for (int i=0; i\n"; + } + s += "
时间地点事件
" + textView_time.getText().toString() + "" + textView_location.getText().toString() + "" + textView_event.getText().toString() + "
\n\n"; + String filename = "event.htm"; + if (!editText_search.getText().toString().equals("")) + filename = editText_search.getText().toString() + ".htm"; + writeFile(filename, s); + break; + case 4: + s = ""; + for (int i=0; i adapterView, View view, int position, long id) { + IMM.hideSoftInputFromWindow(editText_search.getWindowToken(), 0); + final String stime = ((TextView) view.findViewById(R.id.textView_time)).getText().toString(); + final String location = ((TextView) view.findViewById(R.id.textView_location)).getText().toString(); + final String event = ((TextView) view.findViewById(R.id.textView_event)).getText().toString(); + final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setIcon(android.R.drawable.ic_menu_info_details); + String title = ""; + Date date; + try { + date = SDF.parse(stime); + title = DayDiff(date); + } catch (Exception e) { + Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show(); + } + builder.setTitle(title); + builder.setMessage(stime + "\n" + location + "\n" + event); + builder.setPositiveButton("复制", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ClipboardManager CM = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clipData = ClipData.newPlainText("text", stime + "\n" + location + "\n" + event); + CM.setPrimaryClip(clipData); + Toast.makeText(getApplicationContext(), "内容已复制", Toast.LENGTH_SHORT).show(); + dialog.dismiss(); + } + }); + builder.setNegativeButton("搜索", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this); + builder1.setIcon(android.R.drawable.ic_menu_search); + builder1.setTitle("搜索"); + final EditText editText = new EditText(MainActivity.this); + editText.setText(event); + builder1.setView(editText); + builder1.setPositiveButton("搜索", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + IMM.hideSoftInputFromWindow(editText.getWindowToken(), 0); + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_WEB_SEARCH); + intent.putExtra(SearchManager.QUERY, editText.getText().toString()); + startActivity(intent); + } + }); + builder1.create().show(); + } + }); + builder.setNeutralButton("分享", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_SEND); + intent.putExtra(Intent.EXTRA_TEXT, stime + "\n" + location + "\n" + event); + intent.setType("text/plain"); + startActivity(Intent.createChooser(intent, "分享到")); + dialog.dismiss(); + } + }); + builder.create().show(); + } + }); + listView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { + @Override + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { + //AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; + //String title = ((TextView) info.targetView.findViewById(R.id.title)).getText().toString(); + //menu.setHeaderTitle(title); + menu.add(0, 0, 0, "复制"); + menu.add(0, 1, 1, "分享"); + menu.add(0, 2, 2, "修改"); + menu.add(0, 3, 3, "删除"); + } + }); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); + final String sid = ((TextView) menuInfo.targetView.findViewById(R.id.textView_id)).getText().toString(); + String stime = ((TextView) menuInfo.targetView.findViewById(R.id.textView_time)).getText().toString(); + String location = ((TextView) menuInfo.targetView.findViewById(R.id.textView_location)).getText().toString(); + String event = ((TextView) menuInfo.targetView.findViewById(R.id.textView_event)).getText().toString(); + position1 = menuInfo.position; + switch (item.getItemId()) { + case 0: + ClipboardManager CM = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); + CM.setPrimaryClip(ClipData.newPlainText("text", stime + "\n" + location + "\n" + event)); + Toast.makeText(getApplicationContext(), "内容已复制", Toast.LENGTH_SHORT).show(); + break; + case 1: + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_SEND); + intent.putExtra(Intent.EXTRA_TEXT, stime + "\n" + location + "\n" + event); + intent.setType("text/plain"); + startActivity(Intent.createChooser(intent, "分享到")); + break; + case 2: + LayoutInflater layoutInflater = LayoutInflater.from(this); + View view = layoutInflater.inflate(R.layout.event_edit, null); + final EditText editText_location = (EditText) view.findViewById(R.id.editText_location); + final EditText editText_event = (EditText) view.findViewById(R.id.editText_event); + final DatePicker datePicker = (DatePicker) view.findViewById(R.id.datePicker); + final TimePicker timePicker = (TimePicker) view.findViewById(R.id.timePicker); + timePicker.setIs24HourView(true); + Date date; + try { + date = SDF.parse(stime); + datePicker.init(date.getYear() + 1900, date.getMonth(), date.getDate(), null); + timePicker.setCurrentHour(date.getHours()); + timePicker.setCurrentMinute(date.getMinutes()); + } catch (Exception e){ + Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT); + } + editText_location.setText(location); + editText_event.setText(event); + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setIcon(android.R.drawable.ic_menu_edit); + builder.setTitle("修改事件"); + builder.setView(view); + builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String location = editText_location.getText().toString(); + String event = editText_event.getText().toString(); + Field field = null; + try { + //通过反射获取dialog中的私有属性mShowing + field = dialog.getClass().getSuperclass().getDeclaredField("mShowing"); + field.setAccessible(true);//设置该属性可以访问 + } catch (Exception ex) { + + } + if (!location.equals("") && !event.equals("")) { + int year = datePicker.getYear(); + int month = datePicker.getMonth(); + int day = datePicker.getDayOfMonth(); + int hour = timePicker.getCurrentHour(); + int minute = timePicker.getCurrentMinute(); + Date date = new Date(year - 1900, month, day, hour, minute); + DBHelper dbHelper = new DBHelper(getApplicationContext()); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put("time", date.getTime()); + values.put("location", location); + values.put("event", event); + db.update(DBHelper.TableName, values, "_id = " + sid, null); + search(editText_search.getText().toString()); + listView.setSelection(position1); + IMM.hideSoftInputFromWindow(editText_location.getWindowToken(), 0); + try { + //关闭 + field.set(dialog, true); + dialog.dismiss(); + } catch (Exception ex) { + } + } else { + if (location.equals("")){ + editText_location.setError("地点不能为空!"); + } + if (event.equals("")){ + editText_event.setError("事件不能为空!"); + } + try { + //设置dialog不可关闭 + field.set(dialog, false); + dialog.dismiss(); + } catch (Exception ex) { + } + } + } + }); + builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Field field = null; + try { + //通过反射获取dialog中的私有属性mShowing + field = dialog.getClass().getSuperclass().getDeclaredField("mShowing"); + field.setAccessible(true);//设置该属性可以访问 + } catch (Exception ex) { + } + try { + field.set(dialog, true); + dialog.dismiss(); + } catch (Exception ex) { + } + } + }); + builder.create().show(); + break; + case 3: + new AlertDialog.Builder(MainActivity.this) + .setIcon(android.R.drawable.stat_sys_warning) + .setTitle("删除操作") + .setMessage("此步骤不可还原,确定删除" + sid + "?\n" + stime + "\n" + location + "\n" + event) + .setPositiveButton("是", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + DBHelper dbHelper = new DBHelper(getApplicationContext()); + dbHelper.del(sid); + search(editText_search.getText().toString()); + listView.setSelection(position1); + } + }) + .setNegativeButton("否", null) + .show(); + break; + } + return true; + } + + void writeFile(String filename, String s) { + File file = new File(MainActivity.dir, filename); + try { + BufferedWriter BW = new BufferedWriter(new FileWriter(file, false)); //false覆盖 + if(filename.endsWith(".csv")){ + BW.write('\ufeff'); // Excel通过文件的BOM头来判断文件编码 + BW.flush(); + } + BW.write(s); + BW.flush(); + Toast.makeText(getApplicationContext(), "写文件 " + MainActivity.dir + File.separator + filename + " 成功", Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + Log.e(Thread.currentThread().getStackTrace()[2] + "", e.toString()); + Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show(); + } + } + + String DayDiff(Date date) { + String s = ""; + Date date1 = new Date(); + long ms = Math.abs(date1.getTime() - date.getTime()); + long d = ms / 1000 / 60 / 60 / 24; + long y = d / 365; + if (y > 0) { + s += y + "年"; + d = d - y * 365; + } + long m = d / 30; + if (m > 0) { + s += m + "月"; + d = d - m * 30; + } + if (d > 0) { + s += d + "天"; + } + if (date.before(date1)) + s += "前"; + else + s += "后"; + if (m==0 && y==0 && d == 0) { + s = "一天内"; + } + return s; + } + +} \ No newline at end of file diff --git a/main/res/layout/activity_main.xml b/main/res/layout/activity_main.xml new file mode 100644 index 0000000..ecf86ee --- /dev/null +++ b/main/res/layout/activity_main.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/date_range.xml b/main/res/layout/date_range.xml new file mode 100644 index 0000000..beaac47 --- /dev/null +++ b/main/res/layout/date_range.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/event_edit.xml b/main/res/layout/event_edit.xml new file mode 100644 index 0000000..db6fd49 --- /dev/null +++ b/main/res/layout/event_edit.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/item_event.xml b/main/res/layout/item_event.xml new file mode 100644 index 0000000..fd51d41 --- /dev/null +++ b/main/res/layout/item_event.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/main/res/mipmap-hdpi/ic_launcher.png b/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..bea9a91 Binary files /dev/null and b/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/main/res/mipmap-mdpi/ic_launcher.png b/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..9b72c24 Binary files /dev/null and b/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/main/res/mipmap-xhdpi/ic_launcher.png b/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..05b354e Binary files /dev/null and b/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/main/res/mipmap-xxhdpi/ic_launcher.png b/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..3e84ef8 Binary files /dev/null and b/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/main/res/mipmap-xxxhdpi/ic_launcher.png b/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..5f98e9c Binary files /dev/null and b/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml new file mode 100644 index 0000000..a49e00f --- /dev/null +++ b/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + 事件 +